简体   繁体   English

如何在Delphi中运行具有管理员权限的命令?

[英]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 管理员资源可以通过以下方式创建

  • saving the above show XML-Code as administrator.manifest 将以上显示的XML代码保存为administrator.manifest
  • creating as file administrator.rc with the content 使用内容创建为文件administrator.rc

1 24 "administrator.manifest" 1 24“ administrator.manifest”

  • running 跑步

brcc32 administrator.rc brcc32 administrator.rc

using the created administrator.res will require: 使用创建的administrator.res将需要:

  1. disabling runtime themes on newer delphi versions, the are contained in the manifest 在较新的delphi版本上禁用运行时主题,它们包含在清单中
  2. removing XPMan from an existing project (component and code, contained in the manifest) 从现有项目中删除XPMan(清单中包含的组件和代码)
  3. If you need to debug the application, delphi has to be started as Administraor too. 如果您需要调试应用程序,则delphi也必须以Administraor身份启动。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM