@@ -411,7 +411,6 @@ HostFxrResolver::InvokeWhereToFindDotnet()
411411 HandleWrapper<InvalidHandleTraits> hThread;
412412 CComBSTR pwzDotnetName = nullptr ;
413413 DWORD dwFilePointer = 0 ;
414- BOOL fIsCurrentProcess64Bit = FALSE ;
415414 DWORD dwExitCode = 0 ;
416415 STRU struDotnetSubstring;
417416 STRU struDotnetLocationsString;
@@ -426,6 +425,7 @@ HostFxrResolver::InvokeWhereToFindDotnet()
426425 securityAttributes.bInheritHandle = TRUE ;
427426
428427 LOG_INFO (L" Invoking where.exe to find dotnet.exe" );
428+ auto currentProcessArch = Environment::GetCurrentProcessArchitecture ();
429429
430430 // Create a read/write pipe that will be used for reading the result of where.exe
431431 FINISHED_LAST_ERROR_IF (!CreatePipe (&hStdOutReadPipe, &hStdOutWritePipe, &securityAttributes, 0 ));
@@ -499,13 +499,9 @@ HostFxrResolver::InvokeWhereToFindDotnet()
499499 }
500500
501501 FINISHED_IF_FAILED (struDotnetLocationsString.CopyA (pzFileContents, dwNumBytesRead));
502-
503502 LOG_INFOF (L" where.exe invocation returned: '%ls'" , struDotnetLocationsString.QueryStr ());
504503
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
509505 while (TRUE )
510506 {
511507 index = struDotnetLocationsString.IndexOf (L" \r\n " , prevIndex);
@@ -518,37 +514,47 @@ HostFxrResolver::InvokeWhereToFindDotnet()
518514 // \r\n is two wchars, so add 2 here.
519515 prevIndex = index + 2 ;
520516
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)
524519 {
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+
526524 return std::make_optional (struDotnetSubstring.QueryStr ());
527525 }
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+ }
528533 }
529534
530535 Finished:
531536 return result;
532537}
533538
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)
535541{
536542 // Errors while reading from the file shouldn't throw unless
537543 // file.exception(bits) is set
538- std::ifstream file (dotnetPath , std::ios::binary);
544+ std::ifstream file (binaryPath , std::ios::binary);
539545 if (!file.is_open ())
540546 {
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 ;
543549 }
544550
545551 // Read the DOS header
546552 IMAGE_DOS_HEADER dosHeader{};
547553 file.read (reinterpret_cast <char *>(&dosHeader), sizeof (dosHeader));
548554 if (dosHeader.e_magic != IMAGE_DOS_SIGNATURE) // 'MZ'
549555 {
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 ;
552558 }
553559
554560 // Seek to the PE header
@@ -559,32 +565,30 @@ BOOL HostFxrResolver::IsX64(const WCHAR* dotnetPath)
559565 file.read (reinterpret_cast <char *>(&peSignature), sizeof (peSignature));
560566 if (peSignature != IMAGE_NT_SIGNATURE) // 'PE\0\0'
561567 {
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 ;
564570 }
565571
566572 // Read the file header
567573 IMAGE_FILE_HEADER fileHeader{};
568574 file.read (reinterpret_cast <char *>(&fileHeader), sizeof (fileHeader));
569575
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 )
576578 {
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;
584591 }
585-
586- LOG_INFOF (L" %ls is unknown architecture %i" , dotnetPath, fileHeader.Machine );
587- return false ;
588592}
589593
590594std::optional<fs::path>
0 commit comments