执行命令行, 并获取输出字符(比如OSQL)

直接贴代码了, 没什么好说的, 很简单, 也不需要注释

function DoCMD(ACommand: AnsiString; var ACmdResult: string): Boolean;
var
  nStrs: TStringBuilder; {旧版本可以用TStringlist替代}
  nHReadPipe, nHWritePipe: THandle;
  nSI: STARTUPINFOA;
  nLSA: SECURITY_ATTRIBUTES;
  nPI: PROCESS_INFORMATION;
  nBufferSize, nRBufferSize, nEC: DWORD;
  nPH: array[0..4096] of AnsiChar;
begin
  Result := False;

  with nLSA do
  begin
    nLength := SizeOf(SECURITY_ATTRIBUTES);
    lpSecurityDescriptor := nil;
    bInheritHandle := True;
  end;

  if not CreatePipe(nHReadPipe, nHWritePipe, @nLSA, 0) then
    raise Exception.Create('管道创建失败 ' + SysErrorMessage(GetLastError));

  try
    GetStartupInfoA(nSI);
    with nSI do
    begin
      dwFlags := (STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW);
      wShowWindow := SW_HIDE;
      hStdOutput := nHWritePipe;
    end;

    nStrs := TStringBuilder.Create;
    try
      if not CreateProcessA(nil, PAnsiChar(ACommand), nil, nil,
        True, 0, nil, nil, nSI, nPI) then
        raise Exception.Create('进程创建失败 ' + SysErrorMessage(GetLastError));
      try
        nRBufferSize := 0;
        repeat
          GetExitCodeProcess(nPI.hProcess, nEC);
          PeekNamedPipe(nHReadPipe, @nPH, Length(nPH) - 1, @nBufferSize, nil, nil);
          if nBufferSize <> 0 then
          begin
            ReadFile(nHReadPipe, nPH, nBufferSize, nRBufferSize, nil);
            nPH[nRBufferSize] := #0;
            nRBufferSize := 0;
            nStrs.Append(nPH);
          end;
        until nEC <> STILL_ACTIVE;
        nPH[nRBufferSize] := #0;
        nStrs.Append(nPH);
        ACmdResult := nStrs.ToString;
        Result := True;
      finally
        CloseHandle(nPI.hThread);
        CloseHandle(nPI.hProcess);
      end;
    finally
      nStrs.Free;
    end;
  finally
    CloseHandle(nHReadPipe);
    CloseHandle(nHWritePipe);
  end;
end;

 

posted on 2016-10-13 19:04  堕落恶魔  阅读(...)  评论(... 编辑 收藏

统计