Compiling x64 on 32bits version of windows (Teamcity) - c#

Our Teamcity agent is running on a 32bits OS for now and this was not an issue up until now (we now have an x64 applications to build in there).
I heard its possible to compile x64 applications on a 32bit OS but I've never did it. What would be the step required to have Teamcity build a specific project in x64 - Ideally using MSBuild?
When I set my project's MSBuild property "Run Platform" to x64 my agent give me the following warning: "Unmet requirements: DotNetFramework4.0_x64 exists"
As a side note: we will eventually move the agent to a 64bits OS but I would like a short term solution.

I think the Run Platform for MSBuild in TeamCity is for what version of MSBuild to use, it's looking for MSBuild.exe in the C:\Windows\Microsoft.NET\Framework64\v4.0.30319 folder, when you're on a 32-bit version of Windows, and that framework isn't installed. However, the 32-bit version of MSBuild can invoke the C# Compiler that can still produce x64 assemblies, even on your 32-bit machine.
What you want to do is do a Run Platform for x86, but pass /property:Platform=x64 as one of your commands. If you don't have a x64 Configuration, you may considering trying to pass it /property:Platform="Any CPU". However, Any CPU would only be guaranteed to work if all the assemblies you reference in your project are set the Any CPU as well. Alternative, you can create a custom configuration where all your assemblies are specified x64, and pass that via command line to MSBuild.
Keep in mind if any of your projects are C++, you will need to make sure you have the x64 compilers installed, as I don't think they're installed by default.

Related

How to run .NET 5 WPF app without exe and console

I have a .NET 5 WPF application built for AnyCPU platform.
In the project file i have:
WinExe
net5.0-windows
The output folder contains all dll and an exe but when i run the exe on a 32 bits windows i get this message:
This version of software.exe is not compatible with the version of windows
you're running. Check your computer's system information to see
whether you need a x86 (32-bit) or x64 (64-bit) version of the
program, and then contact the software publisher.
To ease deployment and run, I want to have only 1 build and 1 shortcut no matter the target system.
So my initial solution was to run the application using dotnet.exe and having the core dll as a parameter.
dotnet.exe software.dll
The WPF application start and run fine but the console with the dotnet command line is kept open during the application lifetime.
Is there a solution to get rid of the console when I start the WPF application using dotnet.exe ?
No solution without exe file at this time, so as a workaround I found a way to produce both 32bit and 64bit exe.
In the Visual Studio build configuration manager, I added x86 and x64 platforms.
Which updated the csproj with
<Platforms>AnyCPU;x86;x64</Platforms>
Then I added in csproj
<AssemblyName>MySoftware-$(Platform)</AssemblyName>
When I build the solution, it automatically append the targeted platform to the exe and dll for the platform.
MySoftware-x86.exe
MySoftware-x86.dll
MySoftware-x64.exe
MySoftware-x64.dll
Finally, I call "dotnet.exe build" twice for both x86 and x64 using a script.
To put all this together, a 32-bit machine can run anything with a PE
set to PE32, but nothing with a PE of PE32+. A 64-bit machine can run
your file in 64-bit mode as long as 32BIT is 0, but if 32BIT is 1 then
it must use WOW64.
https://illuminatedcomputing.com/posts/2010/02/sorting-out-the-confusion-32-vs-64-bit-clr-vs-native-cs-vs-cpp/
Why would you want to compile a .NET assembly specific to 32-bit or
X64, or IA? Usually because you're P/Invok'ing into a x64 specific
native dll.
The interesting things that corflags tell us are these:
CLR Header: The compiler version...2.0 is .NET 1.1, 2.5 is .NET 2.0
and 3.0 is .NET 3.5. Don't ask. ;)
PE (Portable Executable): PE32 is 32bit and PE32+ is 64-bit.
32BIT: Are we asking to force 32-bit
execution or not?
www.hanselman.com/blog/32bitness-and-64bitness-and-migrating-dasblog-on-iis7-and-aspnet-under-vista64

