Categories

[Win8] Window System

タスクマネージャーのウィンドウを[スタート]画面やMetro Appの上に表示できることを初めて知りました。
私としてこれはちょっと予想外でして、少し調査してみることにしました。

まず、IEを起動してフォアグランドウィンドウにしておきます。ウィンドウに影が付いています。

[Windows]+Cでチャームを表示します。

IEのウィンドウに影がなくなったことが分かります。
つまり、チャームは普通のウィンドウのように動いています。

チャームが表示されているときに、タスクバーにあるプログラムをクリックで起動してみます。
しかし、起動しません。
デスクトップ全体を覆うウィンドウがあるため最初のBUTTON_DOWNを奪っているためのようです。
(時計やツールバーのチャームは透明なウィンドウの上にあるような感じです)

ここからデュアル ディスプレイで実験します。

Windows 8 Consumer Previewでは、[スタート]画面やチャームはメインディスプレイにしか表示されません。(Windows 8 Release Previewでは変更されます)
チャームが表示されている状態で、セカンドディスプレイのタスクバーからプログラムを起動してみます。
しかし、できません。
セカンドディスプレイも覆われているようです。

このスクリプトでチャームが表示された状態でSpy++を起動してみましょう。

var shell = WScript.CreateObject("WScript.Shell");
WScript.Sleep(3000);
shell.Run("spyxx.exe");

これで、チャームが表示されたままの状態でSpy++が起動できました。
ウィンドウの一覧が取得できました。

それらしいウィンドウがあるかな…?
あれ?ないぞ!
どういうこと?
やっぱりWin32からは分離されているんだ。

タスクマネージャーのような特殊なウィンドウは、1枚のサーフェイスとして扱われて、[スタート]画面のようなサーフェイスの上に位置するように管理されているのかな?

[Win8] Switch Metro to Desktop

Windows 8でMetro Appが実行されているとき、強制的に(自動的に)デスクトップに切り替えたい場合はどうすればいいのでしょう?

そもそもできるのでしょうか?

例えば、Metro Appを開発していてデバッガー上で起動します。
ボタンのハンドラーでブレークポイントを設定しておきます。
ボタンを押すと、ちゃんとデスクトップに切り替わります。

何か方法があるはずなのです。

デスクトップ、[スタート]画面、Metro App画面は、エクスプローラーが管理しているだけなので、正式なAPIがあるとは思えません。
絶対に悪用されますし、あったとしても非公開でしょうね。

[Win8] SendKeysでも書いたとおり、キーボード・イベントは分離されていません。
ショートカットキー[Windows]+Dを実行すればデスクトップを表示できます。

WScriptでは、Windowsキーのショートカットキーを記述できないので、UWSCというソフトを使ってみます。
こんなスクリプトを書いてみました。

SLEEP(5)
// この間にMetro Appを起動する。
KBD(VK_WIN,DOWN,100)
KBD(VK_D,DOWN,100)
KBD(VK_D,UP,100)
KBD(VK_WIN,UP,100)

残念なことに切り替わりません。

一応、このようなコードにすると、Windowsキーを押したことになりますので、スクリプトが間違っているわけではありません。

KBD(VK_WIN,DOWN,100)
KBD(VK_WIN,UP,100)

仮に疑似キーボード操作でデスクトップに切り替えられたとしましょう。
[Start]画面やMetro Appで[Windows]+Dをやれば、期待通りにデスクトップに切り替わりますが、
間違ってデスクトップが表示されているときにやると、「デスクトップを表示」という機能になってしまいます。
つまり、今デスクトップが表示されているのか、されていないのかを取得できないと、[Windows]+Dで切り替えを実現するには無理があることになります。

そういうわけで何か別の方法があるはずなのです。
今回はここまで。

[Win8] SendKeys

Windows 8で、WSHを使ってこんなコードを実行してみます。


var shell = WScript.CreateObject("WScript.Shell");
WScript.Sleep(10000);
shell.SendKeys("^{ESC}"); // Windows Key

[スタート]画面やMetro Appを表示している状態で、上記のSendKeysが実行されると、Windowsキーを操作した動作になります。
思っていたより、レガシーと分離させていないのですね。

こんなコードでMetro版Internet Explorerを実行できます。


var shell = WScript.CreateObject("WScript.Shell");
shell.SendKeys("^{ESC}");
WScript.Sleep(1000);
shell.SendKeys("Internet Explorer");
WScript.Sleep(1000);
shell.SendKeys("{ENTER}");

[Win8] Task Manager over Metro

Windows 8のタスクマネージャーで[常に手前に表示]を有効にすると、[スタート]やMetro Appの上に表示されるようにできるのです。

これをどのように実現するのかがフォーラムに載っていたので残しておきます。
・拡張スタイルに WS_EX_TOPMOST を付ける。
・UAC による UI 保護のバイパスを ON にする。(UI Automation Security Overview)
・デジタル署名をする。
・アプリケーションを Program Files より下に入れる。

デスクトップは単なる1つのサーフェイスになっているものと思っていましたが、そんな単純な話ではないのですね。

束縛!?

Visual Studio 11 Beta 日本語版の画面です。

「束縛の種類」
恋愛相談のダイアログですか?

「設定を増やす」
元の英語が想像できないが…。従来なら「詳細設定」とかじゃないか?

バージョンアップの度に翻訳がめちゃくちゃになっていく。
そのうち、日本語版を中国人が作っていそうで怖い。

(追記)
CONNECTのフィードバックに挙がっていました。

C# 5.0 Async and Await (9)

Create your first Metro style app using C# or Visual Basic
このチュートリアルのコードについて考えてみます。

気になったのは、”Using the data in the app”セクションの以下のコードです。


protected override async void OnNavigatedTo(NavigationEventArgs e)
{
  FeedDataSource _feedDataSource = App.DataSource;
  if (_feedDataSource.Feeds.Count == 0)
  {
    await _feedDataSource.GetFeedsAsync();
  }
  this.DataContext = (_feedDataSource.Feeds).First();
}

やりたいことは恐らく、FeedDataSource.GetFeedsAsyncメソッドをまだ呼び出していないなら呼び出す、でしょう。
“_feedDataSource.Feeds.Count == 0″ という条件は、「FeedDataSource.GetFeedsAsyncメソッドをまだ呼び出していない」と等価なのかということです。

まず、スレッドセーフでないコレクションを非同期メソッドで同時に変更して大丈夫なのか?
これは、C# 5.0 Async and Await (6)で書いたとおり、呼び出したときの同期コンテキストで実行されるので問題ありません。


public async Task GetFeedsAsync()
{
  Task feed1 =
    GetFeedAsync("http://windowsteamblog.com/windows/b/developers/atom.aspx");
  ...
  this.Feeds.Add(await feed1);
  ...
}

GetFeedsAsyncメソッドを呼び出しても、feed1が完了するまでコレクションに追加されませんから、やはり”_feedDataSource.Feeds.Count == 0″という条件式は問題ありということになります。

チュートリアルなので気にするに値しないかもしれませんが、このチュートリアルをみて真似をする馬鹿がいるのも事実なので気をつけてもらいたいものです。

C# 5.0 Async and Await (8)

メソッドのオーバーライドを考えてみましょう。

C# 5.0 Async and Await (2)で、asyncはメタデータに一切の情報を付加しないことを書きました。
つまり、asyncはシグネチャーを変更しないということです。
実際にやってみましょう。


abstract class Downloader
{
  public abstract void Download(string url);
}

class HttpDownloader : Downloader
{
  public override async void Download(string url)
  {
    var content = new MemoryStream();
    var webReq = (HttpWebRequest) WebRequest.Create(url);
    using (WebResponse response = await webReq.GetResponseAsync()) {
      using (Stream responseStream = response.GetResponseStream()) {
        await responseStream.CopyToAsync(content);
      }
    }
  }
}

※ あくまで例示用のプログラムです。

オーバーライドしたメソッドでawaitを使いたいためにasyncを付けなければなりませんが、asyncはメソッドを使う側でなくメソッドの実装への宣言であるので問題なくオーバーロードが可能です。

既に気付いているかもしれませんが、戻り値がvoidなので上記のような実装が可能です。
戻り値をbyte[]にした場合、asyncを付与した場合、戻り値をTask<byte[]>型に変更しないといけません。
結果的にシグネチャーが一致しないのでオーバーライドできません。


abstract class Downloader
{
  public abstract byte[] Download(string url);
}

class HttpDownloader : Downloader
{
  // コンパイルエラー
  public override async Task<byte[]> Download(string url)
  {
    var content = new MemoryStream();
    var webReq = (HttpWebRequest) WebRequest.Create(url);
    using (WebResponse response = await webReq.GetResponseAsync()) {
      using (Stream responseStream = response.GetResponseStream()) {
        await responseStream.CopyToAsync(content);
      }
    }
    return content.ToArray();
  }
}

次にDownloadAsyncという抽象メソッド(純粋仮想関数)を定義してみましょう。
asyncを抽象メソッドに修飾すると、コンパイルエラーになります。
くどいですが、asyncはメソッドの実装への修飾子だから、実装を持たない抽象メソッドには定義できないのです。


abstract class Downloader
{
  // 'async' 修飾子は、ステートメント本体を含むメソッドでのみ使用できます。
  // public abstract async void DownloadAsync(string url);
  public abstract void DownloadAsync(string url);
}

class HttpDownloader : Downloader
{
  public override async void DownloadAsync(string url)
  {
    var content = new MemoryStream();
    var webReq = (HttpWebRequest) WebRequest.Create(url);
    using (WebResponse response = await webReq.GetResponseAsync()) {
      using (Stream responseStream = response.GetResponseStream()) {
        await responseStream.CopyToAsync(content);
      }
    }
  }
}

Weblio Gadget

