Arm 版 Windows 能執行業務應用程式嗎 ── x64 模擬(Prism)與原生 DLL・COM 的現實

· · Windows on Arm, Arm64, x64 模擬, 原生互通, P/Invoke, COM, 驅動程式, C#, .NET, Windows 開發, 技術諮詢

「下個月要換的新電腦是所謂的 Copilot+ PC,我們公司的業務系統能動嗎?」── 隨著搭載 Snapdragon 的 PC 在企業導入日益普及,遇到這個問題的開發公司、資訊系統部門也愈來愈多。型錄上寫著「既有應用程式也能透過模擬執行」。但自家的業務應用程式,在 C# 畫面背後 P/Invoke 呼叫廠商提供的原生 DLL,報表則透過 COM 元件產生,甚至還安裝了專用設備的驅動程式。老實說,面對「能動嗎?」這個問題,實在難以立刻給出答案吧。

先講結論:「應用程式本體大多能動。危險的是應用程式周邊的那些傢伙。」x86/x64 的使用者模式程式碼,Windows 11 的模擬能以相當高的精確度處理,但驅動程式、殼層擴充功能、處理程序內的架構混用,這些「模擬守備範圍之外」的領域確實存在。而這個守備範圍之外的領域,正是業務應用程式一向偏愛使用的地方。

本文將在 Microsoft Learn 可查證的範圍內,整理 Windows on Arm 模擬機制的原理與極限、「處理程序內無法混合 x64 與 Arm64」這項大原則、.NET 應用程式特有的組合問題,以及確認「自家應用程式能否在 Arm 機器上執行」的實務步驟。

1. 先講結論

趕時間的讀者,只要先掌握以下 3 點就足夠了。

  1. 應用程式本體大多能動。 Windows 11 on Arm 可透過作業系統內建的模擬功能執行 x86/x64 應用程式,24H2 以後更有 Prism 帶來的效能提升。1
  2. 危險的是「周邊」。 核心模式驅動程式、像殼層擴充功能或輸入法這類會被載入其他處理程序的 DLL,以及原生 DLL・COM 的架構不一致。能不能動,取決的不是應用程式本體,而是這些周邊。234
  3. 確認只需 3 個階段。 相依項目盤點 → 保持 x64 在 Arm 機器上實機確認 → 有需要時再進行 Arm64 原生化。詳細步驟見第 6 章。

Arm64EC・Arm64X 這兩個名詞會在第 4 章說明,這裡不需要先記住。以下是這 3 點的細項與出處,等需要細節時再回來查閱即可。

  • 純粹的受控(.NET)應用程式,以及一般的 x86/x64 桌面應用程式,在 Arm 版 Windows 11 的模擬下幾乎都能執行。 模擬功能是作業系統內建的,不需要修改應用程式,也不需要額外元件。1
  • 模擬只照顧使用者模式的程式碼。核心模式驅動程式不會被模擬,必須是 Arm64 原生版本。 UMDF 驅動程式與印表機驅動程式,同樣必須與作業系統的架構一致。23
  • 殼層擴充功能、輸入法、輔助技術等「會被載入其他處理程序(如檔案總管)的 DLL」,同樣必須重新編譯成與系統相同的 Arm64。 模擬救不了這一類。4
  • 在同一個處理程序內,x64 與 Arm64 無法混合。 x64/Arm64EC 處理程序只能載入 x64 與 Arm64EC 的二進位檔,Arm64 處理程序則只能載入 Arm64 的二進位檔。x64 的 exe 無法呼叫 Arm64 的 DLL,反過來也不行。5
  • 用單一檔案跨越這項限制的機制,就是 Arm64EC(能與 x64 在同一處理程序內混合的原生 Arm64 程式碼)與 Arm64X(讓 Arm64 與 Arm64EC 共存於同一個 PE 檔案、可被任一種處理程序載入的二進位檔)。會被兩種架構呼叫的 COM 處理程序內伺服器或外掛程式,正是 Arm64X 派上用場的地方。56
  • .NET 自 .NET 6 起正式支援 Windows Arm64(目前受支援的 .NET 8/9/10,官方文件也明確將 Windows 11/10 的 Arm64 列為支援的作業系統),可用 RID win-arm64 進行原生發行。 但另一方面,若在 Arm64 的 .NET 執行環境上執行 AnyCPU 應用程式,處理程序會以 Arm64 執行,因此會出現只有 x64 版本的原生 DLL 在 P/Invoke 時載入失敗的組合問題。785
  • 驗證環境除了實機(Copilot+ PC 等)之外,還可以用 Azure 的 Windows 11 Arm64 VM、可在 Arm 機器上的 Hyper-V 或 Apple Silicon Mac 上使用的 Windows 11 Arm64 ISO 來準備。※x64 機器的 Hyper-V 無法建立 Arm64 VM。910

