Why is the 64-bit MSBuild loading 32-bit extensions? - msbuild

I'm attempting to build a project using MSBuild (v4.0) on a 64-bit machine. For some reason, MSBuild is attempting to load a 32-bit extension, and I cannot figure out why. I've reduced the problem to the smallest set in order to demonstrate the issue.
Using the following MSBuild project file:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<Target Name="test">
<Message Text="bin path: $(MSBuildBinPath)" />
<Message Text="extensions path: $(MSBuildExtensionsPath)" />
<Message Text="extensions path (x86): $(MSBuildExtensionsPath32)" />
<Message Text="extensions path (x64): $(MSBuildExtensionsPath64)" />
</Target>
</Project>
I get this output:
Microsoft (R) Build Engine Version 4.0.30319.1
[Microsoft .NET Framework, Version 4.0.30319.1]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 8/27/2010 9:56:35 AM.
Project "D:\5\test.proj" on node 1 (default targets).
test:
bin path: C:\Windows\Microsoft.NET\Framework64\v4.0.30319
extensions path: C:\Program Files (x86)\MSBuild
extensions path (x86): C:\Program Files (x86)\MSBuild
extensions path (x64): C:\Program Files\MSBuild
Done Building Project "D:\5\test.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.03
MSBuild obviously knows about the 32bit and 64bit extensions path, and from the binary path it seems clear that I'm running the 64-bit MSBuild.exe, but for some reason it believes that extensions should be loaded from Program Files (x86) instead of Program Files. This is causing me trouble, as I have an extension that I need loaded, that MUST be loaded correctly in a 32bit/64bit process, and it will not load (MSBuild is attempting to load the 32bit version in a 64bit process).
Why?

I filed a bug on Microsoft Connect, and it was closed as "By Design", with this explanation:
You're exactly right -- this has changed, and strictly speaking, it's wrong now. However, this was a conscious decision. The reason it was changed was that very many extensions (such as .targets files) installed by other products are only installed in the 32 bit program files location. They did not anticipate 64 bit scenarios, but generally would work just fine in 64 bit MSBuild. When a user runs 64 bit MSBuild, which is quite common now because it's the default for Team Build 2010, MSBuildExtensionsPath would have in the past resolved to the 64 bit Program Files as you expect. However this meant that all those .targets files were not longer found and the build failed. It was not practical to get all those products to fix their setup authoring, especially since it had already shipped to customers. So we made the change to make MSBuildExetnsionsPath always point to the 32 bit location. Almost nobody seems to really want the 64 bit location, and those people can change to MSBuildExtensionsPath64. It was really a question of the least bad option here.
I accept the evidence, but I disagree with the conclusion. I believe that authors of broken installers deserve to have their extensions not work on 64-bit machines.

Related

Find out the "Bit"ness of the current OS in MSBuild

