Skip to content

Fix: Application cannot be opened.#61

Open
andoan16 wants to merge 2 commits into
ChrisTitusTech:mainfrom
andoan16:fix/macos-app-cannot-be-opened
Open

Fix: Application cannot be opened.#61
andoan16 wants to merge 2 commits into
ChrisTitusTech:mainfrom
andoan16:fix/macos-app-cannot-be-opened

Conversation

@andoan16

@andoan16 andoan16 commented Jul 5, 2026

Copy link
Copy Markdown

Problem

On macOS, MacUtil-Universal.app crashes immediately with the error:

"The application "MacUtil-Universal.app" can't be opened."

The app quits unexpectedly (SIGABRT) before the UI even appears.

Root Cause

.NET PublishSingleFile with IncludeNativeLibrariesForSelfExtract=true extracts native libraries (libSkiaSharp.dylib, libHarfBuzzSharp.dylib, libAvaloniaNative.dylib) to a temp directory (~/.net/MacUtilGUI/...) at runtime. macOS hardened runtime rejects these dylibs because their code signature has a different Team ID from the main executable:

dlopen(...libSkiaSharp.dylib): code signature in ... not valid for use in process:
mapping process and mapped file (non-platform) have different Team IDs

This causes System.DllNotFoundExceptionSystem.TypeInitializationException → SIGABRT.

Changes

  1. MacUtilGUI.fsproj — Set IncludeNativeLibrariesForSelfExtract=false so native dylibs stay in the bundle directory (Contents/MacOS/) alongside the executable instead of being extracted to ~/.net/ at runtime. This eliminates the signature mismatch entirely.

  2. MacUtilGUI.entitlements — Add com.apple.security.cs.disable-library-validation entitlement as defense-in-depth. This allows the .NET runtime to load libraries with different Team IDs, covering edge cases where dylibs may still be extracted or loaded from external paths.

  3. build_universal.sh — Instead of rsync-ing x64-only .dylib files, merge each native library with lipo into universal binaries (matching the main executable). Added ad-hoc signing step for dylibs and bundle after build, so dev builds run without manual codesign/xattr workarounds.

  4. sign_macos.sh — Added a step to individually sign each .dylib with the Developer ID before deep-signing the bundle. This ensures native libraries have consistent signatures that match the main executable under hardened runtime.

Testing

  • Downloaded the existing MacUtil-Universal.app release → confirmed crash (SIGABRT, DllNotFoundException for libSkiaSharp)
  • Applied codesign --force --deep --sign - --options=0x0 (ad-hoc, no hardened runtime) as a manual workaround → app launched successfully
  • The .fsproj change (IncludeNativeLibrariesForSelfExtract=false) is the definitive fix: native libs remain in the bundle where they share the app's signature, so no extraction-related mismatch can occur

andoan16 added 2 commits July 5, 2026 09:01
…ction

The .NET single-file bundle extracts native libraries (libSkiaSharp.dylib,
libHarfBuzzSharp.dylib, libAvaloniaNative.dylib) to ~/.net/ at runtime.
macOS hardened runtime rejects these dylibs because their Team ID differs
from the main executable, causing SIGABRT before the UI even appears.

Root cause: IncludeNativeLibrariesForSelfExtract=true causes .NET to
extract native dylibs to a temp directory where they fail signature
validation under hardened runtime.

Changes:
- MacUtilGUI.fsproj: set IncludeNativeLibrariesForSelfExtract=false so
  native libs stay in the bundle directory alongside the executable
  instead of being extracted at runtime
- MacUtilGUI.entitlements: add com.apple.security.cs.disable-library-validation
  entitlement to allow loading libraries with different Team IDs
  (defense-in-depth for .NET runtime assemblies)
- build_universal.sh: merge .dylib files with lipo instead of rsync-ing
  x64-only copies; ad-hoc sign dylibs and bundle after build so dev
  builds run without manual codesign workarounds
- sign_macos.sh: sign native .dylib files individually before deep-signing
  the bundle, ensuring consistent Developer ID signatures
When IncludeNativeLibrariesForSelfExtract=false, .NET SDK requires
IncludeAllContentForSelfExtract to also be false (error NETSDK1143).
This ensures native dylibs stay as separate files in the publish
output alongside the executable, not embedded in the single-file bundle.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant