Sep 28, 2026 · Platforms · About 9 min read

v2rayN Desktop (Avalonia) vs. WPF: Which Windows, macOS, or Linux Package Should You Install?

Compare v2rayN’s cross-platform Avalonia desktop app with the Windows-only WPF version. See the differences in UI, system tray, and platform support, then choose the right package for your OS.

At a glance

Windows users can choose between the cross-platform Desktop app and the classic WPF interface; macOS and Linux users should install the Desktop package for their OS. Check your operating system and processor architecture first, then verify runtime requirements, tray behavior, and whether the core starts successfully. This guide covers package selection, installation, migration, and troubleshooting so you don’t mistake UI framework differences for protocol or node differences.

Desktop vs. WPF: The difference is the UI, not the subscription format

Avalonia is a cross-platform desktop UI framework, while WPF is designed for Windows. v2rayN Desktop uses Avalonia and is available for Windows, macOS, and Linux; the WPF version is for Windows. Cross-platform means the project can publish separate builds for different operating systems—not that one installer runs on all three.

v2rayN manages subscription groups, node selection, routing, and core processes. The selected core establishes the proxy connection. Whether protocols such as VMess and VLESS work depends on the core version, node transport settings, and server configuration—not on whether Avalonia or WPF draws the window. Changing the UI won’t fix an outdated subscription or add protocol support to an incompatible core.

FeatureDesktop(Avalonia)WPF
Supported operating systemsWindows, macOS, and Linux; choose a package for your OSWindows
UI and scalingCross-platform controls; system fonts and scaling settings still applyWindows desktop controls and window behavior
System tray and closing behaviorDepends on the OS, desktop environment, and client settingsIntegrates with the Windows notification area
Protocol supportDepends on the core and configuration in useAlso depends on the core and configuration
System proxy and TUNCheck integration methods and permissions for each OSCheck Windows permissions and network settings

Package selection: Check your OS and architecture before choosing a UI

First rule out packages that can’t run on your device. On Windows, choose Desktop or WPF based on your UI preferences and hands-on testing. Don’t switch UI frameworks just because a node fails to connect.

Choosing an installer for Windows, macOS, or Linux

Check three things when downloading: operating system, processor architecture, and package format. In filenames, x64 usually means a 64-bit Intel or AMD desktop processor; arm64 means a 64-bit ARM processor. Both are 64-bit, but they aren’t interchangeable. Whether the package includes a runtime is a separate detail—check the download page.

3 operating systems
Desktop’s supported platforms
1 operating system
WPF is for Windows
64-bit
x64 and arm64 are both 64-bit, but use different architectures

The recommendation below applies to users who want a similar interface across multiple desktop operating systems. It doesn’t mean Desktop is always a better fit than WPF on Windows. Check the download center for the available architectures and package types.

Desktop: Use across operating systems

Recommended

Download the build for Windows, macOS, or Linux. The interfaces are similar, but system proxy, tray, and permissions still work differently on each OS.

Best for: Users who switch between desktop operating systems and want a consistent workflow.

WPF: A Windows-only setup

If you use only Windows, are familiar with the classic interface, and your current setup is stable, you can stick with WPF. A classic UI doesn’t mean the core is outdated; check core status separately.

Best for: Windows users who want to keep their familiar window and system tray workflow.

On macOS and Linux, you can check your architecture in Terminal. This command only reads system information and won’t change network settings:

uname -m

x86_64 usually corresponds to x64; arm64 or aarch64 corresponds to 64-bit ARM. On Linux, check the package notes to confirm required graphics libraries, runtimes, and system libraries are available. Matching the architecture is only the first step.

Test the interface, system tray, and background behavior separately

Desktop and WPF may differ in font rendering, list density, scaling, menu placement, and keyboard shortcut feedback. If text looks too large or dialogs extend off-screen on a high-resolution display, first check system scaling and scaling settings across monitors. Then determine whether the issue is with the client UI. Don’t start by deleting subscriptions or routing settings.

Closing a window doesn’t necessarily quit the app. Whether it minimizes to the tray or leaves a core process running depends on client settings and system tray support in your OS. Linux desktop environments vary widely in their support for status icons, so a missing icon doesn’t prove the core has stopped.

  1. Keep the main window open on first launch: Select a node and check the logs for a successful core startup. If it fails, note the error message first.
  2. Check what happens when you close the window: Click the close button, then use Task Manager or your system’s process tool to see whether the client is still running.
  3. Check the tray: On Windows, look in the hidden notification area icons; on macOS, check the menu bar; on Linux, see whether your desktop environment supports status icons.
  4. Verify a normal exit: Quit from the app menu or tray menu when possible. Then check that the system proxy is back to the expected state. Don’t force-quit the process as your usual way to exit.

