1

I am looking for a way to prevent Visual Studio from reflecting project properties changes onto *.csproj files. I want to set properties only for single build action, then they should be discarded.

I am using EnvDTE automation object in my Visual Studio plugin. Below is my example code that sets (or changes) "UseHostCompilerIfAvailable" property to "false" for specific configuration and platform of a project that is about to be built. Build is initiated from Visual Studio UI.

Somewhere in the build initialization process Visual Studio writes all project properties changes to project files, that is what I am trying to prevent.

dte.Events.BuildEvents.OnBuildProjConfigBegin += BuildEvents_OnBuildProjConfigBegin;
...
private void BuildEvents_OnBuildProjConfigBegin(string Project, string ProjectConfig, string Platform, string SolutionConfig)
{
    ThreadHelper.ThrowIfNotOnUIThread();
    IVsSolution solution = (IVsSolution)this.GetService(typeof(SVsSolution));
    solution.GetProjectOfUniqueName(Project, out IVsHierarchy hier);
    IVsBuildPropertyStorage storage = hier as IVsBuildPropertyStorage;
    storage.SetPropertyValue("UseHostCompilerIfAvailable", $"{ProjectConfig}|{Platform}", (uint)Microsoft.VisualStudio.Shell.Interop._PersistStorageType.PST_PROJECT_FILE, "false");
}

I know that I can save property changes and revert them after build is done or I can cache project files and roll them back in the end, but these approaches have their possible bad side effects. I would be very glad to even get some ideas in which direction I should look at.

3 Answers 3

1

Why you have to do it programmatically? Maybe you can try Directory.build.props file.

Put it in solution folder to customize your build without modifying the project file.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for suggestion, I actually already thought about Directory.Build.props, but user might already have it. I am developing plugin, this plugin is not allowed to change solution structure in any way, it has do all its operations as if it does not exist. Once turned off everything should be kept as before.
0

From your question it seems to me you have to deal with a problem which is not covered by VS default plugin SDK approach.

In such case you may consider trying to hook NtCreateProcess in VS to get the moment MSBuild you need created.

NtCreateProcess allow to set suspend flag. MSBuild created in suspended state then. This moment allow you to make your changes to that process. If you have your custom loader then consider using it in the hook instead of calling native NtCreateProcess.

Inside injected library do hooks for accessing that properties you need. Ideally these should be just some registry keys. But if it is within XML in FS file then it might be some other high level API for accessing XML properties.

NtCreateProcess inside that MSBuild processes of your interest also need to be hooked same way to passthrough this logic to all child process to make this more robust solution.

1 Comment

Thanks for suggestion. I actually also attempted to use managed hooks as MSBuild is developed using C#. This whole build system is quite fragile and complex, I was hoping to get some fresh ideas and simple solutions. Unfortunately looks like hooks are the way to go.
0

As an alternative to Directory.Build.props, did you look at dropping an ImportBefore/ImportAfter targets file in the directory pointed to by MSBuildUserExtensionsPath instead? Any files in that directory will be automatically included in the build.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.