2. 什麼是 Arm 版 Windows ── 搭載 Snapdragon 的 PC 與 Prism

Arm 版 Windows 是在 Arm64 處理器上執行的 Windows。2024 年以後,「Copilot+ PC」── 搭載每秒可執行 40 兆次以上運算(40+ TOPS)的 NPU 的 Windows 11 PC 新品類 ── 之中,有許多採用了以 Arm 為基礎的 Snapdragon X 系列,使得開發者不得不正視這個存在。1112

支撐與既有應用程式相容性的,是作業系統內建的模擬功能。其運作要點如下。1

  • 模擬器會將 x86/x64 指令區塊 JIT 編譯 成 Arm64 指令,並依模組快取轉換結果,讓第二次以後的啟動更快。
  • Windows 11 能同時模擬 x86 與 x64。 Windows 10 on Arm 只能模擬x86,因此談 x64 業務應用程式,實質上就是以 Windows 11 為前提。
  • Windows 11 24H2 導入了新的模擬器 Prism,效能較以往提升,CPU 使用率也降低了。Prism 針對 Qualcomm Snapdragon 進行了最佳化。
  • 32bit(x86)應用程式,會在與 x64 版 Windows 相同的 WOW64 層上執行,並接受檔案系統、登錄的重新導向。另一方面,x64 應用程式沒有 WOW64 層,由於系統二進位檔是以後述的 Arm64X 格式編譯,x64 應用程式可以不經重新導向,直接存取整個作業系統(包括檔案系統與登錄)。1

在模擬下的應用程式所看到的 CPU 資訊,是「被模擬的虛擬處理器」的資訊。為了相容性,就連 GetNativeSystemInfo 也會回傳被模擬後的值,因此若想知道主機是否為 Arm64,要使用 IsWow64Process2GetMachineTypeAttributes13

另外,針對模擬下出問題的應用程式,Windows 側也準備了一套機制:在 exe 上按右鍵 → 內容 → 相容性頁籤,可以變更模擬設定(預設/安全/嚴格/非常嚴格等預設集,以及個別詳細設定)。這是一項用效能換取相容性的調整,但值得記住,它可以作為「以前在 Windows on Arm 上明明能動」這類情況的退路。14

3. 模擬能救、不能救的範圍

對「能動嗎?」這個問題的答案,取決的不是應用程式本體,而是相依物的種類。在進入細節之前,先按層級掌握模擬的守備範圍在哪裡中斷,之後的判斷會快很多。

層級 位於此處的東西 模擬能否救得了
使用者模式 / 自己的處理程序內 自家應用程式的 exe,以及同一架構的整套 DLL 救得了。 保持 x86/x64 不修改就能動1
使用者模式 / 在同一處理程序內混合不同架構 例如在 x64 處理程序中載入 Arm64 的 DLL 救不了。 用 Arm64EC・Arm64X,或改成分離處理程序來迴避(第 4 章)5
使用者模式 / 進入其他處理程序的 DLL 殼層擴充功能、輸入法、輔助技術、其他公司應用程式的外掛程式 救不了。 必須配合對方的處理程序(Arm64)重新編譯4
核心模式 各類驅動程式(VPN、資安產品、USB 硬體鎖、虛擬印表機) 救不了。 核心中不存在模擬,必須是 Arm6423

界線有兩條:「在自己的處理程序之內還是之外」,以及「使用者模式還是核心模式」。可以說,清點落在這兩條界線之外的相依物,實質上就是 Arm 對應調查的全部工作,一點也不誇張。以下是把同樣的內容,以實際檢討時會用到的單位排列出來的判斷表。

分類 在 Arm 版 Windows 11 上的處理方式 根據・備註
x86/x64 的使用者模式應用程式(exe + 同架構的整套 DLL) 透過模擬執行 不需修改、不需額外安裝1
.NET(受控)應用程式 能執行(也可 Arm64 原生執行) 詳見第 5 章8
核心模式驅動程式 無法執行。必須是 Arm64 原生版本 核心中沒有模擬23
UMDF 驅動程式・印表機驅動程式 必須與作業系統相同的 Arm64 即使應用程式本體能靠模擬執行,依賴驅動程式的功能也無法使用3
殼層擴充功能・輸入法・輔助技術(會被載入其他處理程序的 DLL) 必須重新編譯成 Arm64 檔案總管的右鍵選單、雲端儲存的圖示顯示等4
禁止動態程式碼產生的 x86 應用程式 模擬無法執行 因為模擬器會在執行時期產生 Arm64 指令,需要放寬 ProcessDynamicCodePolicy4
依賴舊版 OpenGL・防作弊驅動程式的遊戲 有時無法執行 超過 OpenGL 3.3 或未支援 Arm 的防作弊機制是障礙15
周邊裝置(印表機、掃描器、專用裝置) 取決於是否有 Arm64 驅動程式 需要作業系統內建或廠商提供的 Arm64 驅動程式15
防毒軟體・「改變 Windows 使用體驗」類軟體 需個別確認 Arm 對應已有進展,但建議逐項確認每個產品15

