world2015/01/31無線LANのSSIDをC#から取得する無線LANのSSIDをC#からAPIで取得するコードを書いてみた。FrameworkにもWinRTにもそれが可能なAPIは用意されていない。APIは開発が止まって久しく、かといってP/Invokeの宣言を起こすのも大変そうなので敬遠していた。実用上はNetshの出力をパースすれば大体足りるし。それが、ふとMSDNでこんなエントリを見かけた。C#「おおっ」と思いつつダウンロードしたが、実体部分はC++のライブラリで、それをC#から使うものだった(タイトルどおりではある)。悔しかったので少し探したところ、幾つかサンプルが挙げられていた。SP2これらとMSDNを合わせ見た結果、必要なピースは揃ってそうだったので書いてみた。利用可能なネットワークのSSIDを取得する手順としては以下のようになる。WlanOpenHandleでハンドルを取得する。このdwClientVersionはOSによって変わるが、Vista以降は2。WlanEnumInterfacesでPCにある無線LANインターフェイス(無線LANアダプター)の情報を取得する。WlanGetAvailableNetworkListで各インターフェイスから見える無線LANネットワークの情報を示すWLAN_AVAILABLE_NETWORKを取得する。これは各インターフェイスの感度にも左右されるが、インターフェイスが複数あれば当然、単数でも試した限りでは重複があり得る。WLAN_AVAILABLE_NETWORKからSSIDを取得する。}}P/Invokeの宣言はレポジトリの方を参照。接続中のネットワークのSSIDを取得する手順は2.までは上と同じ。WlanOpenHandleでハンドルを取得する。WlanEnumInterfacesでPCにある無線LANインターフェイスの情報を取得する。WlanQueryInterfaceで各インターフェイスの現在の接続状況を示すWLAN_CONNECTION_ATTRIBUTESを取得する。このためにはOpCodeにwlan_intf_opcode_current_connectionを指定する。WLAN_CONNECTION_ATTRIBUTESのisStateで接続中かどうか判別できるので、接続中ならwlanAssociationAttributesのWLAN_ASSOCIATION_ATTRIBUTESからSSIDを取得する。}}なお、3.のWlanQueryInterfaceはそのインターフェイスが接続中でないときはERROR_INVALID_STATEを返してくる。TPで確認したところ問題なさそうだったので、とりあえずこれで行けると思う。APIで取得できるとコマンド出力をパースするよりわずかでも速いし、気持ちすっきりするのがいい。まあP/Invokeのマーシャリングは結構泥臭いけど。stringとされていて、平たくいうと長さ0-32のバイト配列とされている。これは現在はUTF-8も使えることになっていて、当然日本語を使うこともできる(それで駄洒落を作るのが少しネタになっていた)。string."と釘が刺されている。このDOT11_SSIDに対応するP/Invoke用の構造体を初め以下のように書いていた。}}これには問題があって、uSSIDLengthの示す長さを勘違いしていることもさることながら、実際に試してみるとUnmanagedType.ByValTStrでは正しくマーシャリングされず、「の」が「縺ョ」のように文字化けを起こす。これを回避するには、ucSSIDをまずはバイト配列にマーシャリングした上で、これから文字列に変換すればうまく行った。(int)uSSIDLength);}さらに、規格に忠実にバイト配列としても取り出せるようにまとめ直せば、こんな感じ。8.1のNetshの出力を見るとUnmanagedType.ByValTStrを使ったときと同じように文字化けする。TPでも解消してないらしい。correctlyということで、UTF-8対応ができるという点が、現状APIによる方法が明確に優れている点になる。ライブラリ公開ライブラリとしてまとめたので、コードをなるべく合わせるよう修正した。TPのインストール時に遭遇したエラーについての記録。最近のWindowsのインストールで問題が出ることはあまりないですが、久々に謎なエラーに遭遇しました。X230でUEFI用に作成したUSBメモリから起動してのインストールです。9926の日本語版のISOファイルからUSBメモリを作成し、これから起動しようとしたところ、「お使いのPCに必要なメディアドライバーがありません。」というエラーが表示されて進めない。IntelのIRSTのドライバーファイルを読み込ませてみたが、変化なし。このメッセージどおりの問題ではない。ISOファイルのハッシュ値を確認したが、ダウンロードサイトに示されたとおり。USBメモリを作成し直してみたが、エラーは変わらず。そもそもUEFI用のUSBメモリの作成方法は簡単で(後述)、間違う余地は少ない。missing."という同内容のエラーが出る。単純な問題ではない気配がしてきたので、ISOファイルをDVD-Rに焼いてインストールしたところ、問題なく終了。問題はUSBメモリの起動にある。9879のISOファイルからUSBメモリを作成してみたが、エラーは変わらず。9926特有の問題ではないが、しかし以前は問題なかったはず。USBメモリを差すコネクタをX230の向かって左側から右側に変えたところ、エラーは出ず、ハードウェアと関係があることが判明。正確には左側2箇所のコネクタ(USB.3.0)のどちらでもエラーが出るが、右側1箇所のコネクタ(USB2.0)では出ない。左側でも通常時は問題ないし、左側で作成したUSBメモリで右側から起動もできる。16GB(いずれもUSB3.0)に変えてみたが、エラーの出る条件は変わらず。USBメモリ側の問題ではない。2.0)に変えてみたところ、左右どちらでもエラーは出ず。エラーが出るのはUSB3.0の場合のみ。Enterprise評価版のISOファイルを使ってみたところ、USB3.0のUSBメモリでも左右どちらでもエラーは出ず。TPのインストーラーを起動しようとした場合にこのエラーが出る、ということになります。製造から1年足らずで、2箇所のコネクタに同じ問題が出るものか。USB3.0用のメス側の接点はベロの先端に、かつX230の場合は下向きに付いているので、埃は付着しにくい。いうことがあって、保留です。TPのインストーラーはUSB3.0の認識に何か変更があったっぽい、ということですが、まあ問題に遭遇でもしない限り無駄知識ですけど。CarbonのUSB3.0コネクタでも同じエラーが出るそうで、かつX230の右側のコネクタはUSB2.0なので、エラーが出る条件としてはUSB3.0がやはりキーのようです。Programにポストしました。10074のISOではこのエラーは出なくなりました(日本語版、英語版とも)。問題は解決されたようです。UEFI用のUSBメモリの作成なお、UEFIではブートに関するノウハウが従来と変わりました。パーティションがアクティブであること、専用のブートセクタであることは必要なくなりました。代わりにパーティションがFAT32であることが必須です。したがってブータブルなUSBメモリを作成するには、とにかくFAT32でフォーマットして、ISOファイル(x64版であること)の中身をコピーするだけです。特別なツールやDiskPartを使う場面は基本的にないと思います。この点に関して、Microsoftの高橋さんが書かれている方法のうちアクティブとブートセクタの部分は、従来の場合と両対応にするために必要なことであって、UEFIだけ考える場合は必要ないと思います。10のcompatibilityの記述あり。VerifyVersionInfoがGetVersion/GetVersionExと同じ呪縛にかかった模様。意図された動作かどうか、現状分からないが。最後まで残るとすれば、個人的な予想ではWMIではないかと。WMIはシステム管理にも使われるので、アプリ対策の都合だけで変えにくいと思うので。Proと+portOTGのUSBコネクタで充電とデータ通信が同時にできる+portの話。Labsの+portをオーダーした。本体29ドルに送料10ドルを合わせて39ドル。Proでデモしているように、純正を除けば唯一の確実な選択肢、と思われた。Proが含まれているのを後になってから知り、さらにACASISのHO27の店頭販売が始まった。12月前半まではモバイルショップを回っても影も形もなかったのに、一気に状況が変わってきた。いうことで、このタイミングで+portを買うこともなかったが、来たものは来たものとして使っていく所存。Proを念頭に置いて作られたものらしいから大丈夫だろうとは思ったものの、一応充電時間を比較してみた。接続方法は以下のとおり。文字にするとややこしいが、実際はそうでもない。ちなみに、+portからACアダプターのケーブルを抜くと+portのUSBコネクタに差したデバイスとの接続が失われるので、+portの動作自体にACアダプターからの電源供給が必要な模様。比較するのは以下の3ケース。負荷として無線LANで接続した状態でYouTubeの動画を流し続ける。Proに接続し、充電が開始された後、+portのUSBコネクタに有線LANアダプターを接続。負荷として有線LANで接続した状態で(無線LANはオフ)同じくYouTubeの動画を流し続ける。