I'm developing a macOS application in .NET 7.0 that utilizes the Accessibility Framework (ApplicationServices -> HIServices) to access assistive features. When attempting to invoke the AXUIElementCopyAttributValues() function, the application crashes with the EXC_BAD_ACCESS (SIGSEGV) error.
Here is my code and a link to my test repository:
public partial class ProgramTest
{
public void MainTest()
{
AccessibilityHelper.RequestAccessibilityPermission();
string bundleIdentifier = "com.apple.Safari";
NSRunningApplication app = NSRunningApplication.GetRunningApplications(bundleIdentifier)?.First();
if (app != null)
{
int processId = app.ProcessIdentifier;
IntPtr appElement = AXUIElementCreateApplication((uint)processId);
IntPtr mainWindow;
if (AXUIElementCopyAttributeValue(appElement, kAXMainWindowAttribute, out mainWindow) == 0)
{
Console.WriteLine("Main Window Handle: " + mainWindow);
}
else
{
Console.WriteLine("Could not retrieve the main window.");
}
}
else
{
Console.WriteLine("Application not found.");
}
}
const string accessibilityFramework = "/System/Library/Frameworks/ApplicationServices.framework/Versions/Current/ApplicationServices";
[DllImport(accessibilityFramework)]
static extern IntPtr AXUIElementCreateApplication(uint pid);
[DllImport(accessibilityFramework)]
static extern int AXUIElementCopyAttributeValue(IntPtr element, string attribute, out IntPtr value);
const string kAXMainWindowAttribute = "kAXTitleAttribute";
}
public static class AccessibilityHelper
{
public static void RequestAccessibilityPermission()
{
NSString key = new NSString(AXTrustedCheckOptionPrompt);
NSDictionary options = NSDictionary.FromObjectAndKey(NSNumber.FromBoolean(true), key);
IntPtr optionsPtr = options.Handle;
bool isTrusted = AXIsProcessTrustedWithOptions(optionsPtr);
if (!isTrusted)
{
Console.WriteLine("User denied accessibility permission.");
}
}
const string accessibilityFramework = "/System/Library/Frameworks/ApplicationServices.framework/Versions/Current/ApplicationServices";
[DllImport(accessibilityFramework)]
static extern bool AXIsProcessTrustedWithOptions(IntPtr options);
const string AXTrustedCheckOptionPrompt = "AXTrustedCheckOptionPrompt";
}
Here are the steps I've taken to address the issue:
Info.plist Entries:
I've added the required keys for Accessibility Permissions in my Info.plist file:
<key>NSAppleEventsUsageDescription</key>
<string>We need accessibility permissions to interact with other applications.</string>
<key>NSAccessibilityUsageDescription</key>
<string>We need accessibility permissions to interact with other applications.</string>
Requesting Permissions at Runtime:
I implemented a RequestAccessibilityPermission() method to request Accessibility Permissions at runtime.
public static void RequestAccessibilityPermission()
{
NSString key = new NSString(AXTrustedCheckOptionPrompt);
NSDictionary options = NSDictionary.FromObjectAndKey(NSNumber.FromBoolean(true), key);
IntPtr optionsPtr = options.Handle;
bool isTrusted = AXIsProcessTrustedWithOptions(optionsPtr);
if (!isTrusted)
{
Console.WriteLine("User denied accessibility permission.");
}
}
Custom Library
I've also created a custom Cocoa Library using Xcode with the methods AXUIElementCreateApplication(_:) and AXUIElementCopyAttributeValue(_:_:_:). I intend to use these methods through P/Invoke in my .NET 7.0 macOS application. However, I'm encountering the same EXC_BAD_ACCESS (SIGSEGV) error even when using this custom Cocoa Library.
Entitlements
Additionally, I have disabled the Sandbox in the entitlements.
<key>com.apple.security.app-sandbox</key>
<false/>
Error
Here is the error report
-------------------------------------
Translated Report (Full Report Below)
-------------------------------------
Process: netMacOSTest [70764]
Path: /Users/USER/*/netMacOSTest.app/Contents/MacOS/netMacOSTest
Identifier: com.companyname.netMacOSTest
Version: 1.0 (1)
Code Type: X86-64 (Translated)
Parent Process: vsdbg-ui [70763]
Responsible: VisualStudio [491]
User ID: 501
Date/Time: 2023-12-07 15:44:18.6174 +0100
OS Version: macOS 14.0 (23A344)
Report Version: 12
Anonymous UUID: E66ED467-F839-D06D-428B-00BCDEEAD568
Time Awake Since Boot: 610000 seconds
System Integrity Protection: enabled
Notes:
PC register does not match crashing frame (0x0 vs 0x10344B8E8)
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000746954584180
Exception Codes: 0x0000000000000001, 0x0000746954584180
Termination Reason: Namespace SIGNAL, Code 11 Segmentation fault: 11
Terminating Process: exc handler [70764]
VM Region Info: 0x746954584180 is not in any region. Bytes after previous region: 22442082320769 Bytes before following region: 12514185690752
REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL
MALLOC_NANO 600000000000-600020000000 [512.0M] rw-/rwx SM=PRV
---> GAP OF 0x1fcae3f00000 BYTES
MALLOC_TINY 7fcb03f00000-7fcb04000000 [ 1024K] rw-/rwx SM=PRV
Error Formulating Crash Report:
PC register does not match crashing frame (0x0 vs 0x10344B8E8)
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 <translation info unavailable> 0x10344b8e8 ???
1 HIServices 0x7ff81c30f1e0 AXUIElementCopyAttributeValue + 95
2 ??? 0x116ecfdbe ???
3 ??? 0x116ecafd2 ???
4 ??? 0x116ecae4a ???
5 libcoreclr.dylib 0x10d478d89 CallDescrWorkerInternal + 124
6 libcoreclr.dylib 0x10d478d89 CallDescrWorkerInternal + 124
Does anyone have experience with this issue and can provide advice on how to resolve it? Are there additional steps I should take to identify and address the root cause of the error?