Porting a .NET desktop app to macOS and Linux, and the bugs a VM didn’t show me
Description and use
Porting a .NET desktop app to macOS and Linux uncovered many cross‑platform issues, resolved by configuring rendering, tooltips, locale, Dock‑aware gestures, Finder services, code signing, and file watching.
Problem
A C# file‑converter app that worked only on Windows needed to run on macOS and Linux, but cross‑platform Avalonia revealed numerous platform‑specific bugs.
Outcome
Filee now runs on macOS and Linux with full functionality, including drag gestures, locale handling, Dock‑aware gestures, Finder services, proper code signing, and robust file watching.
Workflow
- 1. Enable 3D acceleration in VMware macOS VM to allow Avalonia’s RenderTimer.
- 2. Set a non‑null tooltip before attaching the tray icon on macOS.
- 3. Use CoreFoundation’s CFLocaleCopyPreferredLanguages to determine UI language and list localizations in Info.plist.
- 4. Skip windows with layer >0 when detecting the window under the cursor to avoid the Dock.
- 5. Implement a macOS service by registering an Objective‑C class at runtime that handles convertFiles:userData:error: and declare it in Info.plist.
- 6. Sign all files in Contents/MacOS (including non‑Mach‑O assemblies) before signing the executable and bundle; fix CRLF in entitlements with .gitattributes.
- 7. Extend file‑watcher logic to wait longer for file stability and skip files with creation date 24 Jan 1984 on macOS.
- 8. Deploy on Linux with install.sh, add file‑manager actions for Nautilus, Nemo, Thunar, Dolphin; use drop window for Wayland.
- 9. Run CI on GitHub runners to capture screenshots and verify functionality.
Evidence
Avalonia.Native was not able to start the RenderTimer. Native error code is: -6661
System.ArgumentNullException: Value cannot be null. (Parameter 'chars') at Avalonia.Native.Interop.Impl.__MicroComIAvnTrayIconProxy.SetToolTipText(String text)
CFLocaleCopyPreferredLanguages
codesign on the main executable failed with "code object is not signed at all" pointing at Microsoft.CSharp.dll
- Record date: 2026-10-10T00:55:52.801Z