後数ヶ月でWindows 8がリリースされようという今日この頃、サイドバーガジェットを作りました。

タイトル通り、weblioの検索ガジェットです。
英単語の意味を調べるために欲しかったのです。

最初はWindows 7のタスクバーにURLをピン留めしていたのですが、貴重なタスクバーを消費することと、あまり使い勝手が良くないので、ガジェットを作ってみました。

個人的に欲しく作っただけなので、Windows Vistaは検証していません。
使いたい人はどうぞ。

ダウンロード

SEAGATE ST3000DM001

2TBのHDDが無応答になり、PCをリセットしないと回復しない状況がたびたび発生するようになりました。
(起動できてしまえば正常に動作しているのが救いです)
再現頻度が上がり、単にHDDの問題だと断定できるようになったので、交換することにしました。

故障したのは、HGST HDS722020ALA330です。
・静音モードにしないとうるさくて使いものにならない。
・アイドル時に自動書き直しが発生するのでうるさいし、正直、気味悪い。
ずっと、ランダムアクセスが速いことで定評のあるIBMの流れを汲むHGSTをひいきにしてきましたが、はっきり言ってこのHDDは駄作でした。

最近では価格競争力もなくなりつつあり、HGSTを離れつつあります。
(前回はバックアップ用HDDということで価格だけでWDを選択しました)

HDD業界は、タイの洪水の影響がまだ残っています。
特にHGSTは高止まりをしており、HGST 2TBの価格で他社の3TB HDDが買えます。
もうHGSTを選ぶ理由はありません。

正直、WDは安物というイメージしかないので、消去方式でSEAGATEにしました。

ST3000DM001の容量は3TBなので、MBRは使えずGPTを使う必要があります。
オイラのPCはまだBIOSなのでGPT非対応ですが、システムドライブはSSDで、HDDはデータドライブとしてしか使用しないので問題ありません。
さらにこの製品は4Kセクター(Advanced Format)なので、Windows Vista以降が必要です。これも私には問題ありません。

いつもならネットで買うのですが、緊急事態につき秋葉原まで足を運びました。
価格は12,980円(ツクモ)でした。
Amazonでの価格も12,980円ですので、秋葉原=安いというのはもう成立しないようですね。
700円近い電車代を考えるとAmazonで買う方が明らかに安いです。

早速、PCにホットプラグしてみましたが、Windowsは746GBしか認識しません。
BIOSで746GBと表示されるなら分かるのですが、なぜ?
冷静にドライバーをアップデートしてみました。
Intel Rapid Storage Technology 10.1.0.1008から
Intel Rapid Storage Technology 10.8.0.1003にアップデートしたところ、正常に3TB(2.7TB)が認識されました。

NTFS 64KBクラスターでフォーマットに7時間、ファイルコピーに4時間。
無事、壊れそうなHDDが壊れることなく新しいHDDに移行できました。

移行して3日ほど経過しますが、極めて順調で満足しています。

ただ1つ気になることを挙げると、音です。シーク音ではありません。
ヘッド退避音のような音が定期的にします。(アイドルのときだけかな)
2chによると、シーク終了から30秒,50秒で音がなり、消費電力が5.6W,3.9Wに落ちるのだそうだ。
金属がすれるような音で結構耳障りです。

Optimized Native Images

Microsoft .NET Framework 4.5で、Optimized Native Imagesがサポートされます。
従来のNGenが単にILをネイティブコードにコンパイルした結果を保存していたのに対して、プロファイル情報を元にネイティブコードのレイアウトを最適化して保存しようという機能です。

この最適化はMPGO(Managed Profile Guided Optimization)というツールで行います。
%ProgramFiles%\microsoft visual studio 11.0\team tools\performance tools\mpgo.exe
にインストールされています。

使い方は、NGenの前にMPGOを起動するだけです。
MPGOによりプロファイル情報がアセンブリのリソースとして埋め込まれ、NGenはそれを参照してネイティブイメージを生成します。

MPGO.exe -scenario MyLargeApp.exe -AssembyList *.* -OutDir C:\Optimized\
NGEN.exe myLargeApp.exe

ただ残念なことにMPGOツールは、Visual Studio 11 Ultimateにしか含まれないようです。

過去にも書きました(参照)が、NGenは実行時でなく事前にネイティブコードを生成するだけで、処理が速くなるわけではありません。
それどころか遅くなる可能性もあります。
速くなるのは起動だけといってもいいかもしれません。(これがNGenを使う最大の理由)

.NET Framework 4.5では、マルチコア対応のJITが搭載され、別のコアで動作するバックグランドスレッドでJITが行われるようになります。
これにより、従来のようにメソッドを初めて呼び出す度にJITを行いそして実行するというオンデマンドJITがなくなる(減る)わけですから、事前にネイティブコードを生成しておくメリットは半減するのだろうと思います。
Microsoftが言うように、MPGOは巨大なプログラムでしか効果を発揮しないのかもしれません。