Как программно включить файл в мой проект?

Фон

Я делаю вспомогательное приложение, которое переформатирует некоторые файлы кода и создает новые файлы кода, которые должны быть добавлены в мой другой проект, чтобы я мог сразу использовать новый код, но у меня серьезные проблемы с добавлением этого нового файла кода в мой проект автоматически. Кстати, это в 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 для получения дополнительной информации.

Другие вопросы по тегам