Repository navigation
Feature Request - ARM64 support on .NET Framework 4.8.1 #4155
Description
Activity
Note that using
arm64for C++/CLI projects targeting .NET Framework seems to require VS 2022 17.3 and using thev143toolset, as that includes an ARM64 version ofmscoree.lib. However, the actual .NET target framework of the project can be a lower one, e.g. .NET Framework 4.5.2.For regular .NET Framework projects, using
arm64asPlatformTypeseems to already work with VS 2019 (16.11), even forExeprojects when using a lower target framework like 4.5.2.I think that once we can use VS 2022 17.3 to build CefSharp (with AppVeyor), adding ARM64 support for .NET Framework would be possible in principle without changing the target framework of the projects (except for the C++/CLI projects which would need to use the C++
v143toolset forarm64).The only open points I can think of is where the process architecture needs to be determined. For example,
DependencyCheckerneeds to check forarm64to excludeD3DCompiler_47.dllfrom the files list (#3841), butRuntimeInformation.ProcessArchitectureis only available since .NET Framework 4.7.1.Also, class
CefRuntimeusesEnvironment.Is64BitProcess()to distinguish betweenx86andx64, which would incorrectly result inx64when running asarm64, but that seems to only be used for support ofAnyCPUapplications which wouldn't run asarm64anyway (AnyCPUapps run either asx86(ifPrefer32Bitis set) or asx64on Windows 11 Version 22H2 ARM64, even when targeting .NET Framework 4.8.1).AnyCPU apps can be run as ARM64 (or any other architecture, excluding ARM32 since .NET Framework ARM32 is not available) with
start /machine <arch> your-app.exein Windows 11 22H2. Not sure about other ways of doing this.One possible workaround might be just P/Invoke
IsWow64Process2(Note x64 on ARM64 is not considered as WOW64 process sopProcessMachinewould beIMAGE_FILE_MACHINE_UNKNOWN), andGetProcessInformationwithProcessInformationClass = ProcessMachineTypeInfo(which detects x64 on ARM64 correctly but only available in Windows 11)Reacted by Konstantin PreißerHi,
AnyCPU apps can be run as ARM64 (or any other architecture, excluding ARM32 since .NET Framework ARM32 is not available) with start /machine your-app.exe in Windows 11 22H2.
Thank you for the info! You are right, with this command I was able to run an
AnyCPU.NET Framework application (targeting 4.7.2) asARM64(whenPrefer32Bitwasfalse). So it seems we also need to consider the case inCefRuntimefor ARM64.One possible workaround might be just P/Invoke
IsWow64Process2(Note x64 on ARM64 is not considered as WOW64 process sopProcessMachinewould beIMAGE_FILE_MACHINE_UNKNOWN), andGetProcessInformationwithProcessInformationClass = ProcessMachineTypeInfo(which detects x64 on ARM64 correctly but only available in Windows 11)Alternatively, maybe we could also try to use reflection to get
RuntimeInformation.ProcessArchitectureto determine the process architecture. If this is not available, it must be an older .NET Framework version (before 4.7.1) that cannot run as ARM64, where thenEnvironment.Is64BitProcesscan be used.(For
IsWow64Process2, note that it is only available starting with Windows 10 build 16299 (RS3).)The command should be
start /machine arm64 your-app.exebut I guess you've already figured that out ;).Reacted by Konstantin PreißerNote that using
arm64for C++/CLI projects targeting .NET Framework seems to require VS 2022 17.3 and using thev143toolset, as that includes an ARM64 version ofmscoree.libAdding the required variants to the project files should be relatively easy. If someone wants to kick this off by creating a PR that only gets the basics building then by all means feel free. Avoid package changes for now.
The packaging will be a problem, upgrading to
VS2022will either require updating the minimum requiredVC++runtime or building with the olderv142tools assuming we can find a build host with support.I'd rather avoid upgrading the minimum
VC++version forx86andx64, so that's something we'll need to look into.Issue cefsharp/cef-binary#93 will also need to be resolved before any sort of package can be created.
For testing purposes the examples already use the
chromiumembeddedframework.runtimepackages.The only open points I can think of is where the process architecture needs to be determined. For example,
DependencyCheckerneeds to check forarm64to excludeD3DCompiler_47.dllfrom the files list (#3841), butRuntimeInformation.ProcessArchitectureis only available since .NET Framework 4.7.1.Seeing if we can use reflection seems like a reasonable first step for this and
CefRuntime.Reacted by Konstantin PreißerAs with
ARM64support for.Net 5.0+I'll be relying on the community to contribute and test as I don't have anARM64device.The packaging will be a problem, upgrading to
VS2022will either require updating the minimum requiredVC++runtime or building with the olderv142tools assuming we can find a build host with support.Issue #4640 will track upgrading to
VC++ 2022(usingVS2022as the build version). IfCEFstarts usingC++20features then we will be forced to upgrade.- marked CefSharp.Common is missing nuget ARM64 dependency #5122 as a duplicate of this issue
on Jun 20, 2025 Has there been any movement towards building CefSharp that supports ARM64? It certainly would be a very nice feature!
Out of interest, is the blocker the VS22 upgrade, v143 toolset, or relying on .net 4.7.1 for RuntimeInformation.ProcessArchitecture?
Has there been any movement towards building CefSharp that supports ARM64?
Not that I'm aware of. You can of course use
.Net 5.0 or greaterThis is currently blocked on #4640
Reacted by stojThis is currently blocked on #4640
This issue has been resolved.
It should now be possible to implement this if someone wants to contribute a
PR.Hi @amaitland
I appreciate yours and @jamescharters effort in getting this one across the line.
Do you have an ETA when the new PR #5267 will be merged in and released?
Thanks.
No ETA. The build is passing on CI. I have no means of testing it.
Once it's been tested it can be merged.
2 remaining items
Hi @amaitland, I'm just following up on my earler post.
Do you have a pre-release nuget package available with the ARM support? If so, I'm happy to test it.
Thanks for the offer. Once I've pushed M150 I'll see about a set of packages to test.
Hopefully on the weekend
MyGet has unfortunately been having issues, builds have more often than not failed to push packages.
Seems like it's back up (though they have had recurring issues lately, so if you have issues then we'll have to look at another option).
https://ci.appveyor.com/project/cefsharp/cefsharp/builds/54435032
https://www.myget.org/F/cefsharp/api/v3/index.json
Should be version 150.0.110-CI5572
I've managed to install the v150 package ok and code builds without issue.
As per the attached image, it unfortunately it doesn't create/copy the cef binaries into the bin\debug\arm64 folder.

Fortunately, it's an easy one to reproduce by creating a new WPF .net framework project and then add the CefSharp.Wpf package. The x64 and x86 folders are correctly populated, but the arm64 folder and contents are missing. If it helps, I've attached the verbose build output from a fresh project.
Hopefully it's something simple.
Some good news though, I've manually copied the binaries into the arm64 folder.. and CefSharp/chromium now works on ARM64 running .net framework :)
Thanks for testing, quick check and it does appear that there are some missing entries in
NuGet/CefSharp.Common.targetsforAnyCPU, so they will need to be added.hi @amaitland
*.targets files are not something I've had a lot of experience. with. But please let me know if there's anything I can do to assist to get this across the line.
And hopefully you'll be able to verify any changes locally regarding the nuget installation as I don't believe this relies on having an ARM CPU.
Hi,
We was following this and was very happy about all the progress during summer. I have also tested the PR changes on an arm machine using a test wpf client. As you said the targets need to be updated for AnyCPU. When using AnyCPU I also had to add
<PreferNativeArm64>true</PreferNativeArm64>to my project to avoid x64 emulation on my test machine.Thanks for the good work.
Here are the changes I used to build the nugets locally to test with. Let me know if I can help with something to get this approved.
diff --git a/NuGet/CefSharp.Common.targets b/NuGet/CefSharp.Common.targets index 3a54a6a0..63899918 100644 --- a/NuGet/CefSharp.Common.targets +++ b/NuGet/CefSharp.Common.targets @@ -118,6 +118,7 @@ <CefSharpTargetDir Condition="'$(CefSharpTargetDir)' != '' AND !HasTrailingSlash('$(CefSharpTargetDir)')">$(CefSharpTargetDir)\</CefSharpTargetDir> <CefSharpTargetDirAnyCpu32>$(CefSharpTargetDir)x86\</CefSharpTargetDirAnyCpu32> <CefSharpTargetDirAnyCpu64>$(CefSharpTargetDir)x64\</CefSharpTargetDirAnyCpu64> + <CefSharpTargetDirAnyCpuArm64>$(CefSharpTargetDir)arm64\</CefSharpTargetDirAnyCpuArm64> <!-- For Sdk Projects the PlatformTarget is unreliable (https://github.com/dotnet/sdk/issues/1560) When our targets file is imported $(PlatformTarget) will be x86 when the Platform is infact AnyCPU. @@ -232,6 +233,12 @@ <PublishState>Included</PublishState> <Visible>false</Visible> </None> + <None Include="@(CefRedistArm64)"> + <Link>$(CefSharpTargetDirAnyCpuArm64)%(RecursiveDir)%(FileName)%(Extension)</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + <PublishState>Included</PublishState> + <Visible>false</Visible> + </None> <None Include="@(CefSharpCommonBinaries32)"> <Link>$(CefSharpTargetDirAnyCpu32)%(RecursiveDir)%(FileName)%(Extension)</Link> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> @@ -244,6 +251,12 @@ <PublishState>Included</PublishState> <Visible>false</Visible> </None> + <None Include="@(CefSharpCommonBinariesArm64)"> + <Link>$(CefSharpTargetDirAnyCpuArm64)%(RecursiveDir)%(FileName)%(Extension)</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + <PublishState>Included</PublishState> + <Visible>false</Visible> + </None> <!-- Include CefSharp.dll and CefSharp.Core.dll (we only need CefSharp.dll but it's easier to include both) in the arch specific folders as required by the BrowserSubProcess. @@ -260,6 +273,12 @@ <PublishState>Included</PublishState> <Visible>false</Visible> </None> + <None Include="@(CefSharpCommonManagedDll)"> + <Link>$(CefSharpTargetDirAnyCpuArm64)%(RecursiveDir)%(FileName)%(Extension)</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + <PublishState>Included</PublishState> + <Visible>false</Visible> + </None> </ItemGroup> </When> <!-- x86 and Win32--> @@ -335,6 +354,13 @@ <Visible>false</Visible> <IncludeInVsix>true</IncludeInVsix> </Content> + <Content Include="@(CefRedistArm64)"> + <Link>$(CefSharpTargetDirAnyCpuArm64)%(RecursiveDir)%(FileName)%(Extension)</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + <PublishState>Included</PublishState> + <Visible>false</Visible> + <IncludeInVsix>true</IncludeInVsix> + </Content> <Content Include="@(CefSharpCommonBinaries32)"> <Link>$(CefSharpTargetDirAnyCpu32)%(RecursiveDir)%(FileName)%(Extension)</Link> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> @@ -349,6 +375,13 @@ <Visible>false</Visible> <IncludeInVsix>true</IncludeInVsix> </Content> + <Content Include="@(CefSharpCommonBinariesArm64)"> + <Link>$(CefSharpTargetDirAnyCpuArm64)%(RecursiveDir)%(FileName)%(Extension)</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + <PublishState>Included</PublishState> + <Visible>false</Visible> + <IncludeInVsix>true</IncludeInVsix> + </Content> <!-- Include CefSharp.dll and CefSharp.Core.dll (we only need CefSharp.dll but it's easier to include both) in the arch specific folders as required by the BrowserSubProcess. @@ -367,6 +400,13 @@ <Visible>false</Visible> <IncludeInVsix>true</IncludeInVsix> </Content> + <Content Include="@(CefSharpCommonManagedDll)"> + <Link>$(CefSharpTargetDirAnyCpuArm64)%(RecursiveDir)%(FileName)%(Extension)</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + <PublishState>Included</PublishState> + <Visible>false</Visible> + <IncludeInVsix>true</IncludeInVsix> + </Content> </ItemGroup> </When> <!-- x86 and Win32-->
Hi @amaitland
Sorry to nag, but do you know when you could merge in the changes from @M4ttsson and release a new nuget package?
I can certainly verify it very quickly.
Thanks
Someone is welcome to submit a PR with the proposed changes, just target https://github.com/cefsharp/CefSharp/tree/netarm64
Hi @amaitland,
I have submitted #5288, targets the netarm64 branch. I verified again today that the project builds properly using both AnyCpu and Arm64.
Please let me know if there is something more I can do or if I should update something in the PR.
Try the 152 release, it includes these changes
Reacted by stoj and M4ttssonThanks everyone. I've just integrated v152 and it looks perfect. We now have an ARM native .net framework build :)
I've also upgraded to v152 now and everything works. Thanks. :)
Bulk of the work to support Windows ARM64 is done. The only feature that will help is if CefSharp could also be compiled for .NET Framework ARM64 support.
It should merely be recompiling the managed components and the managed C++ components but leaving the rest of the native parts unchanged.
This will allow applications that are running on .NET Framework 4.8.1 on Windows 11 ARM64 to work flawlessly.