【问题标题】:How in Delphi can I run a command with administrator privileges?如何在 Delphi 中以管理员权限运行命令?
【发布时间】:2013-03-07 17:21:58
【问题描述】:

我试图在 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;

有人知道怎么做吗?

TIA 马克帕特森

【问题讨论】:

    标签: delphi windows-7 command administrator


    【解决方案1】:

    从 Vista 开始,您需要提升访问权限才能启动/停止服务。
    一种简单的方法是将 RunAs 与 Shellexecute(Ex) 一起使用。

    ShellExecute(handle,'RunAs','net','stop mysql',nil,sw_Show);
    

    更好的方法是使用清单,如下所示:

    <?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>
    

    一个最小的解决方案,不需要“网络”,可能看起来像这样,应该做更多的事情,例如。测试服务是否正在运行,但这取决于你,可以通过 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;
    

    管理员资源可以由

    创建
    • 将上述显示 XML-Code 保存为 administrator.manifest
    • 以文件administrator.rc的形式创建内容

    1 24 "administrator.manifest"

    • 正在运行

    brcc32 管理员.rc

    使用创建的 administrator.res 将需要:

    1. 在较新的 delphi 版本上禁用运行时主题,它们包含在清单中
    2. 从现有项目中删除 XPMan(组件和代码,包含在清单中)
    3. 如果您需要调试应用程序,delphi 也必须以管理员身份启动。

    Source and anything needed for the manifest can be downloaded here

    【讨论】:

    • 另外你应该考虑使用 API 调用而不是启动一个进程来完成这项工作,这里解释了如何做,并且可以翻译成 Delphi:support.microsoft.com/?kbid=245230
    • 我不知道清单,但接近的 RunAs 有效。谢谢。
    • 好的,我还没搞定。它还需要两件事:它需要等到命令完成,它需要捕获用户的响应。
    • Bummi,您确定ServiceStop 功能有效吗?我在运行 MySQL 的机器上测试它。它总是返回假。当我单步执行它时,OpenService 返回 0,我认为这不是我们想要的。
    • 对我来说很好,编译时的任何消息都像重复资源?你得到以管理员身份运行的对话框了吗?
    【解决方案2】:

    我最终做的是:

    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;
    

    【讨论】:

      猜你喜欢
      • 2019-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-29
      • 1970-01-01
      • 2018-11-03
      • 2016-10-08
      相关资源
      最近更新 更多