換成業務應用程式的脈絡來說,危險信號大致如下。

  • VPN 用戶端、資產管理代理程式、資安產品 ── 這些是核心驅動程式的集合體。需要向廠商確認是否有 Arm64 對應版本。
  • USB 硬體鎖認證、專用設備(量測儀器、收付款終端機等) ── 裝置驅動程式是否提供 Arm64 版本,是能否使用的關鍵。
  • 「為檔案總管新增功能」類工具 ── 由於殼層擴充功能會被載入 Arm64 版的檔案總管,保持 x64 就無法運作。
  • 即使應用程式本體不屬於上述任何一種,安裝程式內附驅動程式的情況(例如以虛擬印表機驅動程式方式輸出 PDF)同樣會踩到相同的問題。

4. 處理程序內無法混合架構 ── P/Invoke 與 COM 的現實

從 32bit 時代開始,就有「64bit 處理程序無法載入 32bit DLL」這條鐵則16。Arm 版 Windows 也有結構相同的鐵則。官方對能否載入的規則整理如下。5

處理程序的架構 x64 DLL Arm64EC DLL Arm64 DLL Arm64X DLL
x64 / Arm64EC 處理程序 可載入 可載入 不可 可載入
Arm64 處理程序 不可 不可 可載入 可載入

這裡出現的兩種機制,是思考 Arm 對應設計時的關鍵。

  • Arm64EC(Emulation Compatible)是一種原生 Arm64 程式碼的 ABI,透過遵循 x64 的呼叫慣例、堆疊使用方式與資料配置,能在同一個處理程序內與以模擬方式執行的 x64 程式碼混合。當 x64 應用程式在 Windows 11 on Arm 上執行時,載入該處理程序的作業系統程式碼大多是以 Arm64EC 編譯的,在應用程式渾然不覺的情況下以原生速度執行。即使相依 DLL 仍是 x64,也可以先把自己的程式碼逐步改為 Arm64EC 化來提升效能,作為漸進式遷移的手段。5
  • Arm64X 是一種讓傳統 Arm64 程式碼與 Arm64EC 程式碼共存於同一個 PE 檔案的二進位格式。載入的處理程序若是 x64,就表現得像 x64 的 DLL;若是 Arm64,就表現得像 Arm64 的 DLL,因此適合用在可能被兩種架構的處理程序呼叫的 DLL上。官方文件列舉了需要 Arm64X 的情況,包括「同時被 x64 與 Arm64 應用程式呼叫的 64bit COM 伺服器」「會被 x64/Arm64 任一種應用程式載入的外掛程式」「被注入 x64/Arm64 處理程序的單一二進位檔」。6

具體化成業務應用程式會實際遇到的問題吧。

情況 1:x64 的 exe + x64 的原生 DLL(P/Invoke)。 只要整個處理程序都統一為 x64,就能整套在模擬中執行。不能因為「只想讓一部分變快」就混入 Arm64 的 DLL(依上表所示是不可的)。

情況 2:COM 處理程序內伺服器。 COM 的 in-proc 伺服器就只是一個 DLL,因此上表的規則直接適用。x64 用戶端只能使用 x64(或 Arm64EC/Arm64X)的 COM DLL,一旦把應用程式 Arm64 原生化,x64 的 COM DLL 就無法載入了。若需要同時支援兩種架構,可以把 DLL 改成 Arm64X,或者套用在 32bit↔64bit 時代就已有實績的跨處理程序 COM/IPC 分離(把處理程序分開、以處理程序間通訊連接)這一定石。用處理程序邊界跨越架構之牆,自古以來就是基本作法。166

情況 3:自己主控外掛程式,或被其他程式主控。 Excel 增益集、業務套裝軟體的外掛程式、列印中介軟體等,「自己的 DLL 會被載入對方的處理程序」這種形態,必須配合對方的架構。反過來,若自家應用程式本身是外掛程式的主控端,那麼把自家應用程式 Arm64 化,就會讓所有 x64 的第三方外掛程式全數失效,這一點需要事先評估影響範圍。

順帶一提,手邊的二進位檔究竟是哪一種,可以在開發人員命令提示字元中確認。5

link /dump /headers MyLibrary.dll

要看的只有 FILE HEADER VALUES 之後緊接著的那一行。官方文件中列出的輸出格式如下。5

File Type: EXECUTABLE IMAGE
FILE HEADER VALUES
    8664 machine (x64) (ARM64X)

要判讀的就是這行 machine

