пятница, 16 апреля 2010 г.

Вывод диагностической информации в Process Monitor

   Начиная с версии 2.9 очень полезный инструмент от Марка Руссиновича (Mark Russinovich) и Брюса Когсвелла (Bryce Cogswell) Process Monitor поддерживает новую функциональность - возможность вывода своих диагностических (отладочных) сообщений в Process Monitor, для того чтобы можно было лучше коррелировать выполняемые приложением операции с другими событиями. Аналог OutputDebugString, но вывод показывается Process Monitor-ом (оригинал новости - [1]).


   Process Monitor дает возможность непривилегированным приложениям передать своему драйверу строку Unicode длиной до 2048 символов. В справке приведен кода, который показывает, как передать отладочное сообщение (также в справке описано, что должно быть включено для отображения диагностических сообщений).

   Я написал небольшой модуль для Delphi (2007), реализующий отладочный вывод сообщений в Process Monitor (по ссылке [3] можно найти похожую реализацию, тоже для Delphi). Джон Роббинс написал вспомогательный класс для управляемого кода ([2]).
unit uProcessMonitorTracing;

{******************************************************************************}

interface
{******************************************************************************}

uses Windows;

  function ProcmonTraceMessage(const Message: WideString): Boolean;

{******************************************************************************}

implementation

{******************************************************************************}

const
  METHOD_BUFFERED         = 0;
  FILE_WRITE_ACCESS       = $0002;
  FILE_DEVICE_PROCMON_LOG = $00009535;

const
  szProcmonDevice: WideString = '\\.\Global\ProcmonDebugLogger';

var
  IOCTL_EXTERNAL_LOG_DEBUGOUT: ULONG = 0;

function OpenProcmonDevice(): THandle;
begin
  Result := CreateFileW(PWideChar(szProcmonDevice), GENERIC_READ or GENERIC_WRITE,
    FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE, nil, OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL, 0)
end;

function ProcmonTraceMessage(const Message: WideString): Boolean;
var
  hDevice: THandle;
  fOk: BOOL;
  cbSize, LastError: DWORD;
begin
  fOk := False;
  hDevice := OpenProcmonDevice();

  if (hDevice <> INVALID_HANDLE_VALUE) then
    begin
      cbSize := 0;
      fOk := DeviceIoControl(hDevice, IOCTL_EXTERNAL_LOG_DEBUGOUT, PWideChar(Message),
        Length(Message) * SizeOf(WideChar), nil, 0, cbSize, nil);

      if not fOk then
        LastError := GetLastError();

      CloseHandle(hDevice)
    end
  else
    LastError := ERROR_BAD_DEVICE;

  Result := fOk;
  if not Result then
    SetLastError(LastError)
end;

function CTL_CODE(nDeviceType, nFunction, nMethod, nAccess: DWORD): DWORD;
begin
  Result := ((nDeviceType shl 16) or (nAccess shl 14) or
    (nFunction shl 2) or nMethod)
end;

initialization
  IOCTL_EXTERNAL_LOG_DEBUGOUT := CTL_CODE(FILE_DEVICE_PROCMON_LOG, $81,
    METHOD_BUFFERED, FILE_WRITE_ACCESS);

end.

Ссылки
[1] Updates: Process Monitor v2.9
[2] See the I/O You Caused by Getting Your Diagnostic Tracing into Process Monitor
[3] Interface unit for sending debug messages to SysInternals ProcessMonitor

Комментариев нет:

Отправить комментарий