dotnet / msbuild

The Microsoft Build Engine (MSBuild) is the build platform for .NET and Visual Studio.
https://docs.microsoft.com/visualstudio/msbuild/msbuild
MIT License
5.21k stars 1.35k forks source link

MSBuild is loading the wrong task architecture #7382

Open rseanhall opened 2 years ago

rseanhall commented 2 years ago

Issue Description

64-bit MSBuild loads 32-bit task in-proc. Part of the issue here: https://github.com/wixtoolset/issues/issues/6720.

Steps to Reproduce

  1. Clone https://github.com/rseanhall/wix4.
  2. Checkout the msbuild-task-arch-issue branch.
  3. Run src\setupenv.cmd (might need to download the latest nuget.exe into C:\Programs).
  4. Run build.cmd.

Binlogs are created in build\logs.

Expected Behavior

All tests pass in the src\wix\test\WixToolsetTest.Sdk project.

Actual Behavior

WixToolsetTest.Sdk.MsbuildFixture.CanBuildSimpleMsiPackageWithMergeModule test fails in the 64-bit configuration.

C:\src\mywix4\build\wix\Debug\publish\WixToolset.Sdk\tools\wix.targets(590,5): BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
   at WixToolset.Core.Native.Msm.MsmInterop.MergeModGetClassObject(Guid clsid, Guid iid)
   at WixToolset.Core.Native.Msm.MsmInterop.GetMsmMerge() in C:\src\mywix4\src\wix\WixToolset.Core.Native\Msm\MsmInterop.cs:line 45
   at WixToolset.Core.WindowsInstaller.Bind.ExtractMergeModuleFilesCommand.Execute() in C:\src\mywix4\src\wix\WixToolset.Core.WindowsInstaller\Bind\ExtractMergeModuleFilesCommand.cs:line 56
   at WixToolset.Core.WindowsInstaller.Bind.BindDatabaseCommand.Execute() in C:\src\mywix4\src\wix\WixToolset.Core.WindowsInstaller\Bind\BindDatabaseCommand.cs:line 244
   at WixToolset.Core.WindowsInstaller.MsiBackend.Bind(IBindContext context) in C:\src\mywix4\src\wix\WixToolset.Core.WindowsInstaller\MsiBackend.cs:line 31
   at WixToolset.Core.Binder.BackendBind(IBindContext context) in C:\src\mywix4\src\wix\WixToolset.Core\Binder.cs:line 67
   at WixToolset.Core.Binder.Bind(IBindContext context) in C:\src\mywix4\src\wix\WixToolset.Core\Binder.cs:line 40
   at WixToolset.Core.CommandLine.BuildCommand.BindPhase(Intermediate output, IReadOnlyCollection`1 localizations, IReadOnlyCollection`1 filterCultures, String cabCachePath, IReadOnlyCollection`1 bindPaths, CancellationToken cancellationToken) in C:\src\mywix4\src\wix\WixToolset.Core\CommandLine\BuildCommand.cs:line 360
   at WixToolset.Core.CommandLine.BuildCommand.ExecuteAsync(CancellationToken cancellationToken) in C:\src\mywix4\src\wix\WixToolset.Core\CommandLine\BuildCommand.cs:line 169
   at WixToolset.BuildTasks.WixExeBaseTask.ExecuteCoreAsync(IWixToolsetCoreServiceProvider coreProvider, String commandLineString, CancellationToken cancellationToken) in C:\src\mywix4\src\wix\WixToolset.BuildTasks\WixExeBaseTask_Inproc.cs:line 24
   at WixToolset.BuildTasks.ToolsetTask.ExecuteInProc(String commandLineString) in C:\src\mywix4\src\wix\WixToolset.BuildTasks\ToolsetTask_InProc.cs:line 42
 [C:\Users\rhall\AppData\Local\Temp\5icgguio.okw\MergeMsiPackage\MergeMsiPackage.wixproj]

mergemod.dll is a native DLL that needs to match the process's architecture and is the one that is causing this failure.

Analysis

The test is launching MSBuild from C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\amd64\MSBuild.exe. We have our tasks defined at https://github.com/rseanhall/wix4/blob/6a3a21a9990020e56acbf930f52b479b5d4d08d4/src/wix/WixToolset.Sdk/tools/wix.targets#L142:

  <UsingTask TaskName="WixBuild" Condition=" '$(WixTasksPath64)' == '' " AssemblyFile="$(WixTasksPath)" />
  <UsingTask TaskName="WixBuild" Condition=" '$(WixTasksPath64)' != '' " AssemblyFile="$(WixTasksPath)" Architecture="x86" />
  <UsingTask TaskName="WixBuild" Condition=" '$(WixTasksPath64)' != '' " AssemblyFile="$(WixTasksPath64)" Architecture="x64" />

WixTasksPath64 is always defined in .NET Framework MSBuild, so the task should be loaded from the WixTasksPath64 path.

The very unusual thing about this issue is that it works fine if initializing the command prompt from C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\vsdevcmd.bat.

We have a build process issue that is causing 64-bit dlls to be in the 32-bit folder (build\wix\Debug\publish\WixToolset.Sdk\tools\net472\x86). That test should always be failing in the 32-bit configuration, and always passing in the 64-bit configuration. Instead, both configurations are passing when initialized through vsdevcmd.bat and both configuration are failing otherwise.

Versions & Configurations

msbuild -version output: Microsoft (R) Build Engine version 17.0.0+c9eb9dd64 for .NET Framework Copyright (C) Microsoft Corporation. All rights reserved.

17.0.0.52104

Attach a binlog

MergeMsiPackage.MSBuild64.zip MergeMsiPackage.rest.zip

rainersigwald commented 2 years ago

Duplicate of #6461

rainersigwald commented 2 years ago

Actually wait, maybe not?

rainersigwald commented 2 years ago

@rseanhall can you share a binlog of the passing case?

The failing binlog you shared looks right to me, given your "we have x64 binaries in the x86 folder" situation:

Launching task "WixBuild" from assembly "C:\src\mywix4\build\wix\Debug\publish\WixToolset.Sdk\tools\net472\x86\WixToolset.BuildTasks.dll" in an external task host with a runtime of "CLR4" and a process architecture of "x86".
...
C:\src\mywix4\build\wix\Debug\publish\WixToolset.Sdk\tools\wix.targets(590,5): BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
rseanhall commented 2 years ago

I can, but why should it matter? The actual tasks DLL, WixToolset.BuildTasks.dll, is AnyCPU. This case is running in 64-bit MSBuild and we are declaring that the 64-bit task is in C:\src\mywix4\build\wix\Debug\publish\WixToolset.Sdk\tools\net472\x64\WixToolset.BuildTasks.dll so it should be loading that.

rseanhall commented 2 years ago

@rainersigwald Here are the binlogs when initializing from vsdevcmd.bat. I will update the original post with the other binlogs later when not initializing from vsdevcmd.bat. MergeMsiPackage.passing.zip