machine 這一行 二進位檔的種類
8664 machine (x64) x64
8664 machine (x64) (ARM64X) 部分內容已重新編譯為 Arm64EC(從 x64 處理程序看來就是 x64)
AA64 machine (ARM64) Arm64
AA64 machine (ARM64) (ARM64X) Arm64X。x64/Arm64 任一種處理程序都能載入

由於輸出內容很長,實務上會接上 link /dump /headers MyLibrary.dll | findstr machine,只取出這一行。另外,若用相同指令檢查建置過程中的 OBJ/LIB,會顯示 A641 machine (ARM64EC),但這是 MSVC 內部的識別碼,並不是最終 EXE/DLL 的 machine 值。5

如果只是想確認已經在執行中的應用程式,也可以在工作管理員的「詳細資料」頁籤中顯示「架構」欄位。以 Arm64EC 編譯的執行檔,會顯示為 ARM64 (x64 compatible)5

5. .NET 應用程式的情況 ── AnyCPU 的陷阱與架構判定

.NET(Core 系)自 .NET 6 起正式支援 Windows Arm64,目前受支援的 .NET 8/9/10,官方文件也明確將 Windows 11/10 的 Arm64 列為支援的作業系統。發行時只要在 RID 指定 win-arm64 即可。177

<!-- csproj: 針對 Arm64 原生版本進行發行 -->
<PropertyGroup>
  <TargetFramework>net8.0-windows</TargetFramework>
  <RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
</PropertyGroup>
dotnet publish -r win-arm64 -c Release

如果是純粹只有受控程式碼的應用程式,這樣 Arm64 原生化幾乎就完成了。JIT 只是吐出 Arm64 程式碼,基本上不需要修改原始碼。至於 .NET Framework 應用程式,.NET Framework 4.8.1 新增了 Arm64 原生支援(針對 Windows 11 的 Arm64 機器;4.8.1 執行環境並不支援在 Windows 10 的 Arm 機器上執行原生 Arm64 應用程式)。保持 x64 建置的 Framework 應用程式,則視為以模擬方式執行。1819

問題出在P/Invoke 呼叫原生 DLL 時的組合上。在 Arm 機器上,「因為是 .NET 應用程式,用 AnyCPU 到哪都能動」這種行之多年的直覺會被背叛。

  • 用 Arm64 的 .NET SDK/執行環境執行時,應用程式預設會以 Arm64 處理程序執行8
  • Arm64 處理程序無法載入 x64 的 DLL(第 4 章的表)。也就是說,即使 AnyCPU 的自家程式碼毫髮無傷,DllImport 呼叫的 x64 原生 DLL 仍會載入失敗5
  • 反過來,以 win-x64 發行的應用程式,整個處理程序都會是 x64,並在模擬中執行(連同 x64 原生 DLL 一起)。這種情況下雖然得不到 Arm64 原生的效能,卻是相容性最高的組態。12

看起來「有時能動、有時不能動」的真面目,多半是處理程序的架構,與原生相依物的架構不一致。作為釐清問題的第一步,若能用程式碼確認正在執行的處理程序究竟是以什麼架構跑,調查會輕鬆許多。

using System.Runtime.InteropServices;

// 處理程序本身的架構(若在 x64 模擬下則為 X64)
Console.WriteLine($"Process: {RuntimeInformation.ProcessArchitecture}");

// 作業系統本來的架構(Arm 機器則為 Arm64)
Console.WriteLine($"OS: {RuntimeInformation.OSArchitecture}");

有一點要注意,OSArchitecture 回傳「剝除模擬後、本來的作業系統架構」是從 .NET 7 開始的行為。在此之前,模擬下會回傳 X64,因此在 .NET 6 以前用這個 API 判斷「是否為 Arm 機器」的程式碼,並不會如預期運作。2021

整理一下 .NET 特有的檢查重點。

  • NuGet 套件的原生資產:只有 runtimes/win-x64/native 的套件,在 win-arm64 發行時就沒有可依靠的東西。要在套件內容(或原始儲存庫)中確認是否有 win-arm64 資產。RID 正是為了這種「依平台分派專屬資產」而存在的機制。7
  • 開發機的 SDK 組態:在 Arm 機器上,Arm64 版 .NET 會安裝在一般的 C:\Program Files\dotnet\,x64 版 SDK 則安裝在 C:\Program Files\dotnet\x64\,兩者可以共存。dotnet run 的執行架構會依 PATH 或 DOTNET_ROOT 指向哪一個而改變,驗證時請留意這一點。17
  • 例外的判讀方式:受控組件的架構不一致,會以 BadImageFormatException 呈現(官方參考文件中也明確記載,發生條件之一是「載入以不同平台為目標的元件」)。22

6. 自家應用程式的 Arm 對應檢查清單

實務上,依以下 3 個階段確認會比較有效率。

