[英]How in Delphi can I run a command with administrator privileges?
I am trying to stop mysql from Delphi XE2 on Win 7. I have written some code based on something I found on the web for Delphi 7, that was supposed to do this, but it doesn't work: 我试图从Win 7上的Delphi XE2中停止mysql。我已经基于在网上找到的有关Delphi 7的内容编写了一些代码,该代码本来可以这样做,但它不起作用:
function StopMySQL: boolean;
const
UserName = 'Mark';
Domain = 'PC-Mark';
Command = 'net stop mysql';
var
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
begin
FillChar(StartupInfo, SizeOf(StartupInfo), #0);
StartupInfo.cb := SizeOf(StartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := SW_HIDE;
result := CreateProcessWithLogonW(Username, Domain, Password, 0, nil, Command, 0, nil, nil, StartupInfo, ProcessInfo);
if result then
WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
end;
Does anyone know how to do this? 有谁知道如何做到这一点?
TIA Mark Patterson TIA马克·帕特森
Since Vista you will need an elevated access to start/stop a service. 从Vista开始,您将需要提升的权限才能启动/停止服务。
One simple way would be to use RunAs with Shellexecute(Ex). 一种简单的方法是将RunAs与Shellexecute(Ex)一起使用。
ShellExecute(handle,'RunAs','net','stop mysql',nil,sw_Show);
The better way would be using a manifest, which could look like this: 更好的方法是使用清单,看起来像这样:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
publicKeyToken="6595b64144ccf1df"
language="*"
processorArchitecture="*"/>
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" />
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
a minimum solution, no need of "net", could look like this, there should be more done, eg. 一个最小的解决方案,不需要“ net”,看起来像这样,应该做更多的事情,例如。 testing if the service is running, but thats ut to you and can be done wit WinSvc to:
测试该服务是否正在运行,但这很重要,可以通过WinSvc完成:
implementation
uses WinSvc;
{$R *.dfm}
{$R administrator.res}
function ServiceStop(Machine, ServiceName: string): Boolean;
var
ServiceControlManager, ServiceHandle: SC_Handle;
ServiceStatus: TServiceStatus;
dwCheckPoint: DWORD;
begin
ServiceControlManager := OpenSCManager(PChar(Machine), nil, SC_MANAGER_CONNECT);
if ServiceControlManager > 0 then
begin
ServiceHandle := OpenService(ServiceControlManager, PChar(ServiceName),
SERVICE_STOP or SERVICE_QUERY_STATUS);
if ServiceHandle > 0 then
begin
if (ControlService(ServiceHandle, SERVICE_CONTROL_STOP, ServiceStatus)) then
begin
if (QueryServiceStatus(ServiceHandle, ServiceStatus)) then
begin
while (SERVICE_STOPPED <> ServiceStatus.dwCurrentState) do
begin
dwCheckPoint := ServiceStatus.dwCheckPoint;
Sleep(ServiceStatus.dwWaitHint);
if (not QueryServiceStatus(ServiceHandle, ServiceStatus)) then
break;
if (ServiceStatus.dwCheckPoint < dwCheckPoint) then
break;
end;
end;
end;
CloseServiceHandle(ServiceHandle);
end;
CloseServiceHandle(ServiceControlManager);
end;
Result := (SERVICE_STOPPED = ServiceStatus.dwCurrentState);
end;
procedure TForm2.Button1Click(Sender: TObject);
begin
If ServiceStop('','mysql') then Showmessage('Service Stopped')
else Showmessage('Nope');
end;
Administrator res can be created by 管理员资源可以通过以下方式创建
1 24 "administrator.manifest"
1 24“ administrator.manifest”
brcc32 administrator.rc
brcc32 administrator.rc
using the created administrator.res will require: 使用创建的administrator.res将需要:
Source and anything needed for the manifest can be downloaded here 清单所需的资源和任何内容都可以在这里下载
What I ended up doing is this: 我最终要做的是:
uses WinApi, ShellApi;
function StartStopDatabase(start: boolean): integer;
var
Info: TShellExecuteInfo;
verb: string;
ExitCode: DWORD;
begin
Result := -1;
if start
then verb := 'start'
else verb := 'stop';
FillChar(Info, SizeOf(Info), 0);
Info.cbSize := SizeOf(TShellExecuteInfo);
Info.fMask := SEE_MASK_NOCLOSEPROCESS;
Info.Wnd := Application.Handle;
Info.lpVerb := 'RunAs';
Info.lpFile := 'net';
Info.lpParameters := PWideChar(verb + ' mysql');
Info.nShow := SW_SHOW;
if ShellExecuteEx(@Info) then begin
repeat
Sleep(100);
Application.ProcessMessages;
GetExitCodeProcess(Info.hProcess, ExitCode);
until (ExitCode <> STILL_ACTIVE) or Application.Terminated;
Result := ExitCode;
end;
end;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.