I have a build script that needs to hard code a path to an executable. The path is:
C:\Program Files\Microsoft Visual Studio 9.0\SmartDevices\SDK\SDKTools\cabwiz.exe
This has worked fine, but now I am running on a 64 bit OS (but my coworker and build server are on 32 bit still).
I need the path to be this for me:
C:\Program Files (x86)\Microsoft Visual Studio 9.0\SmartDevices\SDK\SDKTools\cabwiz.exe
But use the normal path for the others.
Here is how I set it up:
<PropertyGroup>
<CabWiz>"C:\Program Files\Microsoft Visual Studio 9.0\SmartDevices\SDK\SDKTools\cabwiz.exe"</CabWiz>
</PropertyGroup>
Is there a condition I can put on that so that I can set it if the OS (not the current build configuration) is 64 bit?
There is a registry key that will tell you the bit-edness of the current OS. Here are the properties I use in my MSBuild files:
<PropertyGroup>
<MachineProcessorArchitecture>$(registry:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment#PROCESSOR_ARCHITECTURE)</MachineProcessorArchitecture>
<Is32Bit>False</Is32Bit>
<Is32Bit Condition="'$(MachineProcessorArchitecture)' == 'x86'">True</Is32Bit>
<Is64Bit>False</Is64Bit>
<Is64Bit Condition="'$(MachineProcessorArchitecture)' == 'AMD64'">True</Is64Bit>
</PropertyGroup>
You're using the bitness to try and guess the correct Program Files folder, but there's no guarantee that it's on the C drive, or even called "Program Files". You would be better using the $(MSBuildProgramFiles32) property (in MSBuild 4.0).
On a 64-bit OS, the following variables are defined:
ProgramFiles=C:\Program Files
ProgramFiles(x86)=C:\Program Files (x86)
So just test for ProgramFiles(x86) and if it's empty, use ProgramFiles.
If you're always running the 32-bit version of MSBuild, regardless of the platform, then it's easy: just substitute '$(ProgramFiles)' for 'C:\Program Files'. Whether on a 32-bit or 64-bit OS, '$(ProgramFiles)' should expand to the correct folder location (the location of all 32-bit programs).
If you're running the 64-bit version of MSBuild on 64-bit platforms (which is unlikely), then it gets a bit trickier. The '%ProgramFiles(x86)%' environment variable would seem to be what you want, but good luck dealing with those parentheses. Easier would probably be to use the '%PROCESSOR_ARCHITECTURE%' environment variable in a condition.

How do I specify the platform for MSBuild?

I am trying to use MSBuild to build a solution with a specified target platform (I need both binaries, x86 and x64). This is how I tried it:
C:\WINDOWS\Microsoft.NET\Framework\v3.5>MsBuild SolutionPath\Solution.sln /t:Rebuild /p:Configuration=Release /p:Platform="x86"
However the build always fails if the platform is different from "Any CPU". What am I doing wrong?
This is the while output MSBuild prints:
C:\WINDOWS\Microsoft.NET\Framework\v3.5>MsBuild
SolutionPath\Solution.sln /t:Rebuild
/p:Configuration=Release
/p:Platform="x86" Microsoft (R) Build
Engine Version 3.5.30729.1 [Microsoft
.NET Framework, Version
2.0.50727.3082] Copyright (C) Microsoft Corporation 2007. All rights
reserved.
Build started 1.7.2010 8:28:10.
Project "SolutionPath\Solution.sln" on
node 0 (Rebuild targe t(s)).
SolutionPath\Solution.sln : error
MSB4126: The specified sol ution
configuration "Release|x86" is
invalid. Please specify a valid
solution c onfiguration using the
Configuration and Platform properties
(e.g. MSBuild.exe Solution.sln
/p:Configuration=Debug
/p:Platform="Any CPU") or leave those
prope rties blank to use the default
solution configuration. Done Building
Project "SolutionPath\Solution.sln"
(Rebuild t arget(s)) -- FAILED.
Build FAILED.
"SolutionPath\Solution.sln" (Rebuild
target) (1) ->
(ValidateSolutionConfiguration target)
-> SolutionPath\Solution.sln : error MSB4126: The specified s olution
configuration "Release|x86" is
invalid. Please specify a valid
solution configuration using the
Configuration and Platform properties
(e.g. MSBuild.ex e Solution.sln
/p:Configuration=Debug
/p:Platform="Any CPU") or leave those
pro perties blank to use the default
solution configuration.
0 Warning(s)
1 Error(s)
Time Elapsed 00:00:00.03
If I try to build it for x86/x64 with devenv it works perfectly, however I am trying to set up a build server without installing all the necessary versions of Visual Studio. By the way, if there is a better free tool (that supports .NET framework 4) out there, I'd love to hear about it.
In MSBuild or Teamcity use command line
MSBuild yourproject.sln /property:Configuration=Release /property:Platform=x64
or use shorter form:
MSBuild yourproject.sln /p:Configuration=Release /p:Platform=x64
However you need to set up platform in your project anyway, see the answer by Julien Hoarau.
If you want to build your solution for x86 and x64, your solution must be configured for both platforms. Actually you just have an Any CPU configuration.
How to check the available configuration for a project
To check the available configuration for a given project, open the project file (*.csproj for example) and look for a PropertyGroup with the right Condition.
If you want to build in Release mode for x86, you must have something like this in your project file:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
...
</PropertyGroup>
How to create and edit the configuration in Visual Studio
(source: microsoft.com)
(source: msdn.com)
(source: msdn.com)
How to create and edit the configuration (on MSDN)
If you're trying to do this from the command line, you may be encountering an issue where a machine-wide environment variable 'Platform' is being set for you and working against you. I can reproduce this if I use the VS2012 Command window instead of a regular windows Command window.
At the command prompt type:
set platform
In a VS2012 Command window, I have a value of 'X64' preset. That seems to interfere with whatever is in my solution file.
In a regular Command window, the 'set' command results in a "variable not defined" message...which is good.
If the result of your 'set' command above returns no environment variable value, you should be good to go.
Hopefully this helps someone out there.
For platform I was specifying "Any CPU", changed it to "AnyCPU" and that fixed the problem.
msbuild C:\Users\Project\Project.publishproj /p:Platform="AnyCPU" /p:DeployOnBuild=true /p:PublishProfile=local /p:Configuration=Debug
If you look at your .csproj file you'll see the correct platform name to use.
For VS2017 and 2019... with the modern core library SDK project files, the platform can be changed during the build process. Here's an example to change to the anycpu platform, just before the built-in CoreCompile task runs:
<Project Sdk="Microsoft.NET.Sdk" >
<Target Name="SwitchToAnyCpu" BeforeTargets="CoreCompile" >
<Message Text="Current Platform=$(Platform)" />
<Message Text="Current PlatformTarget=$(PlatformName)" />
<PropertyGroup>
<Platform>anycpu</Platform>
<PlatformTarget>anycpu</PlatformTarget>
</PropertyGroup>
<Message Text="New Platform=$(Platform)" />
<Message Text="New PlatformTarget=$(PlatformTarget)" />
</Target>
</Project>
In my case, I'm building an FPGA with BeforeTargets and AfterTargets tasks, but compiling a C# app in the main CoreCompile. (partly as I may want some sort of command-line app, and partly because I could not figure out how to omit or override CoreCompile)
To build for multiple, concurrent binaries such as x86 and x64: either a separate, manual build task would be needed or two separate project files with the respective <PlatformTarget>x86</PlatformTarget> and <PlatformTarget>x64</PlatformTarget> settings in the example, above.
When you define different build configurations in your visual studio solution for your projects using a tool like ConfigurationTransform, you may want your Teamcity build, to build you a specified build configuration. You may have build configurations e.g., Debug, Release, Dev, UAT, Prod etc defined. This means, you will have MSBuild Configuration transformation setup for the different configurations. These different configurations are usually used when you have different configurations, e.g. different database connection strings, for the different environment. This is very common because you would have a different database for your production environment from your playground development environment.
They say a picture is worth a thousand words, please see the image below how you would specify multiple build configurations in Teamcity.
In the commandline input text box, specify as below
/p:OutputPath=Publish;Configuration=Dev
Here, I have specified two commandline build configurations/arguments OutputPath and build Configuration with values Publish and Dev respectively, but it could have been, UAT or Prod configuration. If you want more, simply separate them by semi-colon,;
There is an odd case I got in VS2017, about the space between ‘Any’ and 'CPU'.
this is not about using command prompt.
If you have a build project file, which could call other solution files. You can try to add the space between Any and CPU, like this (the Platform property value):
<MSBuild Projects="#(SolutionToBuild2)" Properties ="Configuration=$(ProjectConfiguration);Platform=Any CPU;Rerun=$(MsBuildReRun);" />
Before I fix this build issue, it is like this (ProjectPlatform is a global variable, was set to 'AnyCPU'):
<MSBuild Projects="#(SolutionToBuild1)" Properties ="Configuration=$(ProjectConfiguration);Platform=$(ProjectPlatform);Rerun=$(MsBuildReRun);" />
Also, we have a lot projects being called using $ (ProjectPlatform), which is 'AnyCPU' and work fine. If we open proj file, we can see lines liket this and it make sense.
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
So my conclusion is,
'AnyCPU' works for calling project files, but not for calling solution files,
for calling solution files, using 'Any CPU' (add the space.)
For now, I am not sure if it is a bug of VS project file or MSBuild.
I am using VS2017 with VS2017 build tools installed.
In Visual Studio 2019, version 16.8.4, you can just add
<Prefer32Bit>false</Prefer32Bit>

MSBuild Using Wrong Version of Assembly to Compile RDLC File

I am using the reportviewer control from VS 2010 to create client side reports (rdlc). Everything is working fine on my development machine, and when I manually compile (via VS2010) and manually deploy to a test machine that doesn't have development tools installed.
In order to get the test machine to work (without installing VS2010 or ReportViewer.exe), I had to add references in my project to Microsoft.ReportViewer.Winforms, Microsoft.ReportViewer.Common and Microsoft.ReportViewer.ProcessingModel and have them all "Copy Local".
I have the rdlc files configured for Build Action => embedded resources. This is the default setting when adding a new rdlc to the project. I am open to configuring this otherwise if this would resolve this problem (no idea if its related).
The problem: since adding the rdlc files, the solution no longer builds on the build server. I have installed ReportViewer.exe on the build server, and have verified that the required assemblies exist in the GAC. The .Net 4 framework is NOT installed on the build server--I don't think this is required because the solution targets the 3.5 runtime.
I believe the root of the problem is the following from the build log:
Target "RunRdlCompiler": Building
target "RunRdlCompiler" completely.
Output file
"obj\Release\RdlCompile.compiled" does
not exist. Using "RdlCompile" task
from assembly
"Microsoft.ReportViewer.Common,
Version=9.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a". Task
"RdlCompile":
Report\RDLC\GreenReport.rdlc (0,0):
error rsInvalidReportDefinition: The
report definition is not valid.
Details: The report definition has an
invalid target namespace
'http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition'
which cannot be upgraded.
From what I can tell, Microsoft.ReportViewer.Common version 10.0.0.0 is what should be used to "compile" the rdlc, but MSBuild appears to be using 9.0.0.0. I believe if I could force it to use the right version (which IS installed in the GAC), the solution would compile.
This is because your Microsoft.Common.Targets file is pointing to the 9.0 version of the assembly.
If you look in [sysdir]\Microsoft.NET\Framework\v3.5 you will find Microsoft.Common.targets, which is driving a lot of what MSBuild does. This verion of the common targets file points to [Program Files]\MSBuild\Microsoft\VisualStudio\v9.0\ReportingServices\Microsoft.ReportingServices.targets forcing MSBuild to run with the 9.0 version.
When you installed .NET 4.0, you got a new common targets file in the v4.0.x directory, this new one now points to [Program Files]\MSBuild\Microsoft\VisualStudio\v10.0\ReportingServices\Microsoft.ReportingServices.targets which points to the 10.0 version of the ReportViewer assemblies.
The 10.0 ReportViewer is compiled against .NET 3.5 and intended to work in both 3.5 and 4.0. You could very likely get rid of the .NET 4.0 framework, and alter your 3.5 common targets file to point to the new ReportingServices target file, and it should work. In theory anyway, I've never actually tried it. You may be best off just sticking with 4.0, as that's what we intended when we designed the MSBuild support for the new viewer.
Just install Microsoft Report Viewer 2010 SP1.
I had a very similar issue. Just all of a sudden I could no longer build a VS2010 project that contained an .rdlc file. I wasn't converting any reports or using a report server, everything was local. I tried creating a brand new project and adding an empty new rdlc report and hit build and it wouldn't work. Just one day it stopped compiling and gave me the following error:
The report definition is not valid. Details: The report definition has an invalid target namespace 'http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition' which cannot be upgraded.
Turns out the issue was my "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\ReportingServices\Microsoft.ReportingServices.targets" file had somehow changed. The top of my file was:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="Microsoft.Reporting.RdlCompile" AssemblyName="Microsoft.ReportViewer.Common, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
And it should have been:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="Microsoft.Reporting.RdlCompile" AssemblyName="Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
I changed that one "Using Task" line in the file and everything builds again. REALLY frustrating and it ate up two days of my life. Hoping posting this comment may help someone else in a similar situation.
Jim Lafler
I have tried re-installing all and it didnt work. Then, I tried updating Microsoft.ReportingServices.targets as per Jim's post but even didnt work for me.
At the end, I just copied Microsoft.ReportingServices.targets from other machine (where it was running without error). And surprisingly, it is working.
The additional difference I noticed while comparing, to change PublicKeyToken along with Version.
This may be the case for me only but Jim's post was much useful.
SFUH
Turns out I did need the .Net 4.0 Framework, and more specifically the 4.x version of MSBuild, which uses the newer version of the Microsoft.ReportViewer.Common library.
So even if you are targeting the 3.5 framework, if you create the rdlc with VS2010 it will expect to be "compiled" using 4.0 tools.
I have the same problem: we using ReportViewer 2012 (version of assemblies starts with 11). Both on local machines and on build machine are installed ReportViewer 2012 package and VisualStudio 2013. On local machines compilation in VS succeeds, but on build machine during queued build MSBuild throws such error:
The report definition is not valid. Details: The report definition has an invalid target
namespace 'http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition'
which cannot be upgraded.
I tried to modify Microsoft.Common.targets from .NET 3.5 folder in way, that is described in this post, but no effect. Then I opened Microsoft.Common.targets from .NET 4.0 folder, and found there such strings:
<!-- VS10 without SP1 and without VS11 will not have VisualStudioVersion set, so do
that here -->
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)'
==''">10.0</VisualStudioVersion>
</PropertyGroup>
Then I realized that problem may be in incorrect value of variable $(VisualStudioVersion), so I added to build definition in section "Process" this MSBuild parameter:
/p:VisualStudioVersion=12.0
And it worked! Build completed successfully.
Hope this will help someone.
Pasting file paths doesn't seem to be going through... how about this:
Was:
TaskName="Microsoft.Reporting.RdlCompile" AssemblyName="Microsoft.ReportViewer.Common, Version=8.0.0.0...
And is now:
TaskName="Microsoft.Reporting.RdlCompile" AssemblyName="Microsoft.ReportViewer.WebForms, Version=10.0.0.0...
James
The NetFx40_LegacySecurityPolicy was enabled in my devenv.exe.config, and when I commented this line out, the project built successfully.
We had enabled the legacy security policy on our team to enable our team to work with DevExpress 7.2 controls from within Visual Studio 2010, but in this case, it shows that the approach we took is not always the best.
I lost 2 full days of development due to a similar issue. On building my project it would succeed, but on rebuild it failed with no errors. On investigating the verbose build log in the Output window it directed me towards a problem with the rdlcompile function (so reporting services local report embedding issue). After trying every thing I finally manage to resolve the issue, but disabling my virus scanner. The Antivirus was somehow interfering with my rebuild and caused the rebuild to fail.
After disabling virus scan, rebuild works 100%
I have same problem on my Visual Studio 2013.
The dll version of reporting service on my project is Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
When i checked my ReportingServices targets
C:\Program Files\MSBuild\Microsoft\VisualStudio\v12.0\ReportingServices\Microsoft.ReportingServices.targets
I found the task version is 11.0.0.0
<UsingTask TaskName="Microsoft.Reporting.RdlCompile" AssemblyName="Microsoft.ReportViewer.WebForms, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"/>
When i changed the task version to 10.0.0.0 corresponding to dll version on my proejct.
<UsingTask TaskName="Microsoft.Reporting.RdlCompile" AssemblyName="Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
It' worked.
I just removed this file from my file system. The reports are simply ambedded no need to be compiled.
c:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\V11.0\ReportingServices\Microsoft.ReportingServices.targets
this worked fine for me and for my build server.

