Windows 10からDNS-SD/mDNS、いわゆるAppleのBonjourをネイティブサポートするようになりました。 要するに何ができるかというとIPアドレスやホスト名を知らなくても同じネットワークにいるデバイスとサービスを探すことができる仕組みです。
例えば、iTunesが他のコンピューターのiTunes 共有ライブラリを見つけるといったことに利用されています。そのちょっと便利な機能をUWPのAPIを通して利用できるようになっています。
アプリからDNS-SDでサービスを探す さて、どうやって使うかですがまあまあ簡単で、通常のデバイスを列挙するのと同様にDeviceInformation クラス を利用します……が、列挙しようと思ってFindAllAsyncメソッドを使うと何も返ってこず(awaitすると進まない)、暫くするとエラーが出ます。
この挙動が正しいのかどうかよくわかりませんが、ともかく何やらうまく動きません。
そこでDeviceInformation.CreateWatcher メソッド を利用します。 このメソッドはデバイスがネットワークに追加されたり削除されたりというのを監視する方法です。この方法でならば列挙できます。
Watcherを作ってStartメソッドを呼び、監視を始めるとデバイスが見つかりAddedイベントが呼び出されますのでそこで適当に情報を保持しておけばよいです。 ちなみに監視して列挙終了時の EnumerationCompleted イベントが発生しないので完了を待つというのはやめた方がいいでしょう(多分それがFindAllAsyncが返ってこない原因な気がします)。
とりあえず、ネットワークにあるAndroid TV(正確にはAndroid TVが持つリモコン用サービス)を列挙するソースコードはこんな感じなります。
using Windows.Devices.Enumeration;var serviceName = "_androidtvremote._tcp" ;var protocolId = "{4526e8c1-8aac-4153-9b16-55e86ada0e54}" ;var aqsFilter = $"System.Devices.AepService.ProtocolId:={protocolId} AND System.Devices.Dnssd.Domain:=\"local\" AND System.Devices.Dnssd.ServiceName:=\"{serviceName} \"" ;var properties = new [] { "System.Devices.Dnssd.HostName" , "System.Devices.IpAddress" , };var watcher = DeviceInformation.CreateWatcher(aqsFilter, properties, DeviceInformationKind.AssociationEndpointService); watcher.Added += (sender, args ) => { Debug.WriteLine("Added: " + args .Id); foreach (var prop in args .Properties) { var value = prop.Value is string [] ? (String.Join(", " , (string [])prop.Value)) : prop.Value + "" ; Debug.WriteLine($" - {prop.Key} : {value } " ); } }; watcher.Updated += (sender, args ) => { Debug.WriteLine("Updated: " + args .Id); foreach (var prop in args .Properties) { var value = prop.Value is string [] ? (String.Join(", " , (string [])prop.Value)) : prop.Value + "" ; Debug.WriteLine($" - {prop.Key} : {value } " ); } }; watcher.Start();
実行するとこんな感じにホスト名やIPアドレスなどの情報が取れます。
Added: DnsSd#KJ-55X8500C._androidtvremote._tcp.local#0 - System.ItemNameDisplay: KJ-55X8500C - System.Devices.DeviceInstanceId: - System.Devices.Icon: - System.Devices.GlyphIcon: - System.Devices.InterfaceEnabled: - System.Devices.IsDefault: - System.Devices.PhysicalDeviceLocation: - System.Devices.Aep.CanPair: False - System.Devices.Aep.IsPaired: False - {A35996AB-11CF-4935-8B61-A6761081ECDF} 18: - {A35996AB-11CF-4935-8B61-A6761081ECDF} 13: - System.Devices.Dnssd.HostName: Android.local - System.Devices.IpAddress: 192.168.1.100
アプリはこの情報をもとにサーバー(サービス)に接続すれば、相手の名前をあらかじめ知っていなくてもアクセスできる、というわけです。
手順をおさらいすると、DeviceWatcherを作るCreateWatcherメソッドの引数に渡すAQS文字列と呼ばれる検索フィルター文字列に、 DNS-SDプロトコル({4526e8c1-8aac-4153-9b16-55e86ada0e54})を使うことを指定して、さらにDNS-SDのサービス名(_daap.tcpなど)を指定して、検索を実行すれば見つかるという形になっています。例えばサービス名に_daap.tcpを指定するとネットワーク上のiTunesの共有ライブラリを探すことができます。
ちなみにこのUniversalなAPIはいわゆる従来のデスクトップアプリケーションからも呼び出すことができます。
制限事項 得られたホスト名(.localで終わる名前)をHttpClientなどに渡しても名前解決されますが、たまに失敗するのでIPアドレスを使った方がいいかもしれません。
なお、どうやら試した範囲ではサービス名を指定せずにネットワークに存在するサービスをすべて列挙する、ということはできないようです。System.Devices.Dnssd.ServiceNameを指定しないで検索すると何も返ってこないことに注意が必要です。
また、Hyper-Vが有効の場合にも動作しない という話もあります。
ついにChakraCore が公開されたので、早速ビルドしてC#からとりあえずハローしてみます。
ChakraCore is 何 とその前にChakraCoreのおさらいです。
まずChakraCoreはInternet ExplorerやEdgeで使われているJavaScriptエンジン ChakraのWindows固有の機能を外したライブラリです。要するにV8とかJavaScriptCoreみたいなものです。
オープンソースになった後のロードマップ が公開され、いろいろ書いてあります。
ChakraCoreのメリット 従来のChakraはWindowsまたはInternet Explorerと共にバージョンが管理されていました。 つまり現在、ChakraにはInternet Explorer 9, 10, 11(Windows Vista/7/2008/2008 R2)、Windows 8.1、10、10 Version 1511というバリエーションがあることになり、 それをアプリケーションに組み込んで利用したい場合にバージョンの差異が発生することになります。
そこでChakraCoreはWindowsやブラウザから分離したJavaScriptのエンジンとなったので、 アプリケーションに独立して組み込むことができるようになり、環境ごとのバージョンの差異に悩まされないで済むようになります。
そもそも従来のWindowsではWindows Scripting Hostを経由してエンジンを組み込むことができましたが、APIもCOMベースでJavaScriptのエンジンを使うということ以外を考慮していたりして使いづらく、エンジンも古いのでモダンなJavaScriptを動かすことができなかったという話もあります。
ChakraCoreをビルドする 2016年1月14日現在、WindowsサポートのみなのでGitHubのリポジトリをcloneし、BuildディレクトリにあるChakraCore.slnをVisual Studio 2015で開いてビルドすればよいです。
と、簡単そうな気がしたのですが日本語環境(CP932がデフォルト環境)ではソースコードがUnicodeじゃないよというWarning(C4819)が出て、WarningがErrorとして扱われてビルドが失敗します。幸い数は少ないのでBOM付きUTF-8で適当に保存しなおしましょう。
ビルドすると Build\VcBuild\bin\x64_debug などに ChakraCore.dll が生成されます。
ChakraCoreをC#から使う ChakraCoreを無事ビルドできたらC#からChakraCoreを使ってみます。
ChakraCoreはJSRT API(JavaScript Runtime API)というAPIを持っているのでそれを利用してChakraCoreの機能を呼び出します。ちなみにJSRTはChakraCoreよりも以前からWindows 10以降(またはInternet Explorer 11以降)ではChakraを利用する手段として提供されています。
詳しくはMSDNのJavaScript ランタイムのホスト処理 に書いてあります。
ただしJSRTは.NET Framework向けのAPIではないアンマネージドなAPIなため、P/Invokeでの呼び出しを行う必要があります。 幸いにもGitHubにChakra-Samples@Microsoft というリポジトリがあり、JSRTのC#のバインディングがすでに作られているのでこれを使います(自分で書こうとするとだいぶ大変です)。
というわけでChakra-Samplesをcloneやダウンロードしておきます。Chakra-SamplesにはHello WorldやHostingサンプルがあるのでまあそれでいいという話もあるのですが、最小限の構成を作ってみることにします。
準備 まず初めに適当にコンソールアプリケーションのプロジェクトを作ります。
プロジェクトを作ったら先ほどビルドしたChakraCore.dllをプロジェクトに追加し、プロパティでビルド時にコピーされるように設定します。
ちなみに普通にプロジェクトを作るとPrefer 32bitということで32bitプロセスとして起動されるのでx86版DLLをコピーしておきましょう。
次にChakra-SamplesからChakraCore Samples\JSRT Hosting Samples\C#\ChakraCoreHostにあるHostingフォルダをプロジェクトにコピーします。これがJSRTのバインディングです。
ChakraCoreを実行してみる というわけでまずはランタイム(=実行エンジン)を作り、実行用のコンテキストを作って実行に備えます。
JavaScriptRuntime runtime; Native.JsCreateRuntime(JavaScriptRuntimeAttributes.None, null , out runtime);var context = runtime.CreateContext(); Native.JsSetCurrentContext(context);
次に実際にJavaScriptのコードを実行します。
var script = @" class Greeter { hello() { return 'コンニチハ!'; } } new Greeter().hello(); " ;var currentSourceContext = JavaScriptSourceContext.FromIntPtr(IntPtr.Zero); JavaScriptValue result; Native.JsRunScript(script, currentSourceContext++, "" , out result);
JsRunScriptメソッドはランタイムもコンテキストも渡さず、現在のスレッドのコンテキストから良しなに実行するので少し不思議な感じがしますね。
正常に実行できれば戻り値がresult変数に格納されます。戻り値はJavaScriptの値となっているのでそこからさらにCLRオブジェクトへ変換します。ToStringメソッドがお手軽に変換してくれるので任せましょう。
var resultString = result.ToString(); Console.WriteLine(resultString);
最後はお片付けです。
Native.JsSetCurrentContext(JavaScriptContext.Invalid); runtime.Dispose();
というわけでここまでのコードをまとめるとこんな感じ。
実行すると「コンニチハ!」という出力が出てくるかと思います。割とお手軽ですね。
なお実行してBadImageFormatExceptionでAn attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B) と言われたらそれはx86/x64のDLLを間違えている可能性があります。
まとめ もちろんエラーハンドリングや.NETからJavaScript側へオブジェクトの公開などもありますがとりあえず今回はここまでです。
意外と簡単に動かせるようになっているのでアプリケーションに組み込み用途にはいいかなと思うものの、ホストとChakraCoreとのやり取りが増えると割と高度なことを必要とするのでちょっと難易度高いかもという感じもします。
« 新しいエントリ 1 … 78 79 80 81 82 … 84 古いエントリ »