Question

I have begun working directly with the MSBuild API in order to extend our build process and increase the flexibility.

I have successfully automated the entire process of building our project, but not without a few "gotchas". Due to the extreme lack of documentation and usage examples on the MSBuild API I was forced to endure some lengthy debugging sessions.

Hopefully the details I outline here will help others looking to integrate directly with the MSBuild API.

Compiling C# code was extremely easy, but once I tried to use the MSBuild API to compile some of our legacy VC++ projects, the process really hit a snag.

Here is a code sample of my compiler wrapper:

            globalProperties["Configuration"] = CommonLibrary.BuildMode.Release.ToString();

            //add the compiler variables from the specific project to the properties dictionary
            if (compilerVariables != null)
            {
                foreach(var kvp in compilerVariables)
                {
                    globalProperties.Add(kvp.Key, kvp.Value);
                }
            }

            //set up a build request to be sent to MSBuild
            var request = new BuildRequestData(project.SolutionFile.FullName, globalProperties, null, new string[] { "Rebuild" }, null);

            //configure settings for MSBuild specifically
            var buildParams = new BuildParameters();
            buildParams.EnableNodeReuse = true;

            buildParams.Loggers = new List<Microsoft.Build.Framework.ILogger>() 
            {
                buildLogger,
                fileLogger
            };

            //instantiate the BuildManager, kick off the build, and get the results
            BuildManager buildManager = new BuildManager();
            project.BuildResult = buildManager.Build(buildParams, request);

Another aspect of this process involves the .props file that VC++ uses in order to get the INCLUDE (and other paths) needed for the linker. This .props file lives in C:\Users\%BUILDACCOUNT%\AppData\Local\Microsoft\MSBuild\v4.0\Microsoft.Cpp.%TargetPlatform%.user.props

Now comes the interesting part.

When I run this code against a C# project/solution, everything works fine. That is because the .props file plays no part in C# compilation (Include paths are stored as the .csproj level).

However, when running against a solution that contains VC++ projects this method falls completely on it's face. The reason is because it is unable to resolve the INCLUDE paths that are presumably located within the props file (at the location detailed above).

Another interesting tid-bit is that I can replicate the arguments to MSBuild directly from the command line, and the build succeeds fine. This really puzzled me... so I turned on the verbose diagnostics and ran my test-case again.

Interesting information from logs (logs have been trimmed):

  1. Building from the command line

USERDOMAIN = [REDACTED]

USERNAME = MyUserName

LOCALAPPDATA = C:\Users\MyUserName\AppData\Local

  1. Building from the API

USERDOMAIN = [REDACTED]

USERNAME = BUILDMACHINE$

LOCALAPPDATA = C:\Windows\system32\config\systemprofile\AppData\Local

As you can see, it seems that the current identity when building from the CLI is correctly set to my identity. However, building from the API sets the current identity to the local system. This leads to the INCLUDE path not being correctly set for API builds, because the props file with that information is not available at the expected location (C:\Windows\system32\config\systemprofile\AppData\Local).

My workaround which seems to be working so far is to actually move all the props files from the AppData Location to the directory that the API is expecting it in. I do not think that this is the expected behavior... it doesn't seem very intelligible.

Additional notes:

  • This code is being hosted on IIS, within an application pool running as "MyUserName" (not the local system).
  • I have been able to reproduce this issue on two different machines both running Windows Server 2008

Either I am doing something incorrectly, or the MSBuild API is doing something incorrectly? Any input as to what the official means of getting the props file recognized by the MSBuild API would be extremely helpful.

Thanks.

Was it helpful?

Solution

Ok, I have figured out what the problem is.

The problem has nothing to do with MSBuild. Instead, it is related to my IIS configuration.

Although my application pool was running under the identity of my build account, I had the option "Load User Profile = False", which caused the user profile to default to the LocalSystem.

Switching this setting to "Load User Profile = True" fixed this issue, and MSBuild began accessing the correct .props file.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top