6

Windows Phone 7 エミュレーターには、レジストリ設定 (EnableConsole) または XDE.exe の decfg パラメーターを介して有効にできる優れたコンソール ウィンドウ機能がありました。

デバッガを付けなくても動作しました。ランタイム バインディングの問題や例外を見つけるのに役立ちました。

Windows 8 Phone エミュレーターでコンソール ウィンドウを有効にする方法はありますか?

4

2 に答える 2

12

WP8 エミュレーターは WP7 エミュレーターを完全に書き直したものであるため、文書化されていない同じデバッグ メッセージをサポートする可能性は低いです。結局のところ、質問は次のとおりです。何をログに記録しようとしていますか?

  • アプリ固有の情報を取得しようとしていますか? 次に、WP8 のCoreCon APIを介して IsoStore ファイルを共有するという Pavel のアイデアを使用します。
  • エミュレータ自体で興味深いイベントのメッセージを取得しようとしていますか? エミュレーターは ETW プロバイダーにログを記録し、そのログから読み取ることができます。ここで方法を示します。
  • WP8 OS 内から情報を取得しようとしていますか? 次に、ETL ファイルを生成して調べるか、プロファイリング API を直接使用します。

アプリ固有のメッセージのロギング

重要なボタンのクリックなど、何か興味深いことがアプリで発生したとします。それをアプリに記録し、そのメッセージを IsoStore に書き込む (またはカスタム Web サービスに送信する) 必要があります。私は WP8 と Win8 のログ記録に MetroLog を使用していますが、ファイルが IsoStore に書き込まれる限り、何でも使用できます。MetroLog @ https://github.com/mbrit/MetroLogをチェックしてください

その後、CoreCon APIを使用してファイルを読み取ることができます。WP8 @ https://stackoverflow.com/a/13429709/81687のこれらの API のコード サンプルをアップロードしました。


エミュレーター固有のメッセージのロギング

エミュレーターがアクティブ化されたとき、ズームが設定されたとき、スクリーンショットが失敗した場合、またはタッチイベントが発生した場合に関心があるとします。WP8 エミュレーターは、ETW プロバイダーff86852d-541c-4f7e-98c5-5761e8cb7074を使用して、これらの他のイベントをログに記録します。ETW の詳細については、http://msdn.microsoft.com/en-us/magazine/cc163437.aspx を参照してください。

まず、PerfViewをダウンロードして XDE.exe エミュレーターを起動し、ETW 出力のキャプチャを開始します。

PerfView は、前述のすべてのオプションから開始します

  • 作業ディレクトリを WP8 の XDE.exe の場所に設定します。
  • 最初に VS2012 からそのエミュレーターを実行して、Hyper-V イメージを作成してください。または、方法を知っている場合は、自分でイメージをクランクアウトして /VHD パラメーターを使用できます。
  • XDE.exe を呼び出すと、Hyper-V マネージャーから /NAME パラメーターを取得できます。
  • "ff86852d-541c-4f7e-98c5-5761e8cb7074" を含めるように追加のプロバイダーを設定してください。

次に、PerfView からエミュレーターを実行し、いくつかのことを行い、エミュレーターをシャットダウンして、情報の収集を停止します。これを行うと、エミュレーターで行われたすべてのログを確認できます。興味深い内容は、プロバイダー ID でフィルター処理すると、「イベント」ログの下にあります。

PerfView イベント データ

上記の印刷画面では、イベントと、それらがエミュレーターでいつ発生したかを確認できます。たとえば、イベント 76 はエミュレーターの MicrophoneCaptureThreadStarted であり、プロファイリング セッションの 27 秒後に発生しました。イベント コードの完全なリストについては、XDE.exe アセンブリの Microsoft.Xde.Etw.WindowsPhoneEmulatorProvider c'tor を参照してください。納得させるためにここにコピーを貼り付けます:

