我目前正在使用Inno Setup安装程序,它检查给定服务的依赖服务。根据MSDN文档,我需要函数EnumDependentServices()
。
然而,当我向函数传递参数时,Inno Setup给我状态代码5,代表 “Access Denied”,尽管我以管理员身份执行安装程序。
我使用SC_MANAGER_ALL_ACCESS (0xF003F)
权限启动服务处理程序,但它仍然拒绝我的函数调用。
SCManager和打开的Service(我用“DnsCache”测试过)都返回非零值,并与我的其他函数一起工作。
下面是我的.iss
文件中的[Code]
片段:
#ifdef UNICODE
#define AW "W"
#else
#define AW "A"
#endif
type
SERVICE_STATUS = record
dwServiceType: DWORD;
dwCurrentState: DWORD;
dwControlsAccepted: DWORD;
dwWin32ExitCode: DWORD;
dwServiceSpecificExitCode: DWORD;
dwCheckPoint: DWORD;
dwWaitHint: DWORD;
end;
HANDLE = THandle;
PDWord = DWORD;
const
SERVICE_QUERY_CONFIG = $1;
SC_MANAGER_CONNECT = $0001;
SERVICE_QUERY_STATUS = $0004;
SERVICE_CHANGE_CONFIG = $2;
SERVICE_CURRENT_STATUS = $0003;
SERVICE_START = $10;
SERVICE_STOP = $20;
SERVICE_ALL_ACCESS = $f01ff;
SC_MANAGER_ALL_ACCESS = $F003F;
SERVICE_WIN32_OWN_PROCESS = $10;
SERVICE_WIN32_SHARE_PROCESS = $20;
SERVICE_WIN32 = $30;
SERVICE_INTERACTIVE_PROCESS = $100;
SERVICE_BOOT_START = $0;
SERVICE_SYSTEM_START = $1;
SERVICE_AUTO_START = $2;
SERVICE_DEMAND_START = $3;
SERVICE_DISABLED = $4;
SERVICE_DELETE = $10000;
SERVICE_CONTROL_STOP = $1;
SERVICE_CONTROL_PAUSE = $2;
SERVICE_CONTROL_CONTINUE = $3;
SERVICE_CONTROL_INTERROGATE = $4;
SERVICE_STOPPED = $1;
SERVICE_START_PENDING = $2;
SERVICE_STOP_PENDING = $3;
SERVICE_RUNNING = $4;
SERVICE_CONTINUE_PENDING = $5;
SERVICE_PAUSE_PENDING = $6;
SERVICE_PAUSED = $7;
// #######################################################################################
// nt based service utilities
// #######################################################################################
function OpenSCManager(lpMachineName, lpDatabaseName: string; dwDesiredAccess :cardinal): HANDLE;
external 'OpenSCManager{#AW}@advapi32.dll stdcall';
function OpenService(hSCManager :HANDLE;lpServiceName: string; dwDesiredAccess :cardinal): HANDLE;
external 'OpenService{#AW}@advapi32.dll stdcall';
function CloseServiceHandle(hSCObject :HANDLE): boolean;
external 'CloseServiceHandle@advapi32.dll stdcall';
function CreateService(hSCManager :HANDLE;lpServiceName, lpDisplayName: string;dwDesiredAccess,dwServiceType,dwStartType,dwErrorControl: cardinal;lpBinaryPathName,lpLoadOrderGroup: String; lpdwTagId : cardinal;lpDependencies,lpServiceStartName,lpPassword :string): cardinal;
external 'CreateService{#AW}@advapi32.dll stdcall';
function DeleteService(hService :HANDLE): boolean;
external 'DeleteService@advapi32.dll stdcall';
function StartNTService(hService :HANDLE;dwNumServiceArgs : cardinal;lpServiceArgVectors : cardinal) : boolean;
external 'StartService{#AW}@advapi32.dll stdcall';
function ControlService(hService :HANDLE; dwControl :cardinal;var ServiceStatus :SERVICE_STATUS) : boolean;
external 'ControlService@advapi32.dll stdcall';
function QueryServiceStatus(hService :HANDLE;var ServiceStatus :SERVICE_STATUS) : boolean;
external 'QueryServiceStatus@advapi32.dll stdcall';
function QueryServiceStatusEx(hService :HANDLE;ServiceStatus :SERVICE_STATUS) : boolean;
external 'QueryServiceStatus@advapi32.dll stdcall';
function GetLastError() : cardinal;
external 'GetLastError@kernel32.dll stdcall';
function EnumDependentServices(
hService :HANDLE;
ServiceStatus : LongInt;
lpServices: DWORD;
cbBufSize: DWORD;
var pcbBytesNeeded: DWORD;
var lpServicesReturned : DWORD) : boolean;
external 'EnumDependentServices{#AW}@advapi32.dll stdcall';
function HasServiceDependencies(const ServiceName: string) : boolean;
var
hSCM: HANDLE;
hService: HANDLE;
pcbBytesNeeded : DWORD;
lpServicesReturned : DWORD;
begin
hSCM := OpenSCManager('', '', SC_MANAGER_ALL_ACCESS);
Log(Format('%d', [hSCM]));
if hSCM <> 0 then begin
hService := OpenService(hSCM, ServiceName, SERVICE_QUERY_STATUS);
Log(Format('%d', [hService]));
if hService <> 0 then begin
EnumDependentServices( hService, SERVICE_CURRENT_STATUS, 0, 0, pcbBytesNeeded, lpServicesReturned);
MsgBox(SysErrorMessage(DLLGetLastError()), mbError, mb_Ok);
CloseServiceHandle(hService)
end;
CloseServiceHandle(hSCM)
end;
Result := false;
end;
function InitializeSetup(): Boolean;
begin
Log('InitializeSetup called');
Result := HasServiceDependencies('Dnscache');
if Result = False then
MsgBox('InitializeSetup:' #13#13 'Ok, bye bye.', mbInformation, MB_OK);
end;
我尝试修改状态和查询代码为其他代码,但这也没有帮助。
1条答案
按热度按时间ozxc1zmp1#
根据
EnumDependentServices()
文档:[in] hService
服务的句柄,该句柄由
OpenService
或CreateService
函数返回,必须具有SERVICE_ENUMERATE_DEPENDENTS
访问权限,详情请参阅服务安全和访问权限...
以下错误代码可能由服务控制管理器设置。其他错误代码可能由服务控制管理器调用的注册表函数设置。
| 返回码|说明|
| --------------|--------------|
| 错误_访问_拒绝|句柄没有SERVICE_ENUMERATE_DEPENDENTS访问权限。|
当你打开你的
hService
句柄时,你没有指定SERVICE_ENUMERATE_DEPENDENTS
权限,只指定了SERVICE_QUERY_STATUS
权限(仅由QueryServiceStatus/Ex()
和NotifyServiceStatusChange()
使用,而不是EnumDependentServices()
)。另外,
SC_MANAGER_ALL_ACCESS
请求的权限太多。不要请求比实际需要的权限更多的权限。在这种情况下,您只需要SC_MANAGER_CONNECT
。此外,
SERVICE_CURRENT_STATUS
不是Win32 API定义的有效符号。您将其声明为$0003
,其值与SERVICE_STATE_ALL
相同,SERVICE_STATE_ALL
是EnumDependentServices()
定义的实际符号。试试这个: