サブノート/サブディスプレイに Surface RT を使っていると、デスクトップで見つけた Youtube を Surface で表示したい時が頻繁にあります。この場合、どうやって送るかというと…
- Twitter でメモ的に流してから、Surface 側で拾う
- SkyDrive に URL を置いてから Surface で拾ってくる。
- ちまちまと URL を Surface で打つ
という方法があるわけですが、どれも面倒くさい。ただし、Windows 8 同士であれば、デスクトップアプリでさっくりとできそうなのですが、片方が Windows RT なものだから、Windows ストア アプリしないといけないという制限がある。
で、前々から考えていた、デスクトップPCのほうに簡易HTTPサーバー、タブレットPCにWindows ストア アプリのクライアント、というパターンで実装してみます。
■簡易HTTPサーバー
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | /// <summary> /// フォームロード時 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form1_Load( object sender, EventArgs e) { listener = new HttpListener(); listener.Prefixes.Add( "http://*:8090/url/" ); listener.Start(); // 受信待ちタスク Task tsk = new Task( () => { while ( true ) { var cont = listener.GetContext(); var req = cont.Request; var res = cont.Response; Debug.WriteLine( string .Format( "req {0}" , req.RawUrl)); var tw = new StreamWriter(res.OutputStream); tw.Write(_text); tw.Close(); res.Close(); } }); tsk.Start(); } HttpListener listener; private string _text = "" ; /// <summary> /// ドロップされた時 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form1_DragDrop( object sender, DragEventArgs e) { var text = "" ; var obj = e.Data; foreach ( var fmt in obj.GetFormats()) { Debug.WriteLine( fmt ); if (fmt == "text/uri-list" ) { var sr = (MemoryStream)obj.GetData( "text/uri-list" ); text = Encoding.Unicode.GetString(sr.ToArray()); break ; } } textBox1.Text = text; _text = text; } private void Form1_DragEnter( object sender, DragEventArgs e) { e.Effect = DragDropEffects.All; } |
簡易サーバーは HttpListener で作れば ok です。今回はポート番号を 8090 にして待ちにします。URLはFirefox からドラッグ&ドロップします。何故かIE10の場合はできないのですが…まあ、自分専用なのでFirefoxで。これは後で調査。
■Surface RT 側のクライアント
自動的に取ってくるのがいいのですが、ひとまず、Get ボタンで URL を取得、その後 IE10 で開くという処理を続けてやります。
1 2 3 4 5 6 7 8 9 10 | private async void GetClick( object sender, RoutedEventArgs e) { string url = "http://mars:8090/url" ; HttpClient cl = new HttpClient(); var res = await cl.GetAsync( new Uri(url)); var text = await res.Content.ReadAsStringAsync(); text1.Text = text; // 起動 await Windows.System.Launcher.LaunchUriAsync( new Uri(text)); } |
■サーバーの設定
実は Winodows 8 では、ポートの制限が厳しくて、単純に HttpListener を作っただけでは動きません。管理者のコマンドラインから、次のコマンドを実行します。
1 | netsh http del urlacl url=http: //*:8090/ -user=masuda |
Community Open Day 2012 の補足その1 – Moonmile Solutions Blog
Community Open Day 2012 の補足その2 – Moonmile Solutions Blog
に、netsh の使い方が書いてあります。
あとは、ファイアーウォールで、8090 のポートを開けることです。ポート絡みがややこしいので、本格的にツールにするとしたらインストーラが必須ですね。
■で、何につかうのか?
iSteve from Justin Long, Jorge Garcia, James_Urbaniak, Michaela Watkins, Steve Tom, John Ross Bowie, Paul Rust, Ryan Perez, Juzo Yoshida, Brian Huskey, Art Evans, jill_donnelly, Anthony Gioe, Ally Hord, iSteve, Funny Or Die, Charles Ingram, NickCorirossi, Joe Farrell, and Katy Walker を Surface に送ってみたかったんですよ…って、動かしてみたら、ああ、Surface RT の IE10 だと Flash が動かないタイプな模様 orz 、結局デスクトップPCで閲覧
■サンプルソース
サンプルソースはこちら。適当にホスト名とかポート番号とかを変えて使ってください。