「Xamarin.Macでリムーバブルメディアの着脱を検知する」の版間の差分

提供: MonoBook
ナビゲーションに移動 検索に移動
imported>Administrator
imported>Administrator
 
(同じ利用者による、間の4版が非表示)
1行目: 1行目:
MonoMacで[[CD-ROM]]や[[DVD-ROM]]、[[USBメモリ]]の挿入などを検出できると何かと嬉しい。
+
[[Xamarin.Mac]]で[[CD-ROM]]や[[DVD-ROM]]、[[USBメモリ]]の挿入などを検出できると何かと嬉しい。
  
 
==実装例==
 
==実装例==
NSWorkspace.SharedWorkspace.NotificationCenterを使うと検出できるようだ。この通知で情報として飛んでくるのはデバイスのパスのみなので、そのパスをNSWorkspace.SharedWorkspace.GetFileSystemInfoを使い[[CD-ROM]]なのか[[USBメモリ]]なのかなどを判別する。なお、CD-ROMやDVD-ROMの場合はディスクフォーマットごとに返ってくる値が違うようだ。どんな種類があるのか全部はまだ把握していない。
+
NSWorkspace.SharedWorkspace.NotificationCenterを使うと検出できるようだ。この通知で飛んでくるのは「変化のあったデバイスのパスのみ」なので、そのパスをNSWorkspace.SharedWorkspace.GetFileSystemInfoに投げて「[[CD-ROM]]なのか」「[[USBメモリ]]なのか」などを判別する。なお、GetFileSystemInfoの結果は[[CD-ROM]]や[[DVD-ROM]]の場合はディスクフォーマットごとに返ってくる値が違うようだ。どんな種類があるのか全部はまだ把握していない。
  
 
通知には種類があるようで、この例では以下を実装している。
 
通知には種類があるようで、この例では以下を実装している。
* NSWorkspaceDidMountNotification - マウント直後
+
 
* NSWorkspaceWillUnmountNotification - アンマウント直前
+
*NSWorkspaceDidMountNotification - マウント直後
 +
*NSWorkspaceWillUnmountNotification - アンマウント直前
 +
 
 
NSWorkspaceDidUnmountNotification(WillではなくDid)も実装すればアンマウント直前のみならずアンマウント直後も検出できる。ただしアンマウント後なのでデバイスパスしか取得できない。アンマウント失敗時を考慮するとこちらの方が確実かもしれないが詳しくは知らない。
 
NSWorkspaceDidUnmountNotification(WillではなくDid)も実装すればアンマウント直前のみならずアンマウント直後も検出できる。ただしアンマウント後なのでデバイスパスしか取得できない。アンマウント失敗時を考慮するとこちらの方が確実かもしれないが詳しくは知らない。
 
なお、いわゆる自動実行(autorun.inf)などとは違うので起動していないアプリが起動するわけではない。あくまでアプリが立ち上がっている状態でのみ機能する。
 
  
 
<source lang="csharp">
 
<source lang="csharp">
 
     using System;
 
     using System;
     using MonoMac.Foundation;
+
     using Foundation;
     using MonoMac.AppKit;
+
     using AppKit;
  
 
     public class RemovableMediaNotificationEventArgs : EventArgs
 
     public class RemovableMediaNotificationEventArgs : EventArgs
54行目: 54行目:
 
             if (_mountObserver == null)
 
             if (_mountObserver == null)
 
             {
 
             {
                 _mountObserver = notification.AddObserver("NSWorkspaceDidMountNotification", DidMount);
+
 
 +
                 _mountObserver = notification.AddObserver(NSWorkspace.DidMountNotification, DidMount);
 
             }
 
             }
  
60行目: 61行目:
 
             if (_unmountObserver == null)
 
             if (_unmountObserver == null)
 
             {
 
             {
                 _unmountObserver = notification.AddObserver("NSWorkspaceWillUnmountNotification", WiilUnmount);
+
 
 +
                 _unmountObserver = notification.AddObserver(NSWorkspace.WillUnmountNotification, WiilUnmount);
 
             }
 
             }
 
         }
 
         }
113行目: 115行目:
  
 
             var workspace = NSWorkspace.SharedWorkspace;
 
             var workspace = NSWorkspace.SharedWorkspace;
             workspace.GetFileSystemInfo(devicePath, out isRemovable, out isWritable,out isUnmountable, out description, out fileSystemType);
