Подтвердить что ты не робот

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

Фон

Я создаю вспомогательное приложение, которое переформатирует некоторые файлы кода и создает новые файлы кода, которые должны быть добавлены в мой другой проект, поэтому я мог бы сразу использовать новый код, но у меня возникают серьезные проблемы с добавлением новый файл кода в мой проект автоматически. Кстати, это в С#, а вспомогательное приложение - WinForms.

Неудачные попытки

Этот вопрос только ответ имеет два способа сделать это, но я не мог заставить никого из них работать. С первым я не могу найти сборку Microsoft.Build для ссылки, а в другой явно недостаточно аргументов для командной строки.

Вопрос

Как программно включить файл в проект без использования сторонних приложений?

В принципе, я ищу эквивалент этого:

... Но с использованием кода.

Требования

Это функции, которые, как я полагаю, должны предложить:

  • Выберите решение, в котором есть проект, который мы добавляем в файл
  • Выберите проект, в который должен быть добавлен файл
  • Выберите каталог в проекте
  • И, конечно же, файл, который мы добавляем

Прогресс

С помощью user @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, и в этом случае файл будет помещен туда. Таким образом, в основном файл будет помещен в самую глубокую цепочку папок, найденную в исходном пути к файлу, идущему к корневой папке.

4b9b3361

Ответ 1

Это сработало для того, чтобы просто добавить его в 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();

Ответ 2

В качестве дополнения к ответу Boot750 (сначала предлагался в качестве правки для его ответа, но повторно опубликован как самостоятельный)

Следует отметить, что вызов 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);

Ответ 3

Самый простой способ сделать это - изменить файл проекта. Поскольку это всего лишь файл MSBUILD, VS подберет это изменение и предложит перезагрузить проект. Загрузите файл проекта в формате XML и найдите первый <Compile Include="Name of File.cs" />. Вставьте новый <Compile Include="NewFile.CS" /> и сделанный.

В качестве другого варианта вы можете удалить все теги <Compile> и заменить их на <Compile Include="*.cs" />

Ответ 4

Просто добавьте ответ от @caius-jard

Как только проект находится в GlobalProjectCollection, он хранится в памяти и не отражает никаких изменений вручную, внесенных в проект. Это включает в себя обновление файла .csproj и использование VS для удаления сгенерированных файлов.

Если вы удалите сгенерированный файл и снова запустите код, проект будет обновлен, чтобы содержать 2 сгенерированного файла. Используйте функцию ReevaluateIfNecessary() для обновления экземпляра проекта до использования следующим образом:

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();