Microsoft Assembly configuration for 32-bit mixed C/C++ application

We have a 32 bit mixed C/C++ application that we are trying to deploy to the world.
It naturally uses C and C++ runtime DLLs. We are using VS 2005.
The manifest constructed by VS2005 is the following:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50727.42" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
</dependentAssembly>
</dependency>
</assembly>
We ship this as a file in the same directory as the "application", named
(changed to protect the innocent) "application.exe.manifest".
On the face of it, it is sort of reasonable. But, in installing on some
systems, we get the message when "application.exe" is launched:
This application has failed to start because the application configuration is incorrect
One way to cure this is to run VCRedist_x86.exe from MSDN. (Unfortunately,
while we can run it, we don't know exactly what it is doing.
It appears to be parking DLLs in the SxS directories. But what else
does it do?)
a) The MS docs seem to indicate that the assembly must have an assemblyIdentity
tag directly underneath the assembly tag, that names the application itself.
This is clearly missing here, but the manifest seems to partially work in that
if we remove it, the application doesn't start even if the DLLs are present.
b) Remarkably the assembly doesn't mention the C runtime DLL. Do I need to just add that by hand?
c) We dont want to be dependent on whether the right version DLL is present on the target machine. Assuming that the assembly makes it clear which DLLs to use, how is that we can ensure the DLLs we need are on the target system? (In particular, we don't want run VCRedist or ask our customer to do this). Before assemblies came along, we solved this problem by simply placing the C and C++ DLLs in the same directory as the application .exe file, and Windows would look there first to pick them up. Can we still ship the C and C++ DLLs in the same directory? I can't figure out from the MS docs I can find how the SxS finds the appropriate dependent assemblies.
Any help appreciated.
a) The manifest xml validation clearly has some problems. Depending on the version of Windows this may or may not be an issue. Since so many applications don't correctly follow the schema (and because it was never properly enforced), I doubt it will ever be strict here.
b) The C runtime DLL is referenced in the Microsoft.VC80.CRT.manifest file, pulling it in to to the loader dependency graph. Providing you have a dependency on the manifest, you will also implicitly have a dependency on the DLL.
c) Per my earlier comment, the correct thing to do (aside from installing the latest redist system wide) is to put the CRT manifest and all three DLLs in your application directory. This is poorly documented under SxS: Private Assemblies and Installing Side-by-side Assemblies as Private Assemblies. The probe order is defined in Assembly Searching Sequence.
Generally a SxS binding failure will put an entry in the Application (for Vista+) or System Event Log (pre Vista) describing the error.
Activation context generation failed for "C:\TEMP\sxs\PEVerify.exe".Error in manifest or policy file "C:\TEMP\sxs\Microsoft.VC90.CRT.MANIFEST" on line 4.
Component identity found in manifest does not match the identity of the component requested.
Reference is Microsoft.VC90.CRT,processorArchitecture="x86",publicKeyToken="1fc8b3b9a18e3b",type="win32",version="9.0.21022.8".
Definition is Microsoft.VC90.CRT,processorArchitecture="x86",publicKeyToken="1fc8b3b9a1e18e3b",type="win32",version="9.0.30729.1".
Please use sxstrace.exe for detailed diagnosis.
You can use sxstrace.exe in (Vista+) to see what the loader is actually doing. Junfeng covers this in more detail in Diagnosing SideBySide failures.
To get a better understanding of what is happening at runtime (after the manifest has been parsed and dependencies located), enable "Show Loader Snaps" for your image file (just the filename and extension, do not enter a directory name, like so: "notepad.exe") using gflags.exe. Run your application under windbg (Visual Studio's debugger may also work) and look at the output. Make sure to disable loader snaps when you're done debugging since it will slow down the application even when no debugger is attached. Sample output looks like this:
2d6c:36b4 # 1246428223 - LdrpHandleOneOldFormatImportDescriptor - INFO: DLL "C:\Program Files\Microsoft SDKs\Windows\v6.1\Bin\PEVerify.exe" imports "MSVCR90.dll"
2d6c:36b4 # 1246428223 - LdrpMapDll - INFO: Mapping static redirected DLL "C:\Windows\WinSxS\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.4148_none_5090ab56bcba71c2\MSVCR90.dll"
ModLoad: 4fbd0000 4fc73000 C:\Windows\WinSxS\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.4148_none_5090ab56bcba71c2\MSVCR90.dll
2d6c:36b4 # 1246428285 - LdrpMapDll - INFO: Mapped DLL "C:\Windows\WinSxS\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.4148_none_5090ab56bcba71c2\MSVCR90.dll" at address 4FBD0000
2d6c:36b4 # 1246428285 - LdrpHandleOneOldFormatImportDescriptor - INFO: DLL "C:\Windows\WinSxS\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.4148_none_5090ab56bcba71c2\MSVCR90.dll" imports "KERNEL32.dll"
You could link the C/C++ runtime statically.
You can change the library linkage in the C/C++ compiler options in the Code Generation section. Change the entry from Multithreaded [Debug] DLL to Multithreaded [Debug].
Your DLL will then contain the required parts of the runtime, and the separate installation is not required.
I've never understood how the manifest stuff all hangs together ... but instead of placing the C runtime DLLs in the same directory as your exe try copying the whole 'Microsoft.VC90.CRT' folder from the redist folder in the Visual Studio install (C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\redist\x86\Microsoft.VC90.CRT on my machine).
I believe Microsoft encourages the use of shared libraries and running the official redist since it installs the libraries 'properly' and means they can patch security issues that may be found in them.

Use 32bit "Program Files" directory in msbuild

In 64 bit versions of windows, 32 bit software is installed in "c:\program files (x86)". This means you cannot use $(programfiles) to get the path to (32 bit) software. So I need a $(ProgramFiles32) to overcome this in my MSBuild project. I don't want to change the project depending on the os it is running on.
I have a solution that I will post, but maybe there is a easier/better way.
In MSBuild 4.0+, there's a $(MSBuildProgramFiles32) property for it, which you can confidently employ directly (especially if you're prepared to put a ToolsVersion="4.0" at the top of the file to guarantee it's going to be available and Fail Fast if it's not).
If you're not and need something that can Do The Right Thing even when executed in an MSBuild 2.0 or later environment (i.e., back to VS 2005 environments), the complete solution is:
<PropertyGroup>
<!--MSBuild 4.0 property-->
<ProgramFiles32>$(MSBuildProgramFiles32)</ProgramFiles32>
<!--Use OS env var as a fallback:- 32 bit MSBuild 2.0/3.5 on x64 will use this-->
<ProgramFiles32 Condition=" '' == '$(ProgramFiles32)'">$(ProgramFiles%28x86%29)</ProgramFiles32>
<!-- Handle MSBuild 2.0/3.5 running in 64 bit mode - neither of the above env vars are available. http://stackoverflow.com/questions/336633
NB this trick (Adding a literal " (x86)" to the 64 bit Program Files path) may or may not work on all versions/locales of Windows -->
<ProgramFiles32 Condition ="'$(ProgramFiles32)'=='' AND 'AMD64' == '$(PROCESSOR_ARCHITECTURE)'">$(ProgramFiles) (x86)</ProgramFiles32>
<!--Catch-all - handles .NET 2.0/3.5 non-AMD64 and .NET 2.0 on x86 -->
<ProgramFiles32 Condition=" '' == '$(ProgramFiles32)' ">$(ProgramFiles)</ProgramFiles32>
</PropertyGroup>
Unfortunately Progressive enhancement / polyfill overriding of the MSBuild reserved property name MSBuildProgramFiles32 via either a <PropertyGroup> or <CreateProperty> is rejected by MSBuild 4.0+ so it can't be made tidier and still support .NET 2.0.
My solution is to look whether "c:\program files (x86)" exists, if it exists, asume this is a 64 bit os. Otherwise use the normal program files directory:
<PropertyGroup>
<ProgramFiles32 Condition="Exists('$(PROGRAMFILES) (x86)')">$(PROGRAMFILES) (x86)</ProgramFiles32>
<ProgramFiles32 Condition="$(ProgramFiles32) == ''">$(PROGRAMFILES)</ProgramFiles32>
</PropertyGroup>
I can use it like this
<Exec WorkingDirectory="src\app1" Command='"$(ProgramFiles32)\doxygen\bin\doxygen" Doxyfile' />
In MSBuild 4.0, $(MSBuildProgramFiles32) will give you the 32-bit Program Files directory.
Try "$(MSBuildExtensionsPath32)\.."
I think a slighly more reliable way is to grab the Environment variable "ProgramFiles(x86)". In a 64 bit process on Windows this will point to the 32 bit program files directory. It will be empty on a 32 bit version of windows and I believe on a wow64 process
I ran into virtually same problem recently with some PowerShell scripts. I wrote a blog entry on how a worked around the program files directory issue. Different language obviously but it may help you out.
http://blogs.msdn.com/jaredpar/archive/2008/10/21/program-files-i-just-want-the-32-bit-version.aspx
I stumbled across this question trying to find a generic way in MSbuild to see if it was a 32- or 64-bit os. In case someone else also find this, I used the following:
<PropertyGroup>
<OSBits Condition="$(ProgramW6432) != ''">x64</OSBits>
<OSBits Condition="$(OSBits) == ''">x32</OSBits>
</PropertyGroup>
Apparently %ProgramW6432% is only set on 64-bit systems.
If you run the 32-bit version of the Visual Studio tools (especially in VS2012, there are like 3 different command prompts you can choose from), $(ProgramFiles) points to "Program Files (x86)"