If "Any CPU" is selected in Visual Studio, do I still need to separate 32-bit and 64-bit assembly in Advanced Installer?

I'm creating mixed 32-bit/64-bit installers using advance installer, according to this guide Advance Installer Guide for 32-bit/64-bit installers I should seperate 32-bit and 64-bit assemblies. My question is what if my visual studio build is set to "Any CPU", can I use single assembly file for both 32-bit and 64-bit or do I have to create seperate 32-bit and 64-bit assemblies and put them in 32-bit and 64-bit folders in advanced installer.
Additional Information:
My application does not use any DLL references.
You can leave your project building as AnyCPU, and deploy the same assembly to x86 or x64. Advanced Installer's wizard for creating a Mixed Package will ask for files that are x64 only, x86 only, and shared files. Your AnyCPU assembly would be a shared file to deploy for both x86 and x64. Advanced installer puts the shared files in a common component, and the others in their respective 64-bit and 32-bit components.
The Mixed Package uses bootstrapper that contains both an x86 and x64 msi. Another option for deploying your AnyCPU assembly is to create an x86 msi as it would run on both platforms. The x86 msi would deploy your AnyCPU assembly to Program Files (x86), but when run on an x64 machine it would run as an x64 process.
If the assembly uses unmanaged 32- or 64-bit code, you have to compile two respective versions. Otherwise, with "Any CPU" you can use the same assembly for both platforms.
Your project shouldn't go under either of them and should instead likely be put under MainFeature.
The important thing is under Install Parameters you have set the Package Type to "Mixed 32/64-bit matching the platform"

.NET 4.5 "Any CPU" with Perefer 32 bit option : not work for dlls which have 32 and 64 bit versions with XCopy

While I was try to use an embedded database which has both 32-and 64-bit versions like SQLite and SQL Server CE in "C# - ANY CPU"
[ Both provide XCOPY deployment for their 32 and 64 bit versions.
Check the following links: -sql server ce private installation- -XCOPY deployment with sqlite- ]
I noticed that when we check "Prefer 32 bit", XCOPY deployment not work,In that case procoess is not 64 bit but try to load ddl from x64 folder and crashes.
If we uncheck "Prefer 32 bit" it works as 64 bit and find also right dlls.
Even if I make my project x86 then it also works and find right ddls under x86.
Why does "prefer 32 bit" compile option have this behaviour? Is it a bug?
I can confirm Hippias Minor's problem - caused me some headache too. SQLite consists of a managed library that chooses which native DLL to load at run-time (either SQLite.Interop.DLL from x64 or x86 directory). This way it does not need to embed the native library (and is thus more portable - same "xcopy deployment" can work on different architectures). This is also the way SQLite is usually installed from NuGet.
The difference between "x86" and "Any CPU w/ prefer 32-bit" (beside being able to run on ARM) is that the first will set the environment variable PROCESSOR_ARCHITECTURE to "x86" while the second will set it to "AMD64"! The issue is described here: PROCESSOR_ARCHITECTURE returns AMD64 in some 32-bit processes
Therefore SQLite (which is using that as a heuristic) will try to load the 64-bit interop DLL and miserarbly fail since it is infact being run as a 32-bit process.
A workaround might be to check Environment.Is64BitProcess and when that is false manually change the environment variable to "x86".
The primary purpose of the 'Prefer 32 bit' is better processor support with the 'CPU Any' setting.
From What AnyCPU Really Means As Of .NET 4.5 and Visual Studio 11
The difference, then, between “Any CPU 32-bit preferred” and “x86” is only this: a .NET application compiled to x86 will fail to run on an ARM Windows system, but an “Any CPU 32-bit preferred” application will run successfully.
On a x64 processor setting this option is essentially the same as using the x86 compile option.
if (!Environment.Is64BitProcess
&& Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")
.Equals("AMD64", StringComparison.InvariantCultureIgnoreCase))
{
// Workaround the "Any CPU" w/ "Prefer 32-bit" option from .NET 4.5+
Environment.SetEnvironmentVariable("PROCESSOR_ARCHITECTURE", "x86");
}
before any SQLite code seems to make the thing work.

