Функция окна консоли в эмуляторе Windows Phone 8

Эмулятор Windows Phone 7 имел удобную функцию окна консоли, которую можно включить с помощью параметра реестра (EnableConsole) или с помощью параметра decfg XDE.exe.

Он работал даже без подключения отладчика. Это было полезно при поиске проблем с привязкой во время выполнения, исключений.

Есть ли способ включить окно консоли в эмуляторе телефона Windows 8?


person Lokeshwer    schedule 09.01.2013    source источник


Ответы (2)


Эмулятор WP8 — это полностью переписанный эмулятор WP7, поэтому маловероятно, что он поддерживает те же самые недокументированные отладочные сообщения. В конце дня вопрос: что вы пытаетесь зарегистрировать?

  • Вы пытаетесь получить информацию, относящуюся к вашему приложению? Затем воспользуйтесь идеей Павла по обмену файлами IsoStore через CoreCon API для WP8.
  • Вы пытаетесь получать сообщения об интересных событиях в самом эмуляторе? Эмулятор регистрируется у поставщика ETW, и вы можете читать этот журнал. Я покажу здесь, как.
  • Вы пытаетесь получить информацию изнутри ОС WP8? Затем создайте файл ETL и проверьте его или используйте API-интерфейсы профилирования напрямую.

Запись конкретных сообщений приложения

Допустим, в вашем приложении происходит что-то интересное, например, нажатие важной кнопки. Вы захотите зарегистрировать это в своем приложении и написать это сообщение в IsoStore (или отправить в пользовательскую веб-службу). Я использую MetroLog для ведения журнала WP8 и Win8, но вы можете использовать все, что хотите, если файлы записываются в IsoStore. Проверьте MetroLog @ https://github.com/mbrit/MetroLog

Затем вы можете использовать CoreCon API для считывания файла. Я загрузил образец кода этих API для WP8 @ https://stackoverflow.com/a/13429709/81687


Запись определенных сообщений эмулятора

Скажем, вам интересно узнать, когда был активирован эмулятор, когда был установлен масштаб, не удалось ли сделать снимок экрана или произошло событие касания. Эмулятор WP8 использует поставщика ETW ff86852d-541c-4f7e-98c5-5761e8cb7074 для регистрации этих и других событий. Подробнее о ETW можно прочитать здесь @ http://msdn.microsoft.com/en-us/magazine/cc163437.aspx

Сначала загрузите PerfView, чтобы запустить XDE.exe. эмулятор и начните захват вывода ETW.

PerfView стартует со всеми вышеупомянутыми параметрами

  • Установите в качестве рабочего каталога расположение XDE.exe для WP8.
  • Обязательно сначала запустите этот эмулятор из VS2012, чтобы создать образ Hyper-V. Или, если вы знаете, как вы можете создать образ самостоятельно и использовать параметр /VHD.
  • При вызове XDE.exe вы можете получить параметр /NAME из диспетчера Hyper-V.
  • Убедитесь, что дополнительный поставщик включает «ff86852d-541c-4f7e-98c5-5761e8cb7074».

Теперь запустите эмулятор из PerfView, сделайте что-нибудь, выключите эмулятор и прекратите сбор информации. Как только вы это сделаете, вы сможете увидеть журнал всего, что происходило в эмуляторе. Интересный материал находится в журнале «События», если вы отфильтруете его по идентификатору поставщика.

Данные о событиях PerfView

На приведенном выше экране печати вы можете увидеть события и то, когда они произошли в эмуляторе. Например, событие 76 — это MicrophoneCaptureThreadStarted для эмулятора, и оно произошло через 27 секунд после начала сеанса профилирования. Полный список кодов событий см. в разделе Microsoft.Xde.Etw.WindowsPhoneEmulatorProvider c'tor в сборке XDE.exe. Это копия вставлена ​​сюда для вашего убеждения:

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 выполняет JIT-сборку или когда он выполняет сборку мусора. VS2012 поставляется с инструментами анализа, которые профилируют, сохраняют и отображают эту информацию. Например, вот как начать сеанс профилирования:

Начало сеанса анализа WP8

После завершения сеанса профилирования вы можете увидеть, что папка «PerfLogs» в вашем приложении содержит данные для сеанса профилирования. Если вы профилировали CPU/Execution, вы можете увидеть файлы VSPX в этой папке. Переименуйте файл VSPX в ZIP и извлеките содержащиеся в нем файлы. В этом ZIP вы найдете файл ETL. Этот файл ETL является еще одним журналом ETW, который мы можем изучить PerfView.

Файлы ETL и VSPX

Когда мы открываем такой ETL-файл в PerfView, мы можем видеть, когда каждый класс был JITT, сколько времени это заняло, а также размеры IL и Native. Например, класс App нашего приложения был JITTed на 123,461 мс, на 1,2 мс с размером IL 105 и собственным размером 289.

PerfView Jitter data

Вы также можете напрямую использовать API-интерфейсы профилирования вместо использования VS2012 для сбора этих данных. Если это то, что вы хотели бы сделать, вам придется перепроектировать сборки SilverlightProfiler.*.dll VS2012, чтобы увидеть, что они делают, и воссоздать их вне VS2012.

person JustinAngel    schedule 18.01.2013
comment
Спасибо. Попробую и сообщу - person Lokeshwer; 18.01.2013

Я тоже некоторое время искал консоль или любой другой способ отслеживать выполнение приложения на эмуляторе WP8 без подключения отладчика. Похоже, поскольку он работает на виртуальной машине Hyper-V, консоль больше недоступна.

Однако я нашел небольшой обходной путь. Вы можете создать простой класс, который будет записывать ваши сообщения в изолированное хранилище приложения (подробнее об изолированном хранилище здесь). После того как вы запустите свое приложение, вы сможете изучить содержимое изолированного хранилища с помощью инструментов Windows Phone Power Tools (к счастью, у него есть «обновить», чтобы вы могли выполнять некоторые действия на эмуляторе, а затем просто пересматривать изолированное хранилище).

person Pavel K    schedule 17.01.2013