-
Notifications
You must be signed in to change notification settings - Fork 63
Find correct x64 host on arm64 machines #207
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -10,10 +10,15 @@ namespace Microsoft.Deployment.Launcher | |||||||||||||
{ | ||||||||||||||
internal static class HostFinder | ||||||||||||||
{ | ||||||||||||||
internal static readonly string ArchMsil = "msil"; | ||||||||||||||
internal static readonly string ArchX86 = "x86"; | ||||||||||||||
internal static readonly string ArchX64 = "amd64"; | ||||||||||||||
internal static readonly string ArchArm64 = "arm64"; | ||||||||||||||
|
||||||||||||||
/// <summary> | ||||||||||||||
/// Gets full path to .NET host appropriate for activating the application. | ||||||||||||||
/// | ||||||||||||||
/// .NET host'slocation can be obtained from multiple locations. | ||||||||||||||
/// .NET host's location can be obtained from multiple locations. | ||||||||||||||
/// | ||||||||||||||
/// Current code searches in default, global shared runtime, location only: | ||||||||||||||
/// %ProgramFiles%\dotnet and %ProgramFiles(x86)%\dotnet | ||||||||||||||
|
@@ -33,23 +38,63 @@ internal static string GetHost(string applicationFilePath) | |||||||||||||
{ | ||||||||||||||
string arch = GetProcessorArchitectureFromAssembly(applicationFilePath); | ||||||||||||||
|
||||||||||||||
if (arch == "x86") | ||||||||||||||
if (arch == ArchX86) | ||||||||||||||
{ | ||||||||||||||
return GetX86Host(); | ||||||||||||||
return GetGlobalHost(arch); | ||||||||||||||
} | ||||||||||||||
else if (arch == "amd64" || arch == "arm64") | ||||||||||||||
else if (arch == ArchX64 || arch == ArchArm64) | ||||||||||||||
{ | ||||||||||||||
return Get64bitHost(); | ||||||||||||||
return Environment.Is64BitOperatingSystem ? GetGlobalHost(arch) : string.Empty; | ||||||||||||||
} | ||||||||||||||
else if (arch == "msil") | ||||||||||||||
{ | ||||||||||||||
string host = Get64bitHost(); | ||||||||||||||
return string.IsNullOrEmpty(host) ? GetX86Host() : host; | ||||||||||||||
string host = string.Empty; | ||||||||||||||
|
||||||||||||||
// On arm64 systems, first look for arm64 host | ||||||||||||||
if (IsArm64System) | ||||||||||||||
{ | ||||||||||||||
host = GetGlobalHost(ArchArm64); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
// Fallback for arm64 systems, and native x64 systems | ||||||||||||||
if (string.IsNullOrEmpty(host)) | ||||||||||||||
{ | ||||||||||||||
host = GetGlobalHost(ArchX64); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
return string.IsNullOrEmpty(host) ? GetGlobalHost(ArchX86) : host; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
return string.Empty; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
/// <summary> | ||||||||||||||
/// Checks if running on Arm64 system | ||||||||||||||
/// </summary> | ||||||||||||||
private static bool IsArm64System | ||||||||||||||
{ | ||||||||||||||
get | ||||||||||||||
{ | ||||||||||||||
try | ||||||||||||||
{ | ||||||||||||||
if (NativeMethods.Kernel32.IsWow64Process2(new IntPtr(-1), out _, out ushort nativeMachine)) | ||||||||||||||
{ | ||||||||||||||
if (nativeMachine == NativeMethods.Kernel32.IMAGE_FILE_MACHINE_ARM64) | ||||||||||||||
{ | ||||||||||||||
return true; | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
catch (EntryPointNotFoundException) | ||||||||||||||
{ | ||||||||||||||
// kernel32.dll does not export IsWow64Process2 on systems before Win10 | ||||||||||||||
// API is available on all systems that support arm64. | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
return false; | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
/// <summary> | ||||||||||||||
/// Gets ProgramFiles folder for the specified bitness. | ||||||||||||||
/// </summary> | ||||||||||||||
|
@@ -67,31 +112,22 @@ private static string GetProgramFilesFolder(bool is64bit = false) | |||||||||||||
/// <summary> | ||||||||||||||
/// Get global host if it exists, for the specified bitness. | ||||||||||||||
/// </summary> | ||||||||||||||
/// <param name="is64bit">If 64-bit bitness is required</param> | ||||||||||||||
/// <param name="arch">Architecture</param> | ||||||||||||||
/// <returns></returns> | ||||||||||||||
private static string GetGlobalHost(bool is64bit = false) | ||||||||||||||
private static string GetGlobalHost(string arch) | ||||||||||||||
{ | ||||||||||||||
bool is64bit = arch == ArchX86 ? false : true; | ||||||||||||||
string folder = GetProgramFilesFolder(is64bit); | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know this is not related to this PR exactly, but this is technically wrong. There's no guarantee that the runtime will be in program files. Ever since 3.1 we added the ability to install to custom "global" location and the location is written in registry. See this doc for the arch specific details: https://github.com/dotnet/designs/blob/main/accepted/2021/install-location-per-architecture.md There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that is a known issue. I have called this out in the comments, in this source file. We do not currently support custom global host locations, but I believe this will be done before 7.0 RTM. deployment-tools/src/clickonce/launcher/HostFinder.cs Lines 18 to 23 in f8a0ab6
|
||||||||||||||
string host = !string.IsNullOrEmpty(folder) ? Path.Combine(folder, "dotnet\\dotnet.exe") : string.Empty; | ||||||||||||||
return File.Exists(host) ? host : string.Empty; | ||||||||||||||
} | ||||||||||||||
string relativeHostPath = "dotnet\\dotnet.exe"; | ||||||||||||||
|
||||||||||||||
/// <summary> | ||||||||||||||
/// Gets full path to x86 .NET host. | ||||||||||||||
/// </summary> | ||||||||||||||
/// <returns>X86 host</returns> | ||||||||||||||
private static string GetX86Host() | ||||||||||||||
{ | ||||||||||||||
return GetGlobalHost(); | ||||||||||||||
} | ||||||||||||||
// On Arm64 systems, x64 host is in "x64" sub-folder | ||||||||||||||
if (is64bit && arch == ArchX64 && IsArm64System) | ||||||||||||||
{ | ||||||||||||||
relativeHostPath = "dotnet\\x64\\dotnet.exe"; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
/// <summary> | ||||||||||||||
/// Gets full path to 64-bit .NET host. | ||||||||||||||
/// </summary> | ||||||||||||||
/// <returns>64-bit host</returns> | ||||||||||||||
private static string Get64bitHost() | ||||||||||||||
{ | ||||||||||||||
return Environment.Is64BitOperatingSystem ? GetGlobalHost(true) : string.Empty; | ||||||||||||||
string host = !string.IsNullOrEmpty(folder) ? Path.Combine(folder, relativeHostPath) : string.Empty; | ||||||||||||||
return File.Exists(host) ? host : string.Empty; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
/// <summary> | ||||||||||||||
|
@@ -120,7 +156,7 @@ private static string GetProcessorArchitectureFromAssembly(string path) | |||||||||||||
// Default to "msil", to support failure scenarios, like GetAssemblyIdentityFromFile returning null | ||||||||||||||
// or encountering an unknown architecture. | ||||||||||||||
return string.IsNullOrEmpty(processorArchitecture) ? | ||||||||||||||
"msil" : | ||||||||||||||
ArchMsil : | ||||||||||||||
processorArchitecture.ToLowerInvariant(); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we call GetCurrentProcess instead of hardcoding to -1?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realize it will return a pseudo handle of -1 also.