階段 要做的事 判斷
① 相依項目盤點 列出 P/Invoke 呼叫的原生 DLL、COM 元件、內附驅動程式、殼層擴充功能、含原生資產的 NuGet 若驅動程式・殼層擴充功能為,前景樂觀。若有,則確認各廠商的 Arm64 對應狀況34
② 模擬下的實機確認 保持 x64 建置安裝到 Arm 機器(或 Arm64 VM),跑過一輪主要業務情境 若能動,「保持 x64 運行」就是可行選項。動不了的部分,要懷疑相依物與架構不一致1
③ 評估 Arm64 原生建置 .NET 就發行 win-arm64,C++ 則新增 Arm64 組態,確認是否能建置通過 建置不過的常見原因是相依函式庫沒有 Arm64 版本。可考慮更新、替換,或善用 Arm64EC23

也一併整理第 4 章看到的各種情況,分別會在哪個階段發揮作用。

第 4 章的情況 主要作用的階段 要看的重點
情況 1:x64 的 exe + x64 的原生 DLL ② 實機確認 整個處理程序統一為 x64,能動的可能性高。要確認的與其說是能不能動,不如說是速度是否落在實用範圍內
情況 2:COM 處理程序內伺服器 ① 盤點 → ③ 的判斷 那個 COM DLL 是誰提供的。確認是否有提供 Arm64X 版本的計畫,若沒有就考慮跨處理程序分離
情況 3:主控外掛程式,或被主控 ① 盤點(對方的架構) 把自家應用程式 Arm64 化,會讓 x64 的第三方外掛程式無法使用。進入 ③ 之前要先確定影響範圍

為了 ②③ 所需的驗證環境,有以下幾個選項。

  • 實機:Copilot+ PC 等搭載 Snapdragon 的機器。手邊有一台,連故障調查都能包含在內,是最保險的做法。12
  • Azure VM:在 Azure 入口網站以 Arm64 篩選映像檔,即可建立 Windows 11 的 Arm64 VM(建議大小為 D2ps_v5 等,以 Ampere Altra 為基礎)。優點是即使手邊完全沒有 Arm 機器,也能開始驗證。9
  • 本機 VM:官方有配發 Windows 11 Arm64 的 ISO,可以在Arm 機器上的 Hyper-V,或以 Arm 為基礎的 Apple Silicon Mac 上建立 VM。請注意,x64 機器的 Hyper-V 無法建立 Arm64 VM10

第三方產品的對應狀況,可以在 Microsoft 提供的對應狀況網站(Windows on Arm Ready Software)確認。除此之外,對於自行開發的業務應用程式(LOB)或 ISV 應用程式的相容性問題,還有一個名為 App Assure 的官方支援窗口。在「動不了、走投無路」之前有這樣一個可用的窗口,這一點在向資訊系統部門說明時也很有說服力。1215

整理判斷自家是否為適用對象的依據如下。2425

項目 內容
定位 FastTrack 特典的一部分。包含在對象的 Microsoft 365・Windows 方案中,無需額外費用
適用條件 依循 FastTrack 的適用條件。基準是每一租戶購買150 個以上對象方案授權,對象方案包括 Microsoft 365 E3/E5、Microsoft 365 Business Premium、Microsoft Intune、Enterprise Mobility + Security 等
支援範圍 Windows 10/11、Microsoft 365 Apps、Azure Virtual Desktop、Microsoft Edge、Windows on Arm64 PC、Windows 365。對象應用程式為自行開發的 LOB 應用程式・ISV 應用程式・Microsoft 產品
申請窗口 透過 Request for Assistance 表單申請。整個方案的說明請見 aka.ms/appassure
開發者專用的另一窗口 針對在 Arm 對應作業中卡關的開發者,官方也提供了 App Assure Arm Advisory Service 的申請窗口

要確認自家的授權組態是否適用,最快的方式是把上面的方案名稱,拿去與資訊系統・採購部門的合約內容核對。授權數量的條件與對象方案清單可能會變動,實際申請前請務必到 FastTrack 適用條件的頁面確認最新內容。

7. 目前的現實解法 ── 三個選項的搭配使用

Arm 對應並不是「全部原生化」這一個選項。反而對多數業務應用程式來說,階段性地搭配使用才是現實的解法。

選項 適合的情況 注意事項
(a) 保持 x64,以模擬方式運行 不依賴驅動程式・殼層擴充功能,且效能也在實用範圍內的情況 Prism(24H2 以後)已改善效能。要讓整個處理程序統一為 x64,不要混入 Arm64 二進位檔15
(b) 確認・等待廠商的 Arm64 對應 原生 DLL・驅動程式為第三方產品的情況 確認「是否有提供 Arm64 版(或 Arm64X 版)DLL 的計畫」。驅動程式除了等待之外沒有其他迴避方式323
(c) Arm64 原生建置 純 .NET 應用程式,或相依項目的 Arm64 版本已備齊的情況。效能・電池續航是需求的情況 條件是發行 win-arm64 + 所有原生相依項目都完成 Arm64 化。若是外掛程式的主控端,要留意影響範圍75

