@@ -411,7 +411,6 @@ HostFxrResolver::InvokeWhereToFindDotnet()
411
411
HandleWrapper<InvalidHandleTraits> hThread;
412
412
CComBSTR pwzDotnetName = nullptr ;
413
413
DWORD dwFilePointer = 0 ;
414
- BOOL fIsCurrentProcess64Bit = FALSE ;
415
414
DWORD dwExitCode = 0 ;
416
415
STRU struDotnetSubstring;
417
416
STRU struDotnetLocationsString;
@@ -426,6 +425,7 @@ HostFxrResolver::InvokeWhereToFindDotnet()
426
425
securityAttributes.bInheritHandle = TRUE ;
427
426
428
427
LOG_INFO (L" Invoking where.exe to find dotnet.exe" );
428
+ auto currentProcessArch = Environment::GetCurrentProcessArchitecture ();
429
429
430
430
// Create a read/write pipe that will be used for reading the result of where.exe
431
431
FINISHED_LAST_ERROR_IF (!CreatePipe (&hStdOutReadPipe, &hStdOutWritePipe, &securityAttributes, 0 ));
@@ -499,13 +499,9 @@ HostFxrResolver::InvokeWhereToFindDotnet()
499
499
}
500
500
501
501
FINISHED_IF_FAILED (struDotnetLocationsString.CopyA (pzFileContents, dwNumBytesRead));
502
-
503
502
LOG_INFOF (L" where.exe invocation returned: '%ls'" , struDotnetLocationsString.QueryStr ());
504
503
505
- fIsCurrentProcess64Bit = Environment::IsRunning64BitProcess ();
506
-
507
- LOG_INFOF (L" Current process bitness type detected as isX64=%d" , fIsCurrentProcess64Bit );
508
-
504
+ // Look for a dotnet.exe that matches the current process architecture
509
505
while (TRUE )
510
506
{
511
507
index = struDotnetLocationsString.IndexOf (L" \r\n " , prevIndex);
@@ -518,37 +514,47 @@ HostFxrResolver::InvokeWhereToFindDotnet()
518
514
// \r\n is two wchars, so add 2 here.
519
515
prevIndex = index + 2 ;
520
516
521
- LOG_INFOF (L" Processing entry '%ls'" , struDotnetSubstring.QueryStr ());
522
-
523
- if (fIsCurrentProcess64Bit == IsX64 (struDotnetSubstring.QueryStr ()))
517
+ ProcessorArchitecture dotnetArch = GetFileProcessorArchitecture (struDotnetSubstring.QueryStr ());
518
+ if (dotnetArch == currentProcessArch)
524
519
{
525
- // The bitness of dotnet matched with the current worker process bitness.
520
+ LOG_INFOF (L" Found dotnet.exe matching current process architecture (%ls) '%ls'" ,
521
+ ProcessorArchitectureToString (dotnetArch),
522
+ struDotnetSubstring.QueryStr ());
523
+
526
524
return std::make_optional (struDotnetSubstring.QueryStr ());
527
525
}
526
+ else
527
+ {
528
+ LOG_INFOF (L" Skipping dotnet.exe with non-matching architecture %ls (need %ls). '%ls'" ,
529
+ ProcessorArchitectureToString (dotnetArch),
530
+ ProcessorArchitectureToString (currentProcessArch),
531
+ struDotnetSubstring.QueryStr ());
532
+ }
528
533
}
529
534
530
535
Finished:
531
536
return result;
532
537
}
533
538
534
- BOOL HostFxrResolver::IsX64 (const WCHAR* dotnetPath)
539
+ // Reads the PE header of the binary to determine its architecture.
540
+ ProcessorArchitecture HostFxrResolver::GetFileProcessorArchitecture (const WCHAR* binaryPath)
535
541
{
536
542
// Errors while reading from the file shouldn't throw unless
537
543
// file.exception(bits) is set
538
- std::ifstream file (dotnetPath , std::ios::binary);
544
+ std::ifstream file (binaryPath , std::ios::binary);
539
545
if (!file.is_open ())
540
546
{
541
- LOG_TRACEF (L" Failed to open file %ls" , dotnetPath );
542
- return false ;
547
+ LOG_TRACEF (L" Failed to open file %ls" , binaryPath );
548
+ return ProcessorArchitecture::Unknown ;
543
549
}
544
550
545
551
// Read the DOS header
546
552
IMAGE_DOS_HEADER dosHeader{};
547
553
file.read (reinterpret_cast <char *>(&dosHeader), sizeof (dosHeader));
548
554
if (dosHeader.e_magic != IMAGE_DOS_SIGNATURE) // 'MZ'
549
555
{
550
- LOG_TRACEF (L" %ls is not a valid executable file (missing MZ header)." , dotnetPath );
551
- return false ;
556
+ LOG_TRACEF (L" %ls is not a valid executable file (missing MZ header)." , binaryPath );
557
+ return ProcessorArchitecture::Unknown ;
552
558
}
553
559
554
560
// Seek to the PE header
@@ -559,32 +565,30 @@ BOOL HostFxrResolver::IsX64(const WCHAR* dotnetPath)
559
565
file.read (reinterpret_cast <char *>(&peSignature), sizeof (peSignature));
560
566
if (peSignature != IMAGE_NT_SIGNATURE) // 'PE\0\0'
561
567
{
562
- LOG_TRACEF (L" %ls is not a valid PE file (missing PE header)." , dotnetPath );
563
- return false ;
568
+ LOG_TRACEF (L" %ls is not a valid PE file (missing PE header)." , binaryPath );
569
+ return ProcessorArchitecture::Unknown ;
564
570
}
565
571
566
572
// Read the file header
567
573
IMAGE_FILE_HEADER fileHeader{};
568
574
file.read (reinterpret_cast <char *>(&fileHeader), sizeof (fileHeader));
569
575
570
- // Read the optional header magic field
571
- WORD magic{};
572
- file.read (reinterpret_cast <char *>(&magic), sizeof (magic));
573
-
574
- // Determine the architecture based on the magic value
575
- if (magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
576
+ // Determine the architecture based on the machine type
577
+ switch (fileHeader.Machine )
576
578
{
577
- LOG_INFOF (L" %ls is 32-bit" , dotnetPath);
578
- return false ;
579
- }
580
- else if (magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
581
- {
582
- LOG_INFOF (L" %ls is 64-bit" , dotnetPath);
583
- return true ;
579
+ case IMAGE_FILE_MACHINE_I386:
580
+ LOG_INFOF (L" %ls is x86 (32-bit)" , binaryPath);
581
+ return ProcessorArchitecture::x86;
582
+ case IMAGE_FILE_MACHINE_AMD64:
583
+ LOG_INFOF (L" %ls is AMD64 (x64)" , binaryPath);
584
+ return ProcessorArchitecture::AMD64;
585
+ case IMAGE_FILE_MACHINE_ARM64:
586
+ LOG_INFOF (L" %ls is ARM64" , binaryPath);
587
+ return ProcessorArchitecture::ARM64;
588
+ default :
589
+ LOG_INFOF (L" %ls has unknown architecture (machine type: 0x%X)" , binaryPath, fileHeader.Machine );
590
+ return ProcessorArchitecture::Unknown;
584
591
}
585
-
586
- LOG_INFOF (L" %ls is unknown architecture %i" , dotnetPath, fileHeader.Machine );
587
- return false ;
588
592
}
589
593
590
594
std::optional<fs::path>
0 commit comments