Windows Phone 8仿真器上的控制台窗口功能

时间:2013-01-09 03:29:05

标签: windows-phone-8 windows-phone-8-emulator

Windows Phone 7 Emulator有一个很好的控制台窗口功能,可以通过注册表设置(EnableConsole)或通过XDE.exe的decfg参数启用

即使没有附加调试器也能正常工作。它有助于查找运行时绑定问题,例外。

有没有办法在Windos 8 Phone模拟器中启用控制台窗口?

2 个答案:

答案 0 :(得分:12)

WP8模拟器是对WP7模拟器的完全重写,因此它不太可能支持相同的未记录的调试消息。在一天结束时,问题是:你想记录什么?

  • 您是否尝试获取特定于您应用的信息?然后使用Pavel的想法通过CoreCon API为WP8共享IsoStore文件。
  • 您是否尝试在模拟器本身中获取有趣事件的消息?模拟器记录到ETW提供程序,您可以从该日志中读取。我会在这里展示如何。
  • 您是否尝试从WP8操作系统中获取信息?然后生成一个ETL文件并检查它或直接使用分析API。

记录特定于应用的消息

假设您的应用中发生了一些有趣的事情,例如重要的按钮点击。您需要在应用程序中记录该消息并将该消息写入IsoStore(或发送到自定义Web服务)。我使用MetroLog作为我的WP8& Win8日志记录,但只要文件写入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 start with all the aforementioned options

  • 将工作目录设置为适用于WP8的XDE.exe的位置。
  • 确保首先从VS2012运行该仿真器以创建Hyper-V映像。或者,如果您知道如何自己创建图像并使用/ VHD参数。
  • 调用XDE.exe时,您可以从Hyper-V管理器获取/ NAME参数。
  • 确保将额外的提供商设置为包含“ff86852d-541c-4f7e-98c5-5761e8cb7074”。

现在从PerfView运行模拟器,做一些事情,关闭模拟器并停止收集信息。完成后,您可以看到模拟器中所有内容的日志。一旦您在提供者ID下过滤它,有趣的东西就在“事件”日志下。

PerfView events data

在上面的打印屏幕中,您可以查看事件以及它们何时出现在模拟器中。例如,事件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托管操作系统记录事件

假设您想了解更多有关WP8 JITs程序集或何时执行垃圾收集的信息。 VS2012附带分析工具,可分析,存储和显示该信息。例如,以下是如何开始分析会话:

Starting a WP8 analysis session

分析会话完成后,您可以看到应用程序下的“PerfLogs”文件夹中包含分析会话的数据。如果您已经分析了CPU /执行,那么您可以在该文件夹中看到VSPX文件。将VSPX文件重命名为ZIP并提取其包含的文件。在该ZIP中,您将找到一个ETL文件。那个ETL文件是另一个我们可以检查PerfView的ETW日志。

ETL and VSPX files

当我们在PerfView中打开这样一个ETL文件时,我们可以看到每个类都是JITTed,花了多长时间以及IL&原始尺寸。例如,我们的应用程序的App类是JITTed为123.461ms,为1.2ms,IL大小为105,原始大小为289。

PerfView Jitting data

您也可以直接使用性能分析API,而不是使用VS2012来捕获该数据。如果这是你想要做的事情,你将不得不对VS2012的SilverlightProfiler。*。dll程序集进行逆向工程,以便了解他们正在做什么并在VS2012之外重新创建它。

答案 1 :(得分:1)

我一直在寻找一个控制台或任何其他方式来跟踪WP8模拟器上的应用程序执行,而无需附加调试器一段时间。看起来,因为它在hyper-v VM上运行,控制台不再可用。

但是我找到了一些解决方法。您可以创建一个简单的类,将您的消息记录到应用程序的独立存储(更多关于隔离存储here)。运行应用程序后,您可以使用Windows Phone Power Tools检查隔离存储的内容(通常它具有“刷新”选项,因此您可以在模拟器上执行某些操作,然后只修改隔离存储)。