若 C++ 資產規模龐大,在 (a) 與 (c) 之間還有 Arm64EC 這個中間選項。它可以在保留 x64 相依 DLL 不變的情況下,只把自己的程式碼逐步原生化,是「龐大的 x64 應用程式無法一口氣遷移」這種情況的官方路線。523

在開發環境方面,Visual Studio 有 Arm64 原生版本,並備有可在 Arm 機器上以 Arm64/x64/x86 為目標的完整編譯器工具組。CI 用的建置,用既有的 x64 建置機器交叉編譯也做得出來,因此容易組出「只把測試執行交給 Arm 實機/VM」這種架構。2623

8. 總結

  • Arm 版 Windows 11 可透過作業系統內建的模擬功能執行 x86/x64 應用程式,24H2 以後更有 Prism 帶來的效能提升。x64 模擬是從 Windows 11 才開始的,Windows 10 on Arm 僅限 x86。
  • 模擬的守備範圍僅限使用者模式。核心模式/UMDF/印表機的各種驅動程式,以及殼層擴充功能・輸入法・輔助技術這類「會被載入其他處理程序的 DLL」,都必須是 Arm64 原生版本。業務應用程式能不能動,取決的不是應用程式本體,而是這些周邊相依項目。
  • 處理程序內無法混合 x64 與 Arm64。x64/Arm64EC 處理程序能載入 x64+Arm64EC,Arm64 處理程序則只能載入 Arm64。COM 處理程序內伺服器與外掛程式都遵循同樣的規則,若要同時支援兩種架構,Arm64X 是定石;若要跨越處理程序邊界,則以跨處理程序 COM/IPC 為定石。
  • .NET 可以用 win-arm64 進行原生發行,但 Arm64 執行環境上的 AnyCPU 應用程式會以 Arm64 處理程序執行,因此若 P/Invoke 呼叫僅有 x64 版本的原生 DLL 就會失敗。可以用 RuntimeInformation.ProcessArchitecture / OSArchitecture(.NET 7 以後)來釐清問題。
  • 確認步驟是「相依項目盤點 → 保持 x64 以模擬方式實機確認 → 有需要時再進行 Arm64 原生化」這 3 個階段。驗證環境可以用 Azure 的 Arm64 VM 或 Arm64 ISO 準備,企業還能獲得 App Assure 的支援。
  • 目前的現實解法,是搭配使用「若靠模擬就能動,就保持原狀」「確認驅動程式・DLL 廠商的對應狀況」「視需求進行 Arm64 原生化(C++ 也可用 Arm64EC 分階段遷移)」這三種做法。

相關文章

相關諮詢領域

合同會社小村軟體處理既有業務應用程式能否對應 Arm 版 Windows 的調查、包含原生 DLL・COM 互通的應用程式架構遷移設計,以及「只在 Arm 機器上動不了」這類故障的原因分析。