+
             workspace.GetFileSystemInfo(devicePath, out isRemovable, out isWritable, out isUnmountable, out description, out fileSystemType);
  
             var args = new RemovableMediaNotificationEventArgs {
+
             var args = new RemovableMediaNotificationEventArgs
 +
            {
 
                 DevicePath = devicePath,
 
                 DevicePath = devicePath,
 
                 IsRemovable = isRemovable,
 
                 IsRemovable = isRemovable,
129行目: 132行目:
  
 
==関連項目==
 
==関連項目==
*[[Xamarin.Mac/CDやDVDなどの光学メディアを排出する]]
+
* [[Xamarin.MacでCDやDVDなどの光学メディアを排出する]]
 
+
* [[Xamarin.Macで接続されているリムーバブルメディアの一覧を取得する]]
==参考文献==
 
{{reflist}}
 
 
 
{{stub}}
 
  
 
[[category:MonoMac]]
 
[[category:MonoMac]]
 
[[category:Xamarin.Mac]]
 
[[category:Xamarin.Mac]]

2018年12月28日 (金) 03:50時点における最新版

Xamarin.MacCD-ROMDVD-ROMUSBメモリの挿入などを検出できると何かと嬉しい。

実装例[編集 | ソースを編集]

NSWorkspace.SharedWorkspace.NotificationCenterを使うと検出できるようだ。この通知で飛んでくるのは「変化のあったデバイスのパスのみ」なので、そのパスをNSWorkspace.SharedWorkspace.GetFileSystemInfoに投げて「CD-ROMなのか」「USBメモリなのか」などを判別する。なお、GetFileSystemInfoの結果はCD-ROMDVD-ROMの場合はディスクフォーマットごとに返ってくる値が違うようだ。どんな種類があるのか全部はまだ把握していない。

通知には種類があるようで、この例では以下を実装している。

  • NSWorkspaceDidMountNotification - マウント直後
  • NSWorkspaceWillUnmountNotification - アンマウント直前

NSWorkspaceDidUnmountNotification(WillではなくDid)も実装すればアンマウント直前のみならずアンマウント直後も検出できる。ただしアンマウント後なのでデバイスパスしか取得できない。アンマウント失敗時を考慮するとこちらの方が確実かもしれないが詳しくは知らない。

    using System;
    using Foundation;
    using AppKit;

    public class RemovableMediaNotificationEventArgs : EventArgs
    {
        public string DevicePath { get; set; }
        public bool IsRemovable { get; set; }
        public bool IsWritable { get; set; }
        public bool IsUnmountable { get; set; }
        public string Description { get; set; }
        public string FileSystemType { get; set; }
    }

    public delegate void RemovableMediaNotificationEventHandler(object sender, RemovableMediaNotificationEventArgs args);

    // 着脱を検知するクラス
    public class RemovableMediaNotification : IDisposable
    {
        private NSObject _mountObserver;
        private NSObject _unmountObserver;

        public event RemovableMediaNotificationEventHandler OnMount;
        public event RemovableMediaNotificationEventHandler OnUnmount;

        public RemovableMediaNotification()
        {
        }

        public void Dispose()
        {
            Stop();
        }

        public void Start()
        {
            var workspace = NSWorkspace.SharedWorkspace;
            var notification = workspace.NotificationCenter;

            // マウント直後
            if (_mountObserver == null)
            {

                _mountObserver = notification.AddObserver(NSWorkspace.DidMountNotification, DidMount);
            }

            // マウント直前
            if (_unmountObserver == null)
            {

                _unmountObserver = notification.AddObserver(NSWorkspace.WillUnmountNotification, WiilUnmount);
            }
        }

        public void Stop()
        {
            var workspace = NSWorkspace.SharedWorkspace;
            var notification = workspace.NotificationCenter;

            if (_mountObserver != null)
            {
                notification.RemoveObserver(_mountObserver);
                _mountObserver.Dispose();
                _mountObserver = null;
            }

            if (_unmountObserver != null)
            {
                notification.RemoveObserver(_unmountObserver);
                _unmountObserver.Dispose();
                _unmountObserver = null;
            }
        }

        private void DidMount(NSNotification notification)
        {
            if (OnUnmount != null)
            {
                var path = notification.UserInfo["NSDevicePath"].ToString();
                var args = CreateEventArg(path);
                OnMount(this, args);
            }
        }

        private void WiilUnmount(NSNotification notification)
        {
            if (OnUnmount != null)
            {
                var path = notification.UserInfo["NSDevicePath"].ToString();
                var args = CreateEventArg(path);
                OnUnmount(this, args);
            }
        }

        private RemovableMediaNotificationEventArgs CreateEventArg(string devicePath)
        {
            bool isRemovable;
            bool isWritable;
            bool isUnmountable;
            string description;
            string fileSystemType;

            var workspace = NSWorkspace.SharedWorkspace;
            workspace.GetFileSystemInfo(devicePath, out isRemovable, out isWritable, out isUnmountable, out description, out fileSystemType);

            var args = new RemovableMediaNotificationEventArgs
            {
                DevicePath = devicePath,
                IsRemovable = isRemovable,
                IsWritable = isWritable,
                IsUnmountable = isUnmountable,
                Description = description,
                FileSystemType = fileSystemType,
            };
            return args;
        }
    }

関連項目[編集 | ソースを編集]