在 .NET macOS 应用程序中访问 AXUIElementCopyAttributValue() 时出现 EXC_BAD_ACCESS (SIGSEGV) 错误

问题描述 投票:0回答:1

我正在 .NET 7.0 中开发一个 macOS 应用程序,它利用辅助功能框架(ApplicationServices -> HIServices)来访问辅助功能。当尝试调用

AXUIElementCopyAttributValues()
函数时,应用程序崩溃并出现
EXC_BAD_ACCESS (SIGSEGV)
错误。

这是我的代码和我的测试存储库的链接

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";
    }

以下是我为解决该问题所采取的步骤:

Info.plist 条目:

我已在 Info.plist 文件中添加了辅助权限所需的密钥:

<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>
在运行时请求权限:

我实现了 RequestAccessibilityPermission() 方法来在运行时请求可访问性权限。

 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.");
     }
 }
自定义库

我还使用 Xcode 使用方法

AXUIElementCreateApplication(_:)
AXUIElementCopyAttributeValue(_:_:_:)
创建了一个自定义 Cocoa 库。我打算在我的 .NET 7.0 macOS 应用程序中通过 P/Invoke 使用这些方法。然而,即使使用这个自定义 Cocoa 库,我也会遇到同样的
EXC_BAD_ACCESS (SIGSEGV)
错误。

权利

此外,我已在权利中禁用沙盒。

<key>com.apple.security.app-sandbox</key>
<false/>
错误

这是错误报告

-------------------------------------
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

有谁有解决此问题的经验并可以提供如何解决该问题的建议吗?我是否应该采取其他步骤来识别和解决错误的根本原因?

.net macos xamarin.mac
1个回答
0
投票

您的方法定义似乎并不完全正确。

我刚刚使用以下导入定义进行了一些测试,结果是成功的。 (注意 - 由于指针的使用,您需要允许您的代码执行不安全的代码)

[DllImport("/System/Library/Frameworks/ApplicationServices.framework/ApplicationServices")]
static extern IntPtr AXUIElementCreateSystemWide();

[DllImport("/System/Library/Frameworks/ApplicationServices.framework/ApplicationServices")]
unsafe static extern int AXUIElementCopyAttributeNames(IntPtr element, IntPtr* names);

[DllImport("/System/Library/Frameworks/ApplicationServices.framework/ApplicationServices")]
unsafe static extern int AXUIElementCopyAttributeValue(IntPtr element, IntPtr attribute, IntPtr* value);

这些看起来对我有用,请参阅下面的示例。请注意,您应该使用的属性名称与头文件中的确切 const 定义不匹配,但使用 CopyAttributeNames,您可以验证存在哪些可能的键。

更改方法定义后,我开始获取正确的错误代码或结果,而不是因内存故障而崩溃。

// get accessibility element
var element = AXUIElementCreateSystemWide();

// fetch the available attributes
IntPtr ptrAttributeNames;
var attributeNamesError = AXUIElementCopyAttributeNames(element, &ptrAttributeNames);

// convert response to a readable array
var attributeNames = CFArray.ArrayFromHandleFunc(ptrAttributeNames, CFString.FromHandle);

// fetch the value for an attribute
IntPtr ptrAttributeValue;
var attributeValueError = AXUIElementCopyAttributeValue(element, CFString.CreateNative("AXSelectedText"), &ptrAttributeValue);
var attributeValue = CFString.FromHandle(ptrAttributeValue);
© www.soinside.com 2019 - 2024. All rights reserved.