參考連結

  1. Microsoft Learn, How emulation works on Arm。關於模擬功能是作業系統內建、可執行未修改的應用程式,Windows 11 同時支援 x86/x64、Windows 10 on Arm 僅支援 x86,x86 指令區塊的 JIT 轉換與快取機制,Windows 11 24H2 的 Prism 與針對 Snapdragon 的最佳化,以及 x86 應用程式在 WOW64 下接受重新導向、x64 應用程式不經 WOW64 而使用 Arm64X 系統二進位檔。  2 3 4 5 6 7 8

  2. Microsoft Learn, How emulation works on Arm。關於模擬僅支援使用者模式程式碼、不支援驅動程式,以及核心模式元件必須以 Arm64 編譯。  2 3 4

  3. Microsoft Learn, Troubleshooting x86 desktop apps。關於所有核心模式驅動程式・UMDF 驅動程式・印表機驅動程式都必須與作業系統的架構一致,即使應用程式本體能靠模擬執行,依賴驅動程式的功能仍無法使用。  2 3 4 5 6 7

  4. Microsoft Learn, Troubleshooting x86 desktop apps。關於讓自己的 DLL 被載入 Windows 處理程序的應用程式(殼層擴充功能・輸入法・輔助技術)必須配合系統架構(Arm64)重新編譯,以及禁止動態程式碼產生的 x86 應用程式無法用模擬執行。  2 3 4 5 6

  5. Microsoft Learn, Arm64EC - Build and port apps for native performance on Arm。關於 x64/Arm64EC 處理程序能載入 x64 與 Arm64EC 的二進位檔、Arm64 處理程序只能載入 Arm64 二進位檔的互通對應表,Arm64EC 遵循 x64 的軟體規約、能在同一處理程序內與 x64 程式碼混合,x64 應用程式的處理程序中所載入的作業系統程式碼大多為 Arm64EC,以及用 link /dump /headers 確認二進位檔種類的方法。  2 3 4 5 6 7 8 9 10 11 12 13 14

  6. Microsoft Learn, Arm64X PE files。關於 Arm64X 讓 Arm64 與 Arm64EC 的程式碼共存於同一個 PE 檔案、可被 x64/Arm64 任一種處理程序載入,以及會被兩種架構的應用程式呼叫的 64bit COM 伺服器・外掛程式・注入 DLL,被列為需要 Arm64X 的情況。  2 3

  7. Microsoft Learn, .NET RID Catalog。關於 win-arm64 被定義為 Windows 的 RID,以及 RID 被用來分派 NuGet 套件的平台專屬資產。  2 3 4

  8. Microsoft Learn, Windows on Arm。關於用 Arm64 版 .NET SDK 執行時預設會以 Arm64 執行,目前受支援的 .NET 8/9/10 被列為原生 Arm64 執行的對象,以及既有的 x64 .NET 應用程式會靠作業系統的 x64 模擬執行。  2 3

  9. Microsoft Learn, Quickstart: Create a Windows on Arm virtual machine in the Azure portal。關於可在 Azure 入口網站以 Arm64 篩選映像檔,建立 Windows 11 的 Arm64 VM(建議大小 D2ps_v5,以 Ampere Altra 為基礎)。  2

  10. Microsoft Learn, Windows 11 Arm ISO files overview。關於官方配發 Windows 11 Arm64 的 ISO,可在 Arm 機器上的 Hyper-V 或 Apple Silicon Mac 上建立 VM,以及 x64 硬體的 Hyper-V 不支援 Arm64 VM。  2

  11. Microsoft Learn, Develop AI applications for Copilot+ PCs。關於 Copilot+ PC 是搭載每秒可執行超過 40 兆次運算(40+ TOPS)的 NPU 的 Windows 11 硬體新品類。 

  12. Microsoft Learn, Windows on Arm。關於 Windows 10 支援 x86、Windows 11 新增了 x64 的免修改執行,許多 Copilot+ PC 採用 Snapdragon X 系列,以及 Arm 對應狀況確認網站(Works on Windows on Arm)與 App Assure Arm Advisory Service 的存在。  2 3 4

  13. Microsoft Learn, How emulation works on Arm - Detecting emulation。關於模擬下的應用程式所看到的是被模擬的虛擬處理器資訊,GetNativeSystemInfo 為了相容性同樣回傳被模擬後的值,以及偵測 Arm64 主機要使用 IsWow64Process2 或 GetMachineTypeAttributes。 

  14. Microsoft Learn, Adjust emulation settings on Arm。關於可在 exe 內容的相容性頁籤變更 Prism 的模擬設定(預設/安全/嚴格/非常嚴格等預設集與個別設定)。 

  15. Microsoft Learn, Arm-based Surface devices FAQ。關於 Arm 裝置的限制事項(驅動程式需為 Arm 專用設計、周邊裝置取決於是否有 Arm64 驅動程式、超過 OpenGL 3.3 或未支援防作弊機制的遊戲、輸入法等自訂類應用程式、防毒軟體需個別確認),以及包含 LOB 應用程式在內的 App Assure 相容性支援。  2 3 4

  16. Microsoft Learn, Process Interoperability。關於 64bit 處理程序無法載入 32bit DLL(反之亦然),以及可透過跨處理程序 COM 伺服器與 RPC 跨越架構邊界通訊的定石。  2

  17. Microsoft Learn, Install .NET on Windows。關於 Windows 11/10 的 Arm64 是 .NET 8/9/10 的支援對象,在 Arm 機器上 Arm64 版 .NET 會安裝於 C:\Program Files\dotnet\、x64 版 SDK 則安裝於 C:\Program Files\dotnet\x64\,以及可能需要調整 PATH 或 DOTNET_ROOT。  2

  18. Microsoft Learn, What’s new in .NET Framework。關於 .NET Framework 4.8.1 新增了 Arm64 原生支援,在效能上優於在 Arm64 上以模擬方式執行的 x64 程式碼。 

  19. Microsoft Learn, Develop Apps for Windows IoT Enterprise。關於 .NET Framework 4.8.1 的原生 Arm64 支援是針對 Windows 11,4.8.1 執行環境並不支援在 Windows 10 裝置上執行原生 Arm64 應用程式。 

  20. Microsoft Learn, RuntimeInformation.OSArchitecture under emulation。關於自 .NET 7 起,OSArchitecture 在 Windows Arm64 上即使是模擬中的處理程序也會回傳 Arm64(在此之前會回傳 X64),以及判斷處理程序架構應使用 ProcessArchitecture。 

  21. Microsoft Learn, RuntimeInformation.ProcessArchitecture Property / RuntimeInformation.OSArchitecture Property。關於取得執行中處理程序的架構與作業系統本來架構的 API。 

  22. Microsoft Learn, BadImageFormatException Class。關於當應用程式的元件以不同平台為目標時(載入不同架構的組件),會發生 BadImageFormatException。 

  23. Microsoft Learn, Add Arm support to your Windows app。關於阻礙 Arm64 建置的典型因素(未對應的相依函式庫、架構特定程式碼、核心驅動程式)與對策,保留 x64 相依項目、以 Arm64EC 重新建置的選項,取得測試用 Arm 實機・VM 的方式,以及交叉編譯建置與 Arm 環境測試的組合。  2 3 4

  24. Microsoft Learn, App Assure - Compatibility Cookbook。關於 App Assure 是 FastTrack 特典的一部分,包含在對象 Microsoft 365・Windows 方案中且無需額外費用,支援對象包括 Windows 10/11・Microsoft 365 Apps・Azure Virtual Desktop・Microsoft Edge・Windows on Arm64 PC・Windows 365,以自行開發的 LOB 應用程式・ISV 應用程式・Microsoft 產品的相容性問題為對象,以及可透過 Request for Assistance(aka.ms/appassurerequest)提出申請。 

  25. Microsoft Learn, Eligibility - FastTrack。關於 FastTrack 的支援在每一租戶購買 150 個以上對象授權時提供,以及對象方案包括 Microsoft 365 E3/E5、Microsoft 365 Business Premium、Microsoft Intune、Enterprise Mobility + Security 等。 

  26. Microsoft Learn, Visual Studio on Arm-powered devices。關於可用 Arm64 原生版 Visual Studio 進行 .NET/C++ 開發,並提供可從 Arm64 主機以 Arm64/x64/x86 為目標的 MSVC 工具組。 

