Не понимаю, почему я не могу взять строки lpRebootMsg или lpCommand из структуры... Это указатель, но указывает на какую-то хрень... Помогите, pls...
Прогу наваял специально для тестирования этого случая, думаю проблем скомпилить не составит, у кого Delphi 5.
program Main;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows, WinSvc;
Function forCons(aStr: String): String;
Begin
Result := aStr; UniqueString(Result);
ANSItoOEM(PChar(Result), PChar(Result));
End;
Function QueryServiceConfig2A(
hService: SC_HANDLE; // handle to service
dwInfoLevel: DWORD; // information level
lpInfo: Pointer; // new data
cbBufSize: DWORD; // size of buffer
Var pcbBytesNeeded: DWORD // bytes needed
): BOOL; StdCall; External AdvApi32;
Type
_SERVICE_DESCRIPTION = Record
lpDescription: LPTSTR;
End;
SERVICE_DESCRIPTION = _SERVICE_DESCRIPTION;
PSERVICE_DESCRIPTION = ^SERVICE_DESCRIPTION;
_SC_ACTION_TYPE = (SC_ACTION_NONE, SC_ACTION_RESTART, SC_ACTION_REBOOT, SC_ACTION_RUN_COMMAND);
SC_ACTION_TYPE = _SC_ACTION_TYPE;
_SC_ACTION = Record
aType: SC_ACTION_TYPE;
Delay: DWORD;
End;
TSC_ACTION = _SC_ACTION;
PSC_ACTION = ^TSC_ACTION;
TSC_ACTION_Array = Array[0..0] Of TSC_ACTION;
PSC_ACTION_Array = ^TSC_ACTION_Array;
_SERVICE_FAILURE_ACTIONS = Record
dwResetPeriod: DWORD;
lpRebootMsg: LPTSTR;
lpCommand: LPTSTR;
cActions: DWORD;
lpsaActions: PSC_ACTION_Array;
End;
TSERVICE_FAILURE_ACTIONS = _SERVICE_FAILURE_ACTIONS;
PSERVICE_FAILURE_ACTIONS = ^TSERVICE_FAILURE_ACTIONS;
Const
SERVICE_CONFIG_DESCRIPTION = 1;
SERVICE_CONFIG_FAILURE_ACTIONS = 2;
ActionTypeStrings: Array[SC_ACTION_NONE..SC_ACTION_RUN_COMMAND] Of String = (
'SC_ACTION_NONE', 'SC_ACTION_RESTART', 'SC_ACTION_REBOOT', 'SC_ACTION_RUN_COMMAND'
);
Function GetServiceDescription(sHndl: THandle): String;
Var
BytesNeeded: DWord;
OutBuff: PSERVICE_DESCRIPTION;
Begin
QueryServiceConfig2A(sHndl, SERVICE_CONFIG_DESCRIPTION, Nil, 0, BytesNeeded);
If GetLastError <> ERROR_INSUFFICIENT_BUFFER Then
RaiseLastWin32Error;
GetMem(OutBuff, BytesNeeded);
Try
Win32Check(QueryServiceConfig2A(sHndl, SERVICE_CONFIG_DESCRIPTION, OutBuff, BytesNeeded, BytesNeeded));
Result := OutBuff.lpDescription;
Finally
FreeMem(OutBuff);
End;
End;
Function GetServiceFailureActions(sHndl: THandle): PSERVICE_FAILURE_ACTIONS;
Var
BytesNeeded: DWord;
Begin
QueryServiceConfig2A(sHndl, SERVICE_CONFIG_DESCRIPTION, Nil, 0, BytesNeeded);
If GetLastError <> ERROR_INSUFFICIENT_BUFFER Then
RaiseLastWin32Error;
GetMem(Result, BytesNeeded);
Try
Win32Check(QueryServiceConfig2A(sHndl, SERVICE_CONFIG_FAILURE_ACTIONS, Result, BytesNeeded, BytesNeeded));
Except
FreeMem(Result);
Raise;
End;
End;
Var
scHndl, sHndl: THandle;
anActions: PSERVICE_FAILURE_ACTIONS;
J: Integer;
begin
Try
WriteLn;
WriteLn('Hello, this test application will show work of some API functions, wait...');
Write('Try to open SC Manager...');
scHndl := OpenSCManager(Nil, Nil, MAXIMUM_ALLOWED);
Win32Check(scHndl <> 0);
Try
WriteLn('Ok');
Write('Try to open "WinMgmt" Service...');
sHndl := OpenService(scHndl, 'WinMgmt', MAXIMUM_ALLOWED);
Win32Check(sHndl <> 0);
Try
WriteLn('Ok');
Write('Getting Service Description...');
WriteLn('Ok'#$A'Service Description is: "' + forCons(GetServiceDescription(sHndl)) + '";');
Write('Getting Service Failure Actions...');
anActions := GetServiceFailureActions(sHndl);
Try
WriteLn('Ok');
If anActions = Nil Then
Raise EAbort.Create('Very strange error... Exiting!');
WriteLn('Reset Period, seconds: ', anActions.dwResetPeriod);
WriteLn('Reboot message: "', String(anActions.lpRebootMsg), '";');
WriteLn('Command action: "', String(anActions.lpCommand), '";');
WriteLn('Actions count: ', anActions.cActions, ';');
For J := 0 To anActions.cActions - 1 Do
Begin
WriteLn;
WriteLn(J, ' action type: ', ActionTypeStrings[anActions.lpsaActions[J].aType]);
WriteLn(J, ' action delay, msec: ', anActions.lpsaActions[J].Delay);
End;
WriteLn;
WriteLn('End of actions enumeration.');
Finally
FreeMem(anActions);
End;
Finally
CloseServiceHandle(sHndl);
End;
Finally
CloseServiceHandle(scHndl);
End;
Except
on E: Exception Do
Begin
WriteLn; WriteLn;
If E Is EAbort Then WriteLn(forCons(E.Message))
Else Begin
WriteLn('Exception occured, apllication will be terminated!');
WriteLn('Exception class: "' + E.ClassName + '";');
WriteLn('Exception message: "' + ForCons(E.Message) + '".');
End;
End;
End;
Write('Press Enter to exit...');
ReadLn;
end.
---
Тестировать надо под Win2k, что понятно ввиду специфики API. Нужно открыть консоль MMC, для сервиса «Инструментарий управления Windows», выбрать вкладку «Восстановление», потом сказать, что при последующих сбоях надо перезагружать компьютер, нажать на кнопку «Параметры перезагрузки компьютера», там закрыжить, что нужно слать сообщение, и набрать некое сообщение. После чего запустить прогу.
К сожалению, не могу добиться того, чтобы извлечь это сообщение программно.
Всем заранее огромное спасибо!
|