public WindowsPhoneEmulatorProvider()
{
    this.m_provider = new EventProviderVersionTwo(new Guid("ff86852d-541c-4f7e-98c5-5761e8cb7074"));
    this.XdeStarted = new EventDescriptor(0, 0, 9, 4, 0, 0, -9223372036854775808L);
    this.XdeStopped = new EventDescriptor(1, 0, 0, 4, 0, 0, 0L);
    this.DesktopResolutionChanged = new EventDescriptor(2, 0, 0, 4, 0, 0, 0L);
    this.InvalidLanguageSpecified = new EventDescriptor(3, 0, 0, 2, 0, 0, 0L);
    this.CantFindVhd = new EventDescriptor(5, 0, 0, 2, 0, 0, 0L);
    this.DiffDiskVhdRequiresVhdPath = new EventDescriptor(6, 0, 0, 2, 0, 0, 0L);
    this.InvalidVideoParam = new EventDescriptor(7, 0, 0, 2, 0, 0, 0L);
    this.InvalidMemorySize = new EventDescriptor(8, 0, 0, 2, 0, 0, 0L);
    this.CantFindVM = new EventDescriptor(9, 0, 0, 2, 0, 0, 0L);
    this.UnableToSendKeyToVM = new EventDescriptor(10, 0, 0, 2, 0, 0, 0L);
    this.FailedToCreateDiffVhd = new EventDescriptor(11, 0, 0, 2, 0, 0, 0L);
    this.FailedToCreateVM = new EventDescriptor(12, 0, 0, 2, 0, 0, 0L);
    this.FailedVMStop = new EventDescriptor(13, 0, 0, 2, 0, 0, 0L);
    this.FailedStartVM = new EventDescriptor(14, 0, 0, 2, 0, 0, 0L);
    this.UnableToConnectToGuest = new EventDescriptor(15, 0, 0, 2, 0, 0, 0L);
    this.ConnectedToGuest = new EventDescriptor(0x10, 0, 0, 4, 0, 0, 0L);
    this.GuestIndicatedResolution = new EventDescriptor(0x11, 0, 0, 4, 0, 0, 0L);
    this.LoadedSkin = new EventDescriptor(0x12, 0, 0, 4, 0, 0, 0L);
    this.ButtonPressed = new EventDescriptor(0x13, 0, 0, 4, 0, 0, 0L);
    this.VirtualMachineStateChanged = new EventDescriptor(20, 0, 0, 4, 0, 0, 0L);
    this.ProxyInitialized = new EventDescriptor(4, 0, 0, 4, 0, 0, 0L);
    this.UsageShown = new EventDescriptor(0x16, 0, 0, 4, 0, 0, 0L);
    this.DisplayOrientationSet = new EventDescriptor(0x17, 0, 0, 4, 0, 0, 0L);
    this.ZoomSet = new EventDescriptor(0x18, 0, 0, 4, 0, 0, 0L);
    this.ScreenshotSavedToFile = new EventDescriptor(0x19, 0, 0, 4, 0, 0, 0L);
    this.KeySentToVM = new EventDescriptor(0x1a, 0, 0, 4, 0, 0, 0L);
    this.MouseEventSentToVM = new EventDescriptor(0x1b, 0, 0, 4, 0, 0, 0L);
    this.UnableToSendMouseEventToVM = new EventDescriptor(0x1c, 0, 0, 0, 0, 0, 0L);
    this.BringToFrontExecuted = new EventDescriptor(0x1d, 0, 0, 4, 0, 0, 0L);
    this.ConnectedToAccelerometer = new EventDescriptor(30, 0, 0, 4, 0, 0, 0L);
    this.UnableToConnectToAccelermometer = new EventDescriptor(0x1f, 0, 0, 0, 0, 0, 0L);
    this.InvalidWindowsDetected = new EventDescriptor(0x20, 0, 0, 2, 0, 0, 0L);
    this.HyperVNotEnabled = new EventDescriptor(0x21, 0, 0, 2, 0, 0, 0L);
    this.AskedToConnectExternalSwitches = new EventDescriptor(0x22, 0, 0, 4, 0, 0, 0L);
    this.ConnectedToGuestNotifications = new EventDescriptor(0x23, 0, 0, 4, 0, 0, 0L);
    this.UnableToConnectToGuestNotifications = new EventDescriptor(0x24, 0, 0, 2, 0, 0, 0L);
    this.FailedToSetVmProperties = new EventDescriptor(0x25, 0, 0, 2, 0, 0, 0L);
    this.FailedToInitializeSnapshots = new EventDescriptor(0x26, 0, 0, 2, 0, 0, 0L);
    this.FailedToSetVhd = new EventDescriptor(0x27, 0, 0, 2, 0, 0, 0L);
    this.RdpServerDisconnected = new EventDescriptor(40, 0, 0, 4, 0, 0, 0L);
    this.ScreenshotFailed = new EventDescriptor(0x29, 0, 0, 2, 0, 0, 0L);
    this.AccelerometerSendFailed = new EventDescriptor(0x2a, 0, 0, 2, 0, 0, 0L);
    this.LocationSendFailed = new EventDescriptor(0x2b, 0, 0, 2, 0, 0, 0L);
    this.SnapshotStarted = new EventDescriptor(0x2c, 0, 0, 0, 0, 0, 0L);
    this.SnapshotSucceeded = new EventDescriptor(0x2d, 0, 0, 0, 0, 0, 0L);
    this.SnapshotFailed = new EventDescriptor(0x2e, 0, 0, 2, 0, 0, 0L);
    this.CloseAfterSilentSnapshot = new EventDescriptor(0x2f, 0, 0, 0, 0, 0, 0L);
    this.ApplySnapshotFailed = new EventDescriptor(0x30, 0, 0, 2, 0, 0, 0L);
    this.RemovingSnapshotAfterFailedConnect = new EventDescriptor(50, 0, 0, 0, 0, 0, 0L);
    this.RemovingSnapshotAfterSettingsDidntMatch = new EventDescriptor(0x33, 0, 0, 0, 0, 0, 0L);
    this.ConnectedToShellReadyPipe = new EventDescriptor(0x34, 0, 0, 4, 0, 0, 0L);
    this.UnableToConnectToShellReadyPipe = new EventDescriptor(0x35, 0, 0, 2, 0, 0, 0L);
    this.ConnectedToTouch = new EventDescriptor(0x36, 0, 0, 4, 0, 0, 0L);
    this.UnableToConnectToTouch = new EventDescriptor(0x37, 0, 0, 2, 0, 0, 0L);
    this.TouchSendFailed = new EventDescriptor(0x38, 0, 0, 2, 0, 0, 0L);
    this.SendTextFailed = new EventDescriptor(0x39, 0, 0, 2, 0, 0, 0L);
    this.ReceiveAudioFromGuestWithSpinFailed = new EventDescriptor(0x3a, 0, 0, 2, 0, 0, 0L);
    this.SendMicrophoneDataToGuestFailed = new EventDescriptor(0x3b, 0, 0, 2, 0, 0, 0L);
    this.LoadUserSettingsFailed = new EventDescriptor(60, 0, 0, 0, 0, 0, 0L);
    this.SetGuestSystemTimeAndZoneFailed = new EventDescriptor(0x3d, 0, 0, 2, 0, 0, 0L);
    this.HypervisorNotRunning = new EventDescriptor(0x3e, 0, 0, 2, 0, 0, 0L);
    this.HyperVManagementServiceNotRunning = new EventDescriptor(0x3f, 0, 0, 2, 0, 0, 0L);
    this.UserAlreadyInHyperVAdmin = new EventDescriptor(0x40, 0, 0, 4, 0, 0, 0L);
    this.UserAddedToHyperVAdmins = new EventDescriptor(0x41, 0, 0, 4, 0, 0, 0L);
    this.FailedToAddUserToHyperVAdmins = new EventDescriptor(0x42, 0, 0, 0, 0, 0, 0L);
    this.SendKeyboardEvent = new EventDescriptor(0x43, 0, 0, 4, 0, 0, 0L);
    this.SendKeyboardEventFailed = new EventDescriptor(0x44, 0, 0, 2, 0, 0, 0L);
    this.AudioPlayThreadStarted = new EventDescriptor(0x45, 0, 0, 0, 0, 0, 0L);
    this.AudioPlayThreadExited = new EventDescriptor(70, 0, 0, 0, 0, 0, 0L);
    this.AudioDataReceivedFromGuest = new EventDescriptor(0x47, 0, 0, 0, 0, 0, 0L);
    this.AudioGlitch = new EventDescriptor(0x48, 0, 0, 0, 0, 0, 0L);
    this.AudioPaused = new EventDescriptor(0x49, 0, 0, 0, 0, 0, 0L);
    this.AudioResumed = new EventDescriptor(0x4a, 0, 0, 0, 0, 0, 0L);
    this.AudioDeviceChange = new EventDescriptor(0x4b, 0, 0, 0, 0, 0, 0L);
    this.MicrophoneCaptureThreadStarted = new EventDescriptor(0x4c, 0, 0, 0, 0, 0, 0L);
    this.MicrophoneCaptureThreadExited = new EventDescriptor(0x4d, 0, 0, 0, 0, 0, 0L);
    this.MicrophoneDataSentToGuest = new EventDescriptor(0x4e, 0, 0, 0, 0, 0, 0L);
    this.MicrophoneDeviceChange = new EventDescriptor(0x4f, 0, 0, 0, 0, 0, 0L);
    this.GetNetworkInfoFailed = new EventDescriptor(90, 0, 0, 2, 0, 0, 0L);
    this.IPRenewalInitiated = new EventDescriptor(0x5b, 0, 0, 4, 0, 0, 0L);
}

