我是新手,想写一个查询Windows服务配置的小程序,现在遇到读内存非法的错误,不知道如何解决.程序如下:////查询所有预先定义的服务
procedure TControlWin.QueryAllService;
var
ServiceNames:Array[0..2] of string;
I:Integer;
iniFileName:string;
mService:TMyService;//自己定义的一种数据类型,保存服务名之类的参数
ServiceConfig:PQueryServiceConfig;
begin
ServiceNames[0] := 'MyServices1';
ServiceNames[1] := 'MyServices2';
ServiceNames[2] := 'MyServices3';
ComboBox1.Items.Clear;
for I := MyServiceList.Count - 1 downto 0 do
begin
TMyService(MyServiceList.Items[I]).Free;
end;
MyServiceList.Clear;
for I := 0 to 2 do
begin
New( ServiceConfig);//给QUERY_SERVICE_CONFIG结构体指针分配内存
if QueryMyServiceConfig(PAnsiChar(ServiceNames[I]),ServiceConfig) then
begin
mService := TMyService.Create;
mService.ServiceName := ServiceNames[I];
mService.DisplayName := StrPas(ServiceConfig.lpDisplayName);
mService.BinaryPath := StrPas(ServiceConfig.lpBinaryPathName);
mService.ServiceStatus := QueryMyServiceStatus(PAnsiChar(ServiceNames[I]));
MyServiceList.Add(mService);
ComboBox1.Items.Add(StrPas(ServiceConfig .lpDisplayName));
end;
Dispose(ServiceConfig);
end; if ComboBox1.Items.Count > 0 then
begin
ComboBox1.ItemIndex := 0;
mService := TMyService(MyServiceList.Items[0]);
iniFileName := ExtractFilePath(mService.BinaryPath)+mService.ServiceName+'.ini';
if FileExists(iniFileName) then
begin
btnStart.Enabled := not mService.ServiceStatus;
btnStop.Enabled := not btnStart.Enabled;
end
else
begin
btnStart.Enabled := False;
btnStop.Enabled := False;
btnConfigure.Enabled := True;
ShowMessage('请先配置参数');
end;
end
else
begin
btnStart.Enabled := False;
btnStop.Enabled := False;
btnConfigure.Enabled := False;
ShowMessage('服务尚未安装');
end;end;///查询某个服务的配置
function TControlWin.QueryMyServiceConfig(AServiceName: PAnsiChar; var AServiceConfig: PQueryServiceConfig):Boolean;
var
hManager:SC_HANDLE;
hService:SC_HANDLE;
buffSize:Cardinal;
Number:Cardinal;
begin
Result:=False;
hManager := OpenSCManager(nil,nil,SC_MANAGER_ALL_ACCESS);
if hManager = NULL then
Exit; hService := OpenService(hManager, AServiceName, SERVICE_QUERY_CONFIG);
if hService = 0 then
begin
if GetLastError = ERROR_SERVICE_DOES_NOT_EXIST then
begin
CloseServiceHandle(hManager);
Exit;
end;
end;
buffSize := 0;
if not QueryServiceConfig(hService,nil,0,Number) then
begin
if GetLastError = ERROR_INSUFFICIENT_BUFFER then
begin
buffSize := Number;
end;
end;
if not QueryServiceConfig(hService,AServiceConfig,buffSize,Number) then
Result:=False
else
Result:=True;
CloseServiceHandle(hService);
CloseServiceHandle(hManager);
end;///查询某个服务的状态
function TControlWin.QueryMyServiceStatus(AServiceName: PAnsiChar):Boolean;
var
hManager : SC_HANDLE;
hService : SC_HANDLE;
ServiceStatus : SERVICE_STATUS;
begin
Result := false;
hManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS); if hManager = 0 then
begin
Exit;
end; hService := OpenService(hManager, AServiceName, SERVICE_QUERY_STATUS);
if hService = 0 then
begin
CloseServiceHandle(hManager);
Exit;
end;
if not QueryServiceStatus(hService, ServiceStatus) then
begin
CloseServiceHandle(hService);
CloseServiceHandle(hManager);
Exit;
end;
case ServiceStatus.dwCurrentState of
4 : Result := True;//服务正在运行
end;
CloseServiceHandle(hService);
CloseServiceHandle(hManager);
end;问题描述:
我在窗体的FormCreate事件函数里调用了QueryAllService这个函数,程序正常,但是如果我在窗体里点击某个按钮,在这个按钮的Click事件处理函数里调用QueryAllService函数时,会出现一个读内存地址的错误,调用堆栈窗口显示是QueryAllService函数返回以后,显示"7c812a5b Kernel32.RaiseException + 0x52",看运行的顺序好像是在Graphics调用什么东西画窗体上的控件时出错,这里有个TResourceManager.AllocResource((no value)),估计是这里出问题了,因为程序调试的时候停在
TResourceManager.AllocResource函数的while (Result <> nil) and ((Result^.HashCode <> ResHash) or
not CompareMem(@Result^.Data, @ResData, ResDataSize)) do
Result := Result^.Next;
这里,而且此时Result^.Next中Next的地址刚好是报错的那个地址.不知道QueryMyServiceConfig在进行内存操作的时候跟窗体控件有什么关系啊,实在搞不懂,这个函数哪里有问题,高手指点一下
procedure TControlWin.QueryAllService;
var
ServiceNames:Array[0..2] of string;
I:Integer;
iniFileName:string;
mService:TMyService;//自己定义的一种数据类型,保存服务名之类的参数
ServiceConfig:PQueryServiceConfig;
begin
ServiceNames[0] := 'MyServices1';
ServiceNames[1] := 'MyServices2';
ServiceNames[2] := 'MyServices3';
ComboBox1.Items.Clear;
for I := MyServiceList.Count - 1 downto 0 do
begin
TMyService(MyServiceList.Items[I]).Free;
end;
MyServiceList.Clear;
for I := 0 to 2 do
begin
New( ServiceConfig);//给QUERY_SERVICE_CONFIG结构体指针分配内存
if QueryMyServiceConfig(PAnsiChar(ServiceNames[I]),ServiceConfig) then
begin
mService := TMyService.Create;
mService.ServiceName := ServiceNames[I];
mService.DisplayName := StrPas(ServiceConfig.lpDisplayName);
mService.BinaryPath := StrPas(ServiceConfig.lpBinaryPathName);
mService.ServiceStatus := QueryMyServiceStatus(PAnsiChar(ServiceNames[I]));
MyServiceList.Add(mService);
ComboBox1.Items.Add(StrPas(ServiceConfig .lpDisplayName));
end;
Dispose(ServiceConfig);
end; if ComboBox1.Items.Count > 0 then
begin
ComboBox1.ItemIndex := 0;
mService := TMyService(MyServiceList.Items[0]);
iniFileName := ExtractFilePath(mService.BinaryPath)+mService.ServiceName+'.ini';
if FileExists(iniFileName) then
begin
btnStart.Enabled := not mService.ServiceStatus;
btnStop.Enabled := not btnStart.Enabled;
end
else
begin
btnStart.Enabled := False;
btnStop.Enabled := False;
btnConfigure.Enabled := True;
ShowMessage('请先配置参数');
end;
end
else
begin
btnStart.Enabled := False;
btnStop.Enabled := False;
btnConfigure.Enabled := False;
ShowMessage('服务尚未安装');
end;end;///查询某个服务的配置
function TControlWin.QueryMyServiceConfig(AServiceName: PAnsiChar; var AServiceConfig: PQueryServiceConfig):Boolean;
var
hManager:SC_HANDLE;
hService:SC_HANDLE;
buffSize:Cardinal;
Number:Cardinal;
begin
Result:=False;
hManager := OpenSCManager(nil,nil,SC_MANAGER_ALL_ACCESS);
if hManager = NULL then
Exit; hService := OpenService(hManager, AServiceName, SERVICE_QUERY_CONFIG);
if hService = 0 then
begin
if GetLastError = ERROR_SERVICE_DOES_NOT_EXIST then
begin
CloseServiceHandle(hManager);
Exit;
end;
end;
buffSize := 0;
if not QueryServiceConfig(hService,nil,0,Number) then
begin
if GetLastError = ERROR_INSUFFICIENT_BUFFER then
begin
buffSize := Number;
end;
end;
if not QueryServiceConfig(hService,AServiceConfig,buffSize,Number) then
Result:=False
else
Result:=True;
CloseServiceHandle(hService);
CloseServiceHandle(hManager);
end;///查询某个服务的状态
function TControlWin.QueryMyServiceStatus(AServiceName: PAnsiChar):Boolean;
var
hManager : SC_HANDLE;
hService : SC_HANDLE;
ServiceStatus : SERVICE_STATUS;
begin
Result := false;
hManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS); if hManager = 0 then
begin
Exit;
end; hService := OpenService(hManager, AServiceName, SERVICE_QUERY_STATUS);
if hService = 0 then
begin
CloseServiceHandle(hManager);
Exit;
end;
if not QueryServiceStatus(hService, ServiceStatus) then
begin
CloseServiceHandle(hService);
CloseServiceHandle(hManager);
Exit;
end;
case ServiceStatus.dwCurrentState of
4 : Result := True;//服务正在运行
end;
CloseServiceHandle(hService);
CloseServiceHandle(hManager);
end;问题描述:
我在窗体的FormCreate事件函数里调用了QueryAllService这个函数,程序正常,但是如果我在窗体里点击某个按钮,在这个按钮的Click事件处理函数里调用QueryAllService函数时,会出现一个读内存地址的错误,调用堆栈窗口显示是QueryAllService函数返回以后,显示"7c812a5b Kernel32.RaiseException + 0x52",看运行的顺序好像是在Graphics调用什么东西画窗体上的控件时出错,这里有个TResourceManager.AllocResource((no value)),估计是这里出问题了,因为程序调试的时候停在
TResourceManager.AllocResource函数的while (Result <> nil) and ((Result^.HashCode <> ResHash) or
not CompareMem(@Result^.Data, @ResData, ResDataSize)) do
Result := Result^.Next;
这里,而且此时Result^.Next中Next的地址刚好是报错的那个地址.不知道QueryMyServiceConfig在进行内存操作的时候跟窗体控件有什么关系啊,实在搞不懂,这个函数哪里有问题,高手指点一下
解决方案 »
- 救命啊!!如何做dll窗体和传参数
- 关于Stringgrid和PopupMenu的组合开发问题
- 登陆界面登陆后,如何让他退出内存?
- 奇怪問題,外鍵引起的
- DBgrid 的怎么不能实现这个功能??? 不会是真的吧
- 哪里有通过网络点对点发送文件的源码下载,急急急急急急
- 为什么编译提示如下错误???进来拿分...
- 为什么在DBGrid中同一条记录总是显示36次?
- 如何在htm万年历中添加10天循环的节日提醒
- 我是新手,有1个问题!
- 关于用ComboBox保存代码的问题,急ing
- 我用D写了个webservice的dll,发布到网站,但每次更新dll的时候,必须停掉IIS服务,如果我是租用的空间,那不是一点办法都没有?这个该如
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
SysUtils, Windows, WinSvc;type TServiceManager = class
private
{ Private declarations }
ServiceControlManager: SC_Handle;
ServiceHandle: SC_Handle;
protected
function DoStartService(NumberOfArgument: DWORD; ServiceArgVectors: PChar): Boolean;
public
{ Public declarations }
function Connect(MachineName: PChar = nil; DatabaseName: PChar = nil;
Access: DWORD = SC_MANAGER_ALL_ACCESS): Boolean; // Access may be SC_MANAGER_ALL_ACCESS
function OpenServiceConnection(ServiceName: PChar): Boolean;
function StartService: Boolean; overload; // Simple start
function StartService(NumberOfArgument: DWORD; ServiceArgVectors: PChar): Boolean;
overload; // More complex start
function StopService: Boolean;
procedure PauseService;
procedure ContinueService;
procedure ShutdownService;
procedure DisableService;
function GetStatus: DWORD;
function GetStatusCn: string;
function ServiceRunning: Boolean;
function ServiceStopped: Boolean;
end;implementation{ TServiceManager }function TServiceManager.Connect(MachineName, DatabaseName: PChar;
Access: DWORD): Boolean;
begin
{ open a connection to the windows service manager }
ServiceControlManager := OpenSCManager(MachineName, DatabaseName, Access);
Result := (ServiceControlManager <> 0);
end;function TServiceManager.OpenServiceConnection(ServiceName: PChar): Boolean;
begin
{ open a connetcion to a specific service }
ServiceHandle := OpenService(ServiceControlManager, ServiceName, SERVICE_ALL_ACCESS);
Result := (ServiceHandle <> 0);
end;procedure TServiceManager.PauseService;
var
ServiceStatus: TServiceStatus;
begin
{ Pause the service: attention not supported by all services }
ControlService(ServiceHandle, SERVICE_CONTROL_PAUSE, ServiceStatus);
end;function TServiceManager.StopService: Boolean;
var
ServiceStatus: TServiceStatus;
begin
{ Stop the service }
Result := ControlService(ServiceHandle, SERVICE_CONTROL_STOP, ServiceStatus);
end;procedure TServiceManager.ContinueService;
var
ServiceStatus: TServiceStatus;
begin
{ Continue the service after a pause: attention not supported by all services }
ControlService(ServiceHandle, SERVICE_CONTROL_CONTINUE, ServiceStatus);
end;procedure TServiceManager.ShutdownService;
var
ServiceStatus: TServiceStatus;
begin
{ Shut service down: attention not supported by all services }
ControlService(ServiceHandle, SERVICE_CONTROL_SHUTDOWN, ServiceStatus);
end;function TServiceManager.StartService: Boolean;
begin
Result := DoStartService(0, '');
end;function TServiceManager.StartService(NumberOfArgument: DWORD;
ServiceArgVectors: PChar): Boolean;
begin
Result := DoStartService(NumberOfArgument, ServiceArgVectors);
end;function TServiceManager.GetStatus: DWORD;
var
ServiceStatus: TServiceStatus;
begin
{ Returns the status of the service. Maybe you want to check this
more than once, so just call this function again.
Results may be: SERVICE_STOPPED
SERVICE_START_PENDING
SERVICE_STOP_PENDING
SERVICE_RUNNING
SERVICE_CONTINUE_PENDING
SERVICE_PAUSE_PENDING
SERVICE_PAUSED }
QueryServiceStatus(ServiceHandle, ServiceStatus);
Result := ServiceStatus.dwCurrentState;
end;procedure TServiceManager.DisableService;
begin
{ Implementation is following... }
DeleteService(ServiceHandle);
end;function TServiceManager.ServiceRunning: Boolean;
begin
Result := (GetStatus = SERVICE_RUNNING);
end;function TServiceManager.ServiceStopped: Boolean;
begin
Result := (GetStatus = SERVICE_STOPPED);
end;function TServiceManager.DoStartService(NumberOfArgument: DWORD;
ServiceArgVectors: PChar): Boolean;
begin
Result := WinSvc.StartService(ServiceHandle, NumberOfArgument, ServiceArgVectors);
end;
function TServiceManager.GetStatusCn: string;
begin
case GetStatus of
SERVICE_STOPPED: Result:='服务已停止';
//SERVICE_START_PENDING: Result:='正在启动服务';
//SERVICE_STOP_PENDING: Result:='正在停止服务';
SERVICE_RUNNING: Result:='服务正在运行';
//SERVICE_CONTINUE_PENDING: Result:='正在重起服务';
//SERVICE_PAUSE_PENDING: Result:='正在停止服务';
SERVICE_PAUSED: Result:='服务已暂停';
else
Result:=( '状态未知' );
end;
end;end.