Does changing build options move where an application is located in the Local Machine Software registry key?

I have a solution where the executable's target platform was initially set to x86, many other projects were set to AnyCPU, and included 3 projects in .Net 3.5 (everything else .Net 4.0). I presume this is why the installer wrote to the HKEY_LOCAL_MACHINE\SOFTWARE registry key.
Recently, I fixed some issues and now all projects are .Net 4.0. Additionally, I set the executable target platform to AnyCPU. I found the application was now installed in HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node.
[sidebar - we have p/invokes - DllImport attributes - that did not
specify a CallingConvention. When this was modified both in
managed and unmanaged code to specifiy Cdecl and __cdecl, we were able to
upgrade dependent projects to .Net 4.0 without receiving a PInvokeStackImbalance exception.]
We develop currently with VS2010 on Windows 7 (64-bit) machines.
My question is: Did the installer write to \SOFTWARE\ initially because some of the projects were .Net 3.5?
Also, if this application is intended to be installed on WindowsXP (32-bit is expected to be supported) machines, is the registry key problematic? Better yet, what should I look for in build options that ensures compatibility on WinXp 32-bit systems?
Only a 64-bit installer will avoid Wow6432Node on a 64-bit operating system. In a Setup project, that's set by the TargetPlatform property of the installer, it defaults to "x86". Change it to "x64" if you changed the C# EXE project's Target platform to AnyCPU. This will also ensure that your program is installed to c:\program files and not c:\program files (x86).
You will thus need to maintain two installers. Bit of a headache, you can avoid it by setting the C# EXE project's Target platform to x86 so both the installer and your program access the key in Wow6432Node.
The pinvoke problem is normally the other way around, 64-bit code has only one calling convention and there's no difference between cdecl and stdcall.

32/64 bit confusion with a .NET executable

I have an executable build with Visual Studio 2005 using C#. dumpbin reports that it is x86 and it is claimed that it was built as a x86 target. However, when I try executing it, it somehow becomes a 64bit executable as reported by task manager, process explorer and procmon shows that it loads Framework64. And it fails eventually due to failure to load a 32bit DLL.
What could cause this behavior?
You are building it with the AnyCPU target. If you want it to be x86 even on a 64 bit system, then you must target x86.
When you target AnyCPU, the loader runs the process as a 64 bit process on a 64 bit system, but a 32 bit process on a 32 bit system.
Change the platform target from "Any" to "x86" in the project properties / build configuration list.
One can use corflags.exe to force it to run as 32-bit.
O:\>corflags
Microsoft (R) .NET Framework CorFlags Conversion Tool. Version 3.5.30729.1
Copyright (c) Microsoft Corporation. All rights reserved.
Usage: Corflags.exe Assembly [options]
If no options are specified, the flags for the given image are displayed.
Options:
/ILONLY+ /ILONLY- Sets/clears the ILONLY flag
/32BIT+ /32BIT- Sets/clears the 32BIT flag
/UpgradeCLRHeader Upgrade the CLR Header to version 2.5
/RevertCLRHeader Revert the CLR Header to version 2.0
/Force Force an assembly update even if the image is
strong name signed.
WARNING: Updating a strong name signed assembly
will require the assembly to be resigned before
it will execute properly.
/nologo Prevents corflags from displaying logo
/? or /help Display this usage message
"What could cause this behavior?"
To be techically accurate in answering this question, but not quite in the spirit you asked, what causes this behavior is the lack of the 64-bit DLL.
Why doesn't the program have a 64-bit version of it?
In a few years I doubt 32-bit systems will exist anywhere except as ARM and ARM systems will need new DLLs to be recompiled anyway.

Categories

Resources