Moving from WPF to Desktop: Handle subscriptions and system settings separately

Back up your existing data before migrating. Include subscription URLs, group details, custom routing, and any essential settings. This information may contain access credentials, so store it securely. Don’t copy every configuration file from the old folder over the data directory for another build or version; internal formats and paths may not be compatible.

Migration plan: Keep the old setup and test the new one separately

Old setup: Save what you need to restore
  • Note your subscription groups and update method.
  • Save custom routing rules and DNS settings.
  • Note local listening ports, system proxy, and TUN status.
  • Stop the proxy and core before starting the new setup.
New setup: Start with a basic test
  • Add your subscription groups again through the client UI.
  • Choose an available node you’ve already tested and start the core.
  • Test the local proxy first, then check the system proxy.
  • Restore custom routing, DNS, and TUN settings last.

Migrating one item at a time makes issues easier to track. You can fetch subscriptions again, but local permissions, file paths, and desktop integration need to be checked anew.

A subscription update provides node details from the service provider; it doesn’t sync all local settings from the old client. Check group update intervals, custom rules, keyboard shortcuts, and window behavior individually. When moving between operating systems, don’t reuse old absolute paths as-is.

If you keep both apps on the same device, run only one at a time. Two processes may compete to control the system proxy, listen on the same port, or create a virtual network adapter, making problems harder to diagnose. After testing, decide which instance to keep and check startup settings so the old one doesn’t take over again after a reboot.

After installation, test the local proxy first, then check system proxy and TUN

“The UI opens” and “the proxy works” are two separate checks. The first means the graphical app has started; the second also requires a working core executable, valid node settings, a local inbound, and correct routing. If you’re told a runtime is missing, install the dependency listed in the package notes or choose a suitable package. If the core fails to start, check its logs instead of blaming Avalonia.

  1. Check core status: Review the startup logs and first rule out a missing core, insufficient execution permissions, or a port conflict. On Linux, check that the app’s location allows executables to run.
  2. Check the local inbound: Open Settings → Parameter Settings and check the actual listening address, port, and inbound type. The layout may vary between versions, so use the values shown in the UI.
  3. Test the proxy separately: Make a request with the proxy address specified explicitly to rule out interference from apps that may not read the system proxy settings.
  4. Test the system proxy: Once the local inbound works, configure your browser to use the system proxy. The system proxy doesn’t force every app to use a proxy.
  5. Test TUN last: Enable it only if you need to capture traffic from apps that aren’t proxy-aware. Check system permissions, routing, and DNS. TUN capturing traffic doesn’t mean every destination will use the proxy route.

Here’s an example using a SOCKS inbound at 127.0.0.1:10808 that you’ve confirmed is listening locally. This is only a test example, not a guarantee of the default port in your installation. If the UI shows a different port, replace it. On Windows, use curl.exe in Terminal to call curl explicitly; on macOS and Linux, use curl.

curl --proxy socks5h://127.0.0.1:10808 --head --connect-timeout 10 https://example.com/

socks5h sends domain name resolution through the proxy, while --connect-timeout 10 sets a 10-second timeout for the connection phase. This request can help check whether the current route reaches the destination, but one response can’t confirm that all routing and DNS settings are correct. If it immediately reports that the local port is unreachable, check whether the port is listening. If it times out after connecting, check the node, exit route, and destination connectivity.

Package selection and migration FAQs

I’m already using WPF on Windows. Do I need to switch to Desktop?

There’s no need to migrate just because the UI framework is different. Start by listing your actual needs: do you want a similar interface across operating systems, or are you seeing a reproducible display or interaction issue? If your current setup is stable, back it up and test Desktop separately. Don’t replace the old setup before you’ve verified the new one.

Why won’t an .exe file I downloaded open on macOS?

You downloaded a package for the wrong operating system. Go back to the download center, choose the macOS Desktop package, and select arm64 or x64 for your processor. Renaming a file extension won’t change the operating system a program targets or add missing dependencies.

The Linux window works, but the tray icon is missing. What should I do?

Keep the main window open, confirm your desktop environment supports status icons, then check the client’s window-close settings. Use your system’s process tool to see whether the app is still running in the background. Tray icons are part of desktop integration and don’t indicate core connection status.

Why is routing different after switching to Desktop if my subscription is the same?

Check the selected core, custom routing, rule data, DNS, and system proxy status in turn. The same subscription means the nodes come from the same source; it doesn’t mean your local routing settings are identical. First test with a request that explicitly specifies the proxy inbound, then restore your original rules one by one.

Can I install an x64 package directly on an ARM device?

Don’t rely on a compatibility layer as your first option. Check whether the download center offers an arm64 package for your OS. If you must use compatibility software, verify separately that both the UI app and bundled core can run. A successful UI launch doesn’t guarantee the core will execute.

Download v2rayN