Introduction
Windows on ARM is now mainstream thanks to Copilot+ PCs and Snapdragon X Elite/Plus systems. For the best performance, battery life, and compatibility, you want apps that run natively as ARM64 or ARM64EC instead of through x64 emulation (Microsoft’s new Prism). This guide shows you exactly how to check if your app has an ARM64/ARM64EC build, how to find and install the right one, how to validate what’s running, and what to expect in performance. You’ll also learn requirements, troubleshooting steps, and best practices for developers, IT admins, and power users.
What you’ll get:
- Practical ways to detect architecture for installed apps and installers
- Step-by-step commands to discover and install ARM64/ARM64EC builds
- Methods to benchmark native vs emulated performance
- Known issues, fixes, and optimization tips
- Real-world examples (Dev/IT-focused) to put it all into practice
Why it matters:
- Native ARM64 apps typically start faster, use less power, and feel smoother than emulated x64 apps
- ARM64EC lets you mix native ARM speed with x64 plug-in support where needed
- Some drivers and plug-ins simply won’t work under emulation—knowing your options prevents surprises
The Big Picture: Windows on ARM, Prism, and App Architectures
- Windows on ARM: Windows 11 running on ARM-based SoCs (e.g., Snapdragon X Elite/Plus). It supports native ARM apps and emulates x64/x86 apps via Prism.
- Prism emulation: The latest generation of x64/x86 emulation for Copilot+ PCs. It’s fast and compatible, but native ARM64 is still faster and more efficient in most cases.
- ARM64 vs ARM64EC:
- ARM64: Fully native ARM binary. Best performance/efficiency when the whole app and its dependencies are ARM64.
- ARM64EC: Hybrid ABI that lets ARM64-native code load x64 plug-ins/libraries in the same process. Excellent when you need x64 plug-ins (e.g., creative tools, enterprise plug-ins), while keeping most of the app native.
- x64/x86: Intel/AMD builds. On Windows on ARM, these run under Prism. Many apps work fine, but you’ll typically see higher CPU use and sometimes compatibility quirks.
- Drivers: Kernel-mode drivers must be ARM64. There is no emulation for kernel-mode drivers.
Compatibility and Key Facts You Should Know
- Kernel-mode drivers must be ARM64 (VPN clients, anti-cheat, security/EPP, storage filters, some peripherals).
- Shell extensions, plug-ins, and in-process add-ons must match the host’s architecture.
- UWP/MSIX packages can include per-architecture binaries; Store installs the matching one automatically.
- Frameworks:
- .NET 6+ and .NET Framework support ARM64. Use ARM64 .NET runtime where applicable.
- Java (OpenJDK 17/21+) is available for Windows ARM64.
- Python wheels exist for win_arm64; ensure your native extensions have ARM64 wheels.
- Electron has ARM64 builds; many popular apps already ship arm64 MSIs or ZIPs.
- Package managers:
- winget: First-class support for per-architecture installers (arm64, x64, x86).
- Microsoft Store: Generally chooses the right architecture automatically.
- Scoop/Chocolatey: Many manifests support ARM64; check each package.
Common states you’ll see in the wild
- Fully native ARM64 app
- ARM64 app hosting x64 plug-ins via ARM64EC
- x64-only app running under Prism emulation
- App uses a native ARM64 UI but relies on x64 helper tools/drivers (may not work)
- Store app that is “Neutral” (MSIL) or includes multiple architectures (Store selects ARM64)
Quick compatibility snapshot
- Runs great: Pure user-mode apps with ARM64 builds, Store apps with ARM64 packages, .NET/C++ apps compiled for ARM64.
- Works via emulation: Most x64 apps without kernel drivers or low-level hooks.
- Known pain points: Kernel-mode drivers (VPNs, device utilities), legacy shell extensions, low-level security products, certain anti-cheat modules.
Requirements and Prerequisites
- A Copilot+ PC or other Windows 11 on ARM device.
- Windows 11 24H2 or later recommended for the latest Prism improvements.
- Up-to-date OEM drivers/firmware (via Windows Update and/or OEM utility).
- ARM64 runtimes as needed:
- Microsoft Visual C++ Redistributable ARM64 (if your app depends on MSVC runtime).
- .NET Runtime ARM64 (for .NET apps).
- Java ARM64 (if running JVM apps).
- For devs:
- Visual Studio 2022 with ARM64/ARM64EC toolsets and Windows SDK installed.
- If cross-compiling, set up CI to produce win-arm64 and/or ARM64EC artifacts.
Step-by-Step: How to Check If Your App Has an ARM64/ARM64EC Build (and Find One)
Method 1: Check running processes quickly in Task Manager
- Open Task Manager > Processes.
- Right-click any column header > Select columns > enable Architecture.
- Review the Architecture column:
- ARM64: native.
- ARM64EC: hybrid ARM64 host capable of x64 plug-ins.
- x64 or x86: running under Prism emulation.
Method 2: Inspect the file’s PE header with PowerShell (works for .exe and .dll)
Use this script to identify the PE machine type of any binary:
function Get-PEMachineType {
param([Parameter(Mandatory=$true, ValueFromPipeline=$true)][string[]]$Path)
$map = @{
0x014c = 'x86'
0x8664 = 'x64'
0x01c4 = 'ARM'
0xAA64 = 'ARM64'
0xA641 = 'ARM64EC'
}
foreach ($p in $Path) {
if (-not (Test-Path $p)) { Write-Warning "Not found: $p"; continue }
$fs = [System.IO.File]::OpenRead($p)
try {
$br = New-Object System.IO.BinaryReader($fs)
$fs.Seek(0x3C, 'Begin') | Out-Null
$peHeaderOffset = $br.ReadInt32()
$fs.Seek($peHeaderOffset + 4, 'Begin') | Out-Null
$machine = $br.ReadUInt16()
$arch = $map[$machine]
if (-not $arch) { $arch = ('0x{0:X4}' -f $machine) }
[pscustomobject]@{
Path = $p
MachineHex = ('0x{0:X4}' -f $machine)
Architecture = $arch
}
} finally {
$fs.Dispose()
}
}
}
Examples:
- Single file: Get-PEMachineType “C:\Program Files\MyApp\myapp.exe”
- Entire folder: Get-ChildItem “C:\Program Files\MyApp” -Recurse -Include .exe,.dll | % { Get-PEMachineType $_.FullName }
Tip: If the main EXE is ARM64 but some DLLs are x64, the app likely uses ARM64EC. If any DLLs are x86, they won’t load into a 64-bit process.
Method 3: For Microsoft Store apps, query installed package architecture
- Find the package:
- Get-AppxPackage | Sort-Object Name | Out-GridView
- Check architecture:
- Get-AppxPackage -Name “YourAppName” | Select-Object Name, Version, Architecture
Architecture will display Arm64/Neutral/x64/x86/Arm.
Method 4: Use winget to discover and install ARM64 builds
- Discover installers and architectures:
- winget search “
“ - winget show –id <Publisher.App> (look for Installer Architecture: arm64/x64/x86)
- winget search “
- Force the ARM64 build:
- winget install –id <Publisher.App> –architecture arm64
- If you must compare versions:
- winget install –id <Publisher.App> –architecture x64
- Keep installs isolated if the app allows side-by-side.
Method 5: Visual Studio “dumpbin” for developers
If you have Visual Studio Build Tools:
- Dump machine type:
- “C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\
\bin\Hostx64\x64\dumpbin.exe” /headers myapp.exe | findstr /i “machine”
- “C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\
- Expected output includes Machine (ARM64, ARM64EC, x64, x86).
Method 6: Sysinternals tools while running
- Process Explorer: Add columns for Image Type/Architecture and Emulation. This is very informative for ARM64EC hosts that load x64 DLLs.
- Handle/Autoruns: Useful to spot plug-in DLLs and shell extensions and confirm their architectures (use PowerShell PE check above on suspect DLLs).
Method 7: GitHub Releases and vendor downloads
- Look for assets named with arm64, aarch64, win-arm64, WindowsArm64, or ARM64EC.
- Prefer MSIs/MSIX/EXEs specifically labeled arm64.
- For ZIP distributions, check the main EXE with the PowerShell method above before installing.
Method 8: For .NET apps
- Check assembly CPU type:
- corflags MyApp.exe
- Look for 32BIT, 64BIT, AnyCPU; for native-hosted .NET, the actual published runtime matters.
- Ensure you install the ARM64 .NET runtime:
- dotnet –info (verify RID includes win-arm64)
- Publishing for ARM64:
- dotnet publish -r win-arm64 -c Release –self-contained true
Method 9: For Java/Python apps
- Java: Install an ARM64 JDK for Windows (e.g., OpenJDK 17/21 for Windows arm64). Confirm with: java -XshowSettings:properties -version (check os.arch = aarch64 or arm64).
- Python: Ensure win_arm64 wheels are installed. pip debug –verbose shows tags; pip install “
” should pick win_arm64 wheels on ARM64 Python.
Method 10: Check driver architecture (when apps rely on drivers)
- pnputil /enum-drivers
- Look for “Architecture: arm64” on relevant drivers (VPN, security, hardware). If you only see x64 drivers for a device, it will not work on Windows on ARM.
Finding an ARM64/ARM64EC Build When the Site Isn’t Obvious
- Use winget show –id
to list architectures; if arm64 is available, install with –architecture arm64. - Search the vendor’s download page and release notes for “ARM64” or “Windows on ARM.”
- On GitHub, filter release assets by “arm64” or “aarch64.”
- If there’s an ARM64EC build, prefer it when you need x64 plug-in compatibility.
- Use reputable community catalogs and package sources dedicated to Windows on ARM software to quickly discover native builds.
- Contact the vendor’s support/enterprise rep—many have ARM64 builds available upon request or in preview.
Performance and Benchmarks: Native vs Emulated
What to expect
- Native ARM64 or ARM64EC user-mode paths generally deliver better responsiveness and battery life than emulated x64.
- ARM64EC can provide near-native performance in the ARM parts of your app while retaining x64 plug-in compatibility.
- Emulated x64 apps tend to use more CPU for the same workload and may have higher idle draw.
How to measure realistically
- Pick repeatable workloads and isolate variables (same device, power mode, background tasks minimized).
- Benchmark both the ARM64 and x64 (emulated) versions of the same app.
Suggested quick tests
- 7-Zip benchmark
- ARM64 version: 7z b
- x64 version (emulated): 7z b
- Compare MIPS and CPU utilization.
- CLI wall-clock with PowerShell
- Measure-Command { & “C:\Path\to\MyApp_ARM64.exe” –batch test.json }
- Measure-Command { & “C:\Path\to\MyApp_x64.exe” –batch test.json }
- Browser (native ARM64 builds exist for major browsers)
- Use a consistent browser build and profile.
- Speedometer 3 or your web app’s internal perf tests.
- Battery impact
- powercfg /batteryreport
- Run your workload for a fixed time with ARM64 vs x64 and compare energy usage and discharge rates.
Interpreting your results
- If the ARM64 version shows shorter runtimes and lower CPU utilization, stick with it.
- If you rely on x64-only plug-ins, ARM64EC can offer a strong compromise.
- Only stay on emulation when no native or ARM64EC build exists, or compatibility dictates it.
Troubleshooting Common Issues and Proven Fixes
- The installer keeps installing the x64 version
- Use winget install –architecture arm64.
- Uninstall the x64 version first; clear leftover Program Files folders and registry entries if required.
- Check for a separate ARM64 installer on the vendor site or GitHub Releases.
- App crashes or plug-in not loading on ARM64 build
- If the app loads x64 plug-ins, switch to an ARM64EC build of the host if available.
- Replace plug-ins with ARM64 builds. Mixed-architecture in the same process is only supported when the host is ARM64EC.
- VPN/security software not working
- Install ARM64-native drivers and clients. x64 drivers do not work on Windows on ARM.
- Confirm driver architecture: pnputil /enum-drivers
- Missing MSVC/.NET runtime
- Install the ARM64 VC++ Redistributable and ARM64 .NET Runtime.
- For .NET self-contained apps, republish with win-arm64.
- Poor performance on battery
- Ensure you installed the native build.
- Update OEM firmware/drivers.
- Check Windows power mode and disable unnecessary background tasks.
- Store app runs as x64
- Uninstall and reinstall; the Store may now have an ARM64 package.
- Use Get-AppxPackage to verify the installed Architecture.
- Command-line tools fail silently
- Verify the architecture of the tool and its DLLs with the PowerShell PE check.
- Replace any x86 DLLs; they won’t load into a 64-bit process.
Best Practices for Stable, Optimized Windows on ARM Use
- Prefer ARM64 or ARM64EC builds whenever available.
- Keep your device on Windows 11 24H2+ and OEM driver updates.
- Standardize on ARM64 runtimes (VC++, .NET, Java) across your fleet.
- For dev pipelines:
- Produce ARM64 and ARM64EC artifacts.
- For Electron/.NET apps, generate win-arm64 packages in CI.
- Test with ARM64EC when your app has a plug-in ecosystem still on x64.
- For IT:
- Use winget and Microsoft Store for Business/Intune to enforce –architecture arm64.
- Validate drivers and security stack availability on ARM64 before broad rollout.
- Pilot with power users who rely on plug-ins; consider ARM64EC hosts.
- For Docker/WSL:
- Prefer linux/arm64 images on ARM hosts.
- Use buildx to build multi-arch images.
- Keep architecture hygiene:
- Don’t mix x86 DLLs in 64-bit apps.
- Treat shell extensions and in-process add-ons as architecture-specific.
- Have a fallback strategy:
- If only x64 exists, test under Prism; pin that version if stable.
- Track vendors for ARM64 roadmaps; revisit periodically.
Use Case Example 1: IT Pro deploying an ARM64-native browser via winget and Intune
Goal: Ensure Copilot+ PCs get the ARM64 build.
- Discover architectures:
- winget show –id Vendor.Browser
- Confirm Installer Architecture: arm64 is listed.
- Install command:
- winget install –id Vendor.Browser –architecture arm64 –silent –accept-source-agreements –accept-package-agreements
- Intune/Endpoint:
- Add a Win32 app with the winget command or Store app if available.
- Detection: Verify EXE path exists and confirm architecture via a custom detection script using the Get-PEMachineType function.
- Validation:
- On a test device, open Task Manager Architecture column; confirm ARM64.
- Run Speedometer or internal web app tests; confirm performance and lower CPU during sustained browsing.
Use Case Example 2: Developer shipping ARM64EC for a plug-in-heavy Windows app
Goal: Keep core app native while supporting x64 plug-ins.
- Visual Studio setup:
- Install ARM64 and ARM64EC MSVC toolsets and Windows SDKs.
- Build:
- msbuild MyApp.sln /p:Configuration=Release /p:Platform=ARM64EC
- Verify:
- Use the PowerShell PE check on your EXE to confirm Architecture = ARM64EC.
- Launch the app; use Process Explorer to confirm x64 plug-ins are loaded.
- Package:
- Produce ARM64EC installer and add a clear label (“Windows on ARM (ARM64EC)”).
- Document:
- Publish which plug-in paths and versions are supported under ARM64EC.
- Monitor:
- As plug-in vendors add ARM64 builds, consider switching to pure ARM64 host.
Use Case Example 3: Power user comparing native vs emulated CLI tool
- Install both:
- winget install –id Vendor.Tool –architecture arm64
- winget install –id Vendor.Tool –architecture x64 –location “C:\Tools\Tool_x64”
- Benchmark:
- Measure-Command { & “C:\Program Files\Vendor\Tool\tool.exe” –process input.dat }
- Measure-Command { & “C:\Tools\Tool_x64\tool.exe” –process input.dat }
- Validate CPU use and runtime; keep the faster one as default and document the difference.
Conclusion
Windows on ARM is ready for serious work, and the fastest path to a great experience is to run native builds. ARM64 delivers the best performance and efficiency, while ARM64EC gives you a bridge to x64 plug-ins without giving up most of the native benefits. With the methods above, you can quickly detect what you’re running, find the right installers, and validate your results. Whether you’re a developer, IT admin, or power user, you can standardize on ARM64 today and keep emulation as a fallback for edge cases.
FAQ
What’s the difference between ARM64 and ARM64EC?
- ARM64 is a pure ARM build—best performance and power efficiency. ARM64EC is a hybrid format where the host app runs natively on ARM but can load x64 plug-ins and libraries in-process. Choose ARM64EC when you need x64 plug-in compatibility.
How do I force-install an ARM64 build?
- Use winget: winget install –id <Publisher.App> –architecture arm64
- On vendor sites or GitHub, choose the asset labeled arm64/aarch64/win-arm64. Uninstall any x64 version first if the installer picks the wrong architecture.
How can I tell if a Store app is ARM64?
- PowerShell: Get-AppxPackage -Name “AppName” | Select Name, Architecture
- The Store generally installs the right package automatically. If not, uninstall and reinstall (or check if an ARM64 package exists yet).
Do x64 drivers work under Prism emulation?
- No. Kernel-mode drivers (VPN, anti-cheat, storage filters, device utilities) must be compiled for ARM64. Check with pnputil /enum-drivers and vendor documentation.
Is emulation “good enough,” or should I wait for native?
- Prism compatibility and speed are strong, but native ARM64/ARM64EC almost always improves responsiveness and battery life. Use ARM64 whenever available, use ARM64EC for plug-in ecosystems still on x64, and fallback to emulation only when necessary.