共用相同標籤的最新文章。能以相近的主題延伸理解。

與本文相近的主題頁面。以本文為起點,可進一步連到相關服務與其他文章。

本文連結到以下服務頁面,歡迎從最接近的入口查看。

常見問題

整理諮詢這個主題時常見的問題。

Arm 版 Windows 能執行一般的 x64 業務應用程式嗎?
多數情況下能執行。Windows 11 on Arm 內建了可不經修改直接執行 x86/x64 應用程式的模擬功能,Windows 11 24H2 以後更有名為 Prism 的新模擬器帶來效能提升。不過模擬只照顧使用者模式的程式碼,核心模式驅動程式,以及像檔案總管這類會被載入其他處理程序的殼層擴充功能・輸入法之流,都必須是 Arm64 原生版本。請這樣理解:能不能動,取決的不是應用程式本體,而是周邊的相依項目。
x64 的 exe 可以呼叫 Arm64 的 DLL 嗎?
不行。同一個處理程序內無法混合 x64 與 Arm64 的二進位檔,x64(或 Arm64EC)處理程序只能載入 x64 與 Arm64EC 的二進位檔,Arm64 處理程序則只能載入 Arm64 的二進位檔。反方向(Arm64 的 exe 呼叫 x64 的 DLL)同樣不行。如果無論如何都需要一個能同時支援兩種架構的 DLL,可以使用讓 Arm64 與 Arm64EC 程式碼共存於一個檔案的 Arm64X 格式,或改成把處理程序分開、以 IPC 互通的架構。
要讓 .NET 應用程式對應 Arm64,需要做什麼?
.NET 6 以後正式支援 Windows Arm64,目前受支援的 .NET 8/9/10,官方文件也明確將 Windows 11/10 的 Arm64 列為支援的作業系統。只要在 publish 時指定 RID(執行環境識別碼)win-arm64,就能產生 Arm64 原生的執行檔。如果只有純粹的受控程式碼,這樣就幾乎完成了;但若有 P/Invoke 呼叫的原生 DLL,或含有原生資產的 NuGet 套件,就需要逐一確認是否存在對應的 Arm64 版本。若是 .NET Framework 應用程式,4.8.1 支援在 Windows 11 上進行 Arm64 原生執行。
在 Arm 版 Windows 上動不了的是哪些軟體?
首推包含核心模式驅動程式的軟體。由於驅動程式不會被模擬,VPN 用戶端、資安產品、虛擬裝置、USB 硬體鎖認證等,若沒有 Arm64 驅動程式就無法運作。其次是殼層擴充功能・輸入法・輔助技術這類會把 DLL 載入作業系統側處理程序的軟體、禁止動態程式碼產生的應用程式,以及依賴舊版 OpenGL 或防作弊驅動程式的遊戲等。周邊裝置也是由是否有 Arm64 驅動程式來決定能不能使用。

作者檔案

本文作者的個人檔案頁面。

Go Komura

小村軟體有限公司 代表

以 Windows 軟體開發、技術諮詢與故障調查為中心,在難以重現的故障調查與既有資產仍在運作的專案上具有優勢。

回到部落格一覽