Hyper-V ホスト OS からのイベントのログ記録

WP8 JIT がどのようにアセンブリするか、またはいつガベージ コレクションを行うかについて詳しく知りたいとしましょう。VS2012 には、その情報をプロファイリング、保存、表示する分析ツールが付属しています。たとえば、プロファイリング セッションを開始する方法は次のとおりです。

WP8 分析セッションの開始

プロファイリング セッションが完了すると、アプリの下の "PerfLogs" フォルダーにプロファイリング セッションのデータがあることがわかります。CPU/Execution をプロファイリングした場合、そのフォルダーに VSPX ファイルが表示されます。VSPX ファイルの名前を ZIP に変更し、含まれているファイルを抽出します。その ZIP に ETL ファイルがあります。その ETL ファイルは、PerfView で調べることができるもう 1 つの ETW ログです。

ETL および VSPX ファイル

このような ETL ファイルを PerfView で開くと、各クラスが JITTed された時期、所要時間、IL とネイティブのサイズを確認できます。たとえば、アプリの App クラスは 123.461 ミリ秒で JITT され、1.2 ミリ秒で IL サイズが 105 でネイティブ サイズが 289 でした。

PerfView ジッティング データ

VS2012 を使用してそのデータをキャプチャする代わりに、プロファイリング API を直接使用することもできます。それをやりたい場合は、VS2012 の SilverlightProfiler.*.dll アセンブリをリバース エンジニアリングして、何を行っているかを確認し、VS2012 の外部で再作成する必要があります。

于 2013-01-18T00:50:44.187 に答える
1

私は、しばらくの間、デバッガーを接続せずに WP8 エミュレーターでアプリの実行を追跡するコンソールまたはその他の方法を探していました。Hyper-V VM で実行されているため、コンソールが使用できなくなったようです。

しかし、私は少し回避策を見つけました。メッセージをアプリの分離ストレージに記録する単純なクラスを作成できます (分離ストレージの詳細はこちら)。アプリを実行した後、Windows Phone Power Toolsを使用して分離ストレージのコンテンツを調べることができます(幸いなことに、「更新」オプションがあるため、エミュレーターでいくつかのアクションを実行してから、分離ストレージを修正することができます)。

于 2013-01-17T13:54:37.757 に答える