Добавление события Postbuild в проект
Когда я генерирую проект C# (csproj
файл), а затем скомпилировать его, msbuild
как-то не распознает переменные $(ConfigurationName)
а также $(ProjectDir)
(и другие) в событии до и после сборки.
Когда я вручную перемещаю конфигурацию событий до и после сборки в сгенерированную .csproj
далее, затем msbuild правильно распознает эти переменные.
Добавление builddevent к проекту - это последнее, что я делаю перед сохранением проекта.
Вот как я добавляю это:
using Microsoft.Build.Construction;
using Microsoft.Build.Evaluation;
private const string PreBuildEventFixture = "PreBuildEvent";
private const string PostBuildEventFixture = "PostBuildEvent";
private const string PreBuildEvent = "attrib -R \"$(ProjectDir)app.config\"";
private const string PostBuildEvent = "copy \"$(ProjectDir)app.config.$(ConfigurationName)\" \"$(TargetDir)\\$(ProjectName).dll.config\" \r\n attrib -R \"$(ProjectPath)\"";
public void AddBuildEvents(Project project)
{
ProjectPropertyGroupElement propertyGroupElement = project.Xml.AddPropertyGroup();
propertyGroupElement.AddProperty(PreBuildEventFixture, PreBuildEvent);
propertyGroupElement.AddProperty(PostBuildEventFixture, PostBuildEvent);
}
Я получаю ошибку при запуске сгенерированного проекта через msbuild:
The command "copy "app.config." "\.dll.config"" exited with code 1
Когда я потом вручную редактирую .csproj
файл (с помощью блокнота или другого текстового редактора), вырезайте событие до и после сборки и вставьте его под <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
элемент, то msbuild строит сгенерированный .csproj
файл в порядке.
Каков наилучший способ добавить события сборки в .csproj
файл, так что он заканчивается после Import
элемент в результате XML
?
Видимо, мой нынешний способ использования [ProjectPropertyGroupElement][1]
запросив его у AddPropertyGroup свойства Xml объекта Microsoft.Build.Evaluation.Project - нет.
Пример проекта:
using System.IO;
using Microsoft.Build.Construction;
using Microsoft.Build.Evaluation;
class Program
{
private const string PreBuildEventFixture = "PreBuildEvent";
private const string PostBuildEventFixture = "PostBuildEvent";
private const string PreBuildEvent = "attrib -R \"$(ProjectDir)app.config\"";
private const string PostBuildEvent = "copy \"$(ProjectDir)app.config.$(ConfigurationName)\" \"$(TargetDir)\\$(ProjectName).exe.config\" \r\n attrib -R \"$(ProjectPath)\"";
private const string ProjectFile = @"C:\test\TestProject\TestProject.csproj";
static void Main(string[] args)
{
if (!File.Exists(ProjectFile))
throw new FileNotFoundException("ProjectFile not found");
ProjectCollection collection = new ProjectCollection();
Project project = collection.LoadProject(ProjectFile);
ProjectPropertyGroupElement propertyGroupElement = project.Xml.AddPropertyGroup();
propertyGroupElement.AddProperty(PreBuildEventFixture, PreBuildEvent);
propertyGroupElement.AddProperty(PostBuildEventFixture, PostBuildEvent);
project.Save();
collection.UnloadAllProjects();
}
}
Действия по воспроизведению
- Создать новый проект
- Вручную добавьте файл app.config.debug, который должен отличаться от файла app.debug
- Добавьте postbuildevent:
copy "$(ProjectDir)app.config.$(ConfigurationName)" "$(TargetDir)\$(ProjectName).exe.config
- Смотрите, что сборка проекта и правильный файл конфигурации применены
- Удалите события до и после сборки с помощью блокнота (чтобы не оставлять следов)
- Запустите пример проекта
- Перезагрузите и соберите созданный вами проект.
- Окно вывода теперь скажет
The system cannot find the file specified.
2 ответа
var propertyGroupElement = project.Xml.CreatePropertyGroupElement();
project.Xml.AppendChild(propertyGroupElement);
propertyGroupElement.AddProperty(PreBuildEventFixture, PreBuildEvent);
propertyGroupElement.AddProperty(PostBuildEventFixture, PostBuildEvent);
Связанные с проектом макросы не анализируются, если они добавляются до фактического создания проекта (создание проекта включает добавление ссылок). Вместо того, чтобы использовать $(ProjectName)
путь может быть построен с использованием переменных решения (которые уже существуют), например:
copy "$(SolutionDir)ProjectName\app.config.$(Configuration)" "$(SolutionDir)ProjectName\bin\$(Configuration)\ProjectName.dll.config"
Обратите внимание, что ProjectName - это фактическое имя проекта, жестко закодированное, но поскольку вы генерируете проект, его легко добавить.