Как программно включить файл в мой проект?
Фон
Я делаю вспомогательное приложение, которое переформатирует некоторые файлы кода и создает новые файлы кода, которые должны быть добавлены в мой другой проект, чтобы я мог сразу использовать новый код, но у меня серьезные проблемы с добавлением этого нового файла кода в мой проект автоматически. Кстати, это в C#, а вспомогательное приложение - WinForms.
Неудачные попытки
Единственный ответ на этот вопрос имеет два способа сделать это, но я не мог заставить ни один из них работать. С первым не могу найти Microsoft.Build
сборка для ссылки, а в другом явно не хватает аргументов для командной строки.
Вопрос
Как программно включить файл в проект без использования сторонних приложений?
По сути, я ищу эквивалент этого:
... но сделано с помощью кода.
Требования
Я полагаю, что это решение должно предложить следующие функции:
- Выберите решение, в котором есть проект, к которому мы добавляем файл
- Выберите проект, в который будет добавлен файл
- Выберите каталог в проекте
- И, конечно же, файл, который мы добавляем
Прогресс
С помощью пользователя @psubsee2003 я смог найти Microsoft.Build.dll
файл в C:\Windows\Microsoft.NET\Framework\v4.0.30319
папку на моем компьютере и успешно импортировать ее, изменив целевую инфраструктуру моего проекта на версию 4 Полный профиль, а не профиль клиента по умолчанию.
И я нашел, как использовать AddItem
метод:
var p = new Microsoft.Build.Evaluation.Project(@"C:\projects\MyProject.csproj");
p.AddItem("Compile", @"C:\folder\file.cs");
p.Save();
Файл появится в корневой папке проекта, если в проекте уже не было папки с именем folder
, в этом случае файл будет размещен там. Таким образом, в основном файл будет помещен в самую глубокую цепочку папок, найденную в пути исходного файла, идущем к корневой папке.
5 ответов
Это сработало для меня, просто добавив его в ProjectFolder, а также добавив папку программным способом, как это.
var p = new Microsoft.Build.Evaluation.Project(@"C:\projects\BabDb\test\test.csproj");
p.AddItem("Folder", @"C:\projects\BabDb\test\test2");
p.AddItem("Compile", @"C:\projects\BabDb\test\test2\Class1.cs");
p.Save();
В качестве дополнения к ответу Boot750 (сначала его предложили в качестве правки к его ответу, но, похоже, несколько недальновидных рецензентов подумали, что я разговаривал с Boot750, когда фактически принимал его направление общения с OP):
Вы должны отметить, что звонок new Microsoft.Build.Evaluation.Project(path)
фактически вызывает загрузку проекта в глобальный кеш, поддерживаемый Microsoft.Build.Evaluation
сборка. призвание new Project(path)
снова с тем же путем, без выгрузки его из глобальной коллекции, сначала / перезапуск приложения вызовет исключение, подобное:
Эквивалентный проект (проект с той же глобальной версией свойств и инструментов) уже присутствует в коллекции проектов с путем "YOUR_PATH". Чтобы загрузить эквивалент в эту коллекцию проектов, сначала выгрузите этот проект.
даже если переменная p
вышел за рамки.
Следовательно, вам может потребоваться принять шаблон более похожий на этот, если вы планируете использовать шаблон Load/AddItem/Save несколько раз:
var p =
Microsoft.Build.Evaluation
.ProjectCollection.GlobalProjectCollection
.LoadedProjects.FirstOrDefault(pr => pr.FullPath == projFilePath);
if (p == null)
p = new Microsoft.Build.Evaluation.Project(projFilePath);
Просто чтобы добавить к ответу @ Caius-Jard
Когда проект находится в коллекции GlobalProjectCollection, он сохраняется в памяти и не отражает никаких изменений, внесенных в проект вручную. Это включает в себя обновление файла.csproj и использование VS для удаления сгенерированных файлов.
Если вы удалите сгенерированный файл и снова запустите код, проект обновится и будет содержать 2 сгенерированных файла. Используйте функцию ReevaluateIfNeeded (), чтобы обновить экземпляр проекта перед использованием следующим образом:
var p = Microsoft.Build.Evaluation
.ProjectCollection.GlobalProjectCollection
.LoadedProjects.FirstOrDefault(pr => pr.FullPath == projFilePath);
if (p == null)
p = new Microsoft.Build.Evaluation.Project(projFilePath);
// Update instance of project
p.ReevaluateIfNecessary();
// Check folder is not already in the project
var folderLoc = @"C:\projects\BabDb\test\test2";
if(p.Items.FirstOrDefault(i => i.EvaluatedInclude == folderLoc) == null)
p.AddItem("Folder", folderLoc);
// Check file is not already in the project
var fileLoc = @"C:\projects\BabDb\test\test2\Class1.cs";
if(p.Items.FirstOrDefault(i => i.EvaluatedInclude == fileLoc) == null)
p.AddItem("Compile", fileLoc);
p.Save();
Самый простой способ сделать это - изменить файл проекта. Поскольку это всего лишь файл MSBUILD, VS примет изменения и предложит перезагрузить проект. Загрузите файл проекта в виде XML и найдите первый <Compile Include="Name of File.cs" />
, Вставьте новый <Compile Include="NewFile.CS" />
и вы сделали.
В качестве другого варианта вы можете удалить все <Compile>
теги и заменить их <Compile Include="*.cs" />
Я знаю, что это старый пост. Однако мне понадобился этот вариант, и я не нашел подходящего, как мне хотелось бы. Итак, я разработал расширение VS с расширенными функциями. Вы можете установить типы файлов, а затем выбрать список каталогов проектов, файлы которых будут загружаться в проект после их создания.
Вы можете использовать текстовые шаблоны T4. См. http://msdn.microsoft.com/en-us/library/vstudio/bb126445(v=vs.100).aspx для получения дополнительной информации.