差分
ナビゲーションに移動
検索に移動
[[Mac OS X]]のGlobal Event Monitorなどの一部の[[API]]は[[システム環境設定]]にあるアクセシビリティの許可がされていない状態では機能しない。
恐ろしいことにアクセシビリティの許可がされていない状態でGlobal Event MonitorなどのAPI呼び出しを行ってもスルーされるだけで[[エラー]]も何も発生しない。 この挙動は確実に半年くらいしてどんな実装だったかを忘れたころにトラブルになり、[[エラー]]も出ないので[[デバッグ]]も捗らず原因不明の[[バグ]]に悩まされ[[デスマーチ]]突入は決定的である。
これを回避するためアプリ起動時にアクセシビリティの許可がされているかを確認し、未許可であれば警告を出す必要がある。
==実装:ApplicationServicesフレームワークを使用する==
ApplicationServicesという標準フレームワークのAPIを叩くことで実現できる。
管理者権限は必要ない。
なお、[[Mac OS X 10.8]]([[Mountain Lion]])以前はAXAPIEnabledメソッドを使用し、[[Mac OS X 10.9]]([[Mavericks]])以降はAXIsProcessTrustedWithOptionsメソッドを使用するようになっており、[[OS]]のバージョンにより叩くべきメソッドが異なる。これはアクセシビリティの設定が、Mac OS X 10.8まではOSにひとつの許可設定であったが、Mac OS X 10.9からはアプリ単位の許可設定となったためだと思われる。
[[Xamarin.Mac]]にはApplicationServicesフレームワーク関連のライブラリが無いようなので直接叩いてやる。
<source lang="csharp">
using System;
using System.Runtime.InteropServices;
using MonoMac.Foundation;
namespace PrivacyAccessibility
{
public static class ApplicationServices
{
public const string DllName = "/System/Library/Frameworks/ApplicationServices.framework/ApplicationServices";
[DllImport(DllName)]
public extern static bool AXIsProcessTrustedWithOptions(IntPtr option);
[DllImport(DllName)]
public extern static bool AXAPIEnabled();
public static bool IsCurrentProcessTrusted()
{
var dic = NSDictionary.FromFile(@"/System/Library/CoreServices/SystemVersion.plist");
var osVersion = new Version(dic["ProductVersion"].ToString());
Console.WriteLine(osVersion);
if (new Version(10,9) <= osVersion)
{// 10.9 Mavericks以降
var options = IntPtr.Zero;
return AXIsProcessTrustedWithOptions(options);
}
else
{// 10.8 Mountain Lion以前
return AXAPIEnabled();
}
}
}
}
</source>
AXIsProcessTrustedWithOptionsメソッドの引数に「AXTrustedCheckOptionPrompt」に「1」を設定して渡してやると、アプリのアクセシビリティが未許可の場合に[[システム環境設定]]を開くかを確認するダイアログが表示される。なお、ダイアログが表示されても、そこで[[スレッド]]は止まらずに即座に[[戻り値]]「false」が返されて続行される。
<source lang="csharp">
var options = NSDictionary.FromObjectAndKey(new NSNumber(1), new NSString("AXTrustedCheckOptionPrompt"));
AXIsProcessTrustedWithOptions(options.Handle);
</source>
また、古い[[OS]]の場合は自前でダイアログを表示する必要がある。新旧に対応し、かつ統一感を出すには自前で警告ダイアログを実装した方がいいかもしれない。これらの理由によりアクセシビリティの許可設定の確認と未許可時の警告ダイアログの表示は別々に処理した方が良いと思われる。
*[[MonoMac/モーダルウインドウを作成する]]
*[[Xamarin.Mac/システム環境設定を開く]]
==関連項目==
*[[Xamarin.Mac/Global Event Monitorでキー入力を監視する
*[[Xamarin.Mac/OSのバージョンを取得する]]
*[[MonoMac/モーダルウインドウを作成する]]
*[[Xamarin.Mac/システム環境設定を開く]]
==参考文献==
{{reflist}}
{{stub}}
[[category:Xamarin.Mac]]
[[category:MonoMac]]
恐ろしいことにアクセシビリティの許可がされていない状態でGlobal Event MonitorなどのAPI呼び出しを行ってもスルーされるだけで[[エラー]]も何も発生しない。 この挙動は確実に半年くらいしてどんな実装だったかを忘れたころにトラブルになり、[[エラー]]も出ないので[[デバッグ]]も捗らず原因不明の[[バグ]]に悩まされ[[デスマーチ]]突入は決定的である。
これを回避するためアプリ起動時にアクセシビリティの許可がされているかを確認し、未許可であれば警告を出す必要がある。
==実装:ApplicationServicesフレームワークを使用する==
ApplicationServicesという標準フレームワークのAPIを叩くことで実現できる。
管理者権限は必要ない。
なお、[[Mac OS X 10.8]]([[Mountain Lion]])以前はAXAPIEnabledメソッドを使用し、[[Mac OS X 10.9]]([[Mavericks]])以降はAXIsProcessTrustedWithOptionsメソッドを使用するようになっており、[[OS]]のバージョンにより叩くべきメソッドが異なる。これはアクセシビリティの設定が、Mac OS X 10.8まではOSにひとつの許可設定であったが、Mac OS X 10.9からはアプリ単位の許可設定となったためだと思われる。
[[Xamarin.Mac]]にはApplicationServicesフレームワーク関連のライブラリが無いようなので直接叩いてやる。
<source lang="csharp">
using System;
using System.Runtime.InteropServices;
using MonoMac.Foundation;
namespace PrivacyAccessibility
{
public static class ApplicationServices
{
public const string DllName = "/System/Library/Frameworks/ApplicationServices.framework/ApplicationServices";
[DllImport(DllName)]
public extern static bool AXIsProcessTrustedWithOptions(IntPtr option);
[DllImport(DllName)]
public extern static bool AXAPIEnabled();
public static bool IsCurrentProcessTrusted()
{
var dic = NSDictionary.FromFile(@"/System/Library/CoreServices/SystemVersion.plist");
var osVersion = new Version(dic["ProductVersion"].ToString());
Console.WriteLine(osVersion);
if (new Version(10,9) <= osVersion)
{// 10.9 Mavericks以降
var options = IntPtr.Zero;
return AXIsProcessTrustedWithOptions(options);
}
else
{// 10.8 Mountain Lion以前
return AXAPIEnabled();
}
}
}
}
</source>
AXIsProcessTrustedWithOptionsメソッドの引数に「AXTrustedCheckOptionPrompt」に「1」を設定して渡してやると、アプリのアクセシビリティが未許可の場合に[[システム環境設定]]を開くかを確認するダイアログが表示される。なお、ダイアログが表示されても、そこで[[スレッド]]は止まらずに即座に[[戻り値]]「false」が返されて続行される。
<source lang="csharp">
var options = NSDictionary.FromObjectAndKey(new NSNumber(1), new NSString("AXTrustedCheckOptionPrompt"));
AXIsProcessTrustedWithOptions(options.Handle);
</source>
また、古い[[OS]]の場合は自前でダイアログを表示する必要がある。新旧に対応し、かつ統一感を出すには自前で警告ダイアログを実装した方がいいかもしれない。これらの理由によりアクセシビリティの許可設定の確認と未許可時の警告ダイアログの表示は別々に処理した方が良いと思われる。
*[[MonoMac/モーダルウインドウを作成する]]
*[[Xamarin.Mac/システム環境設定を開く]]
==関連項目==
*[[Xamarin.Mac/Global Event Monitorでキー入力を監視する
*[[Xamarin.Mac/OSのバージョンを取得する]]
*[[MonoMac/モーダルウインドウを作成する]]
*[[Xamarin.Mac/システム環境設定を開く]]
==参考文献==
{{reflist}}
{{stub}}
[[category:Xamarin.Mac]]
[[category:MonoMac]]