delphi xe7 多线程调用CMD,使用管道,临界区技术,实现指定用户名,多线程,异步返回CMD命令结果到memo
第一次发这个,发现格式很乱,不好看,可以用XE7的project--format project sources命令格式化一下代码.
后面我会上传此次修改函数用的源代码到云盘
链接: http://pan.baidu.com/s/1jIjk7fK 密码: nf3p
基于网络上一个函数,我修改后发现如果运行命令ipconfig /all.将不能等待到返回.后面的函数已经该好了.
废话少说,先看第一个函数,注意此函数buffer为PansiChar.我想异步返回结果,结果造成不小麻烦,所有我选择一次性提交结果
function WaitRunDOs(ReadPepi: THandle;ProcessInfo: TProcessInformation;Memo: TMemo) :TProc;
begin
  Result:= procedure
  var
    BytesRead: DWord;
    Buffer: PAnsiChar;
    fSize: DWORD;
  begin
    // showmessage('等待开始');
    if (WaitForSingleObject(ProcessInfo.hProcess, INFINITE)= WAIT_OBJECT_0) then
    begin
      // 申请缓冲
      Fsize := GetFileSize(ReadPepi,nil);
      Buffer := AllocMem(Fsize + 1);
      BytesRead := 0;
     // ReadFile(ReadPepi, Buffer[0], CUANTOBUFFER, BytesRead, nil);
      ReadFile(ReadPepi, Buffer[0], fSize + 1, BytesRead, nil);
      Buffer[BytesRead] := #0;
      OemToAnsi(Buffer, Buffer);
      Memo.Lines.Add(String(AnsiToUtf8(Buffer)));
             {按照换行符进行分割,并在Memo中显示出来}
     { while (pos(#10, Buffer) > 0)do
        begin
          sss:= Copy(Buffer, 1, pos(#10, Buffer) - 1);
          Memo.Lines.Add(Copy(Buffer, 1, pos(#10, Buffer) - 1));
          Delete(Buffer, 1, pos(#10, Buffer));
        end;   }
FreeMem(Buffer);
      CloseHandle(ProcessInfo.hProcess);
      CloseHandle(ProcessInfo.hThread);
      CloseHandle(ReadPepi);
    end;
  end;
end;
procedure RunDosInMemo(command: String; Memo: TMemo);
var
  pepiAttr: TSecurityAttributes;
  startInfo: TStartupInfoW;
  ProcessInfo: TProcessInformation;
  ApplicationName: PWideChar;
  ReadPipe,WritePipe: THandle;
begin
  // 安全描述 可以省略
  with pepiAttr do
  begin
    nlength := SizeOf(TSecurityAttributes);
    binherithandle := true;
    lpsecuritydescriptor := nil;
  end;
{ 创建管道}
  if Createpipe(ReadPipe, WritePipe, @pepiAttr, 0) then
  begin
    // 创建STARTUPINFO
    FillChar(startInfo, SizeOf(startInfo), #0);
    startInfo.cb := SizeOf(startInfo);
    startInfo.hStdOutput := WritePipe;
   // startInfo.hStdInput := ReadPipe;
    startInfo.dwFlags := STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES or 16;
    startInfo.wShowWindow := SW_HIDE;
    ApplicationName :=pwidechar('C:\Windows\System32\cmd.exe');
    if not (CreateProcessWithLogon(
                 '用户名(如administrator)','域名','密码', LOGON_WITH_PROFILE,
                  nil,PChar('cmd /c' + command),
                   // CREATE_NO_WINDOW,
                  CREATE_DEFAULT_ERROR_MODE,
                  nil,nil,
                  StartInfo, ProcessInfo))then
    begin
       RaiseLastOSError;
    end else
      begin
        CloseHandle(WritePipe);
        //预计完成运行
        cs.Enter;
        TThread.CreateAnonymousThread(WaitRunDOs(ReadPipe,ProcessInfo,Memo)).Start;
        cs.Leave;
    end;
  end;
end;
然后我决定有必要修改,查找资料后得到下面这个函数,总算实现了我的目的.如果想同时执行几个命令,可以将command赋值为'';然后将命令写在同目录下的command.bat中
当然也可以使用重定向输入.具体实现方式还没研究,不知道哪位兄弟可提供些代码来学习
/// <param name="command">
/// 命令行如果为空,则运行同一目录下command.bat文件,
/// 但需确保应用程序和bat文件不在特定用户的桌面等无读写权限的特殊目录
/// </param>
procedure GetDosToMemo(command:string;memo:TMemo);
var
  SA: TSecurityAttributes;
  SI: TStartupInfo;
  PI: TProcessInformation;
  PipeRead,PipeWrite: THandle;
  WasOK: Boolean;
  Buffer: array [0 .. 255] of AnsiChar;
  PCName: array [0..254] of char;
  PCNameSize:Dword;
  BytesRead: Cardinal;
  Commandline,AppName,CurrentDir,return:string;
begin
  //获取计算机名
  GetComputerName(PCName,PCNameSize);
  AppName :=pwidechar('C:\Windows\System32\cmd.exe');
        CommandLine:='/c' + Command;
        if length(command) <= 0 then
          CommandLine := '/c command.bat';
         Currentdir := GetCurrentDir;
TThread.CreateAnonymousThread(
  procedure
  begin
    with SA do
    begin
      nLength := SizeOf(SA);
      bInheritHandle := True;
      lpSecurityDescriptor := nil;
    end;
    if CreatePipe(PipeRead, PipeWrite, @SA, 0) then
    begin
      try
        with SI do
        begin
          FillChar(SI, SizeOf(SI), 0);
          cb := SizeOf(SI);
          dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
          wShowWindow := SW_HIDE;
          hStdInput := GetStdHandle(STD_INPUT_HANDLE); // 不重定向hStdInput
          hStdOutput := PipeWrite;
          hStdError := PipeWrite;
        end;
       { CreateProcess(nil, PChar('cmd /c ' + comand), nil, nil,
          True, 0, nil, nil, SI, PI); }
         //如果ApplicationName :=pwidechar('C:\Windows\System32\ping.exe');
      //则不使用cmd 参数 ,'/c'或'/k'等,
      //AppName为nil,则参数必须加上环境变量目录内的//应用程序名 如'cmd /c'
{if not (CreateProcessWithLogon(
                     '用户名','域名','密码', LOGON_WITH_PROFILE,
                      nil, PChar('cmd /c' + command),
                     // PChar('cmd /c' + command),
                       // CREATE_NO_WINDOW,
                      CREATE_DEFAULT_ERROR_MODE,
                      nil,nil,
                      SI, PI))then  }
        if not (CreateProcessWithLogon(
                     '用户名','域名','密码',
                     LOGON32_PROVIDER_DEFAULT or LOGON_WITH_PROFILE,
                     PChar(AppName),
                     PChar(CommandLine),
                     (CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE) + CREATE_UNICODE_ENVIRONMENT,
                     nil,
                     pchar(CurrentDir),
                      SI, PI))then
            RaiseLastOSError;
CloseHandle(PipeWrite);
        try
          return := '';
          cs.Enter;
          repeat
            WasOK:= ReadFile(PipeRead, Buffer, 255, BytesRead, nil);
            if BytesRead > 0 then
            begin
              Buffer[BytesRead] := #0;
              return := string(AnsiToUtf8(return + Buffer));
            end;
if EndsText(#13#10,return) then
            begin
              //ShowMessage(return + 'a');
              //去掉首先返回的#13#10和最后的#13#10,否则每行会插入一空行
              if Length(return) > 2 then
              begin
                if StartsText(#13#10,return) then
                Delete(return,1,2);
Delete(return,Length(return)-2,Length(return));
                //返回的数据有少量不同,不采用
                //memo.Lines.Add(ReplaceText(return,#13#10,''));
                memo.Lines.Add(return);
              end;
              return := '';
            end;
          until not WasOK or (BytesRead = 0);
          //避免提前关闭句柄
          WaitForSingleObject(PI.hProcess, INFINITE);
        finally
          CloseHandle(PI.hThread);
          CloseHandle(PI.hProcess);
        end;
        cs.Leave;
      finally
        CloseHandle(PipeRead);
      end;
    end;
  end).Start;
end;
delphi xe7 多线程调用CMD,使用管道,临界区技术,实现指定用户名,多线程,异步返回CMD命令结果到memo的更多相关文章
- Delphi xe7 up1 调用android振动功能
		Delphi xe7 up1 调用android振动功能 振动用到以下4个单元: Androidapi.JNI.App,Androidapi.JNIBridge,Androidapi.JNI.Os,A ... 
- Delphi中线程类TThread实现多线程编程2---事件、临界区、Synchronize、WaitFor……
		接着上文介绍TThread. 现在开始说明 Synchronize和WaitFor 但是在介绍这两个函数之前,需要先介绍另外两个线程同步技术:事件和临界区 事件(Event) 事件(Event)与De ... 
- Delphi XE7调用C++动态库出现乱码问题回顾
		事情源于有个客户需使用我们C++的中间件动态库来跟设备连接通讯,但是传入以及传出的字符串指针格式都不正确(出现乱码或是被截断),估计是字符编码的问题导致.以下是解决问题的过程: 我们C++中间件动态库 ... 
- Delphi XE7的安卓程序如何调用JAVA的JAR,使用JAVA的类?
		本文使用工具和全部源码下载: http://download.csdn.net/detail/sunylat/8190765 为什么我们要在Delphi XE7的安卓程序调用JAVA的JAR,使用JA ... 
- Delphi XE7调用Java Class,JAR
		Delphi XE5,XE6需要用户手工编译并将Classes.Dex加入到包中,不过Delphi XE7可以省掉这些工作了. 如何在XE7中调用Java,具体步骤如下: 1.将jar文件添加到XE7 ... 
- delphi2010\delphi  XE7 开发及调试WebService 实例
		使用delphi已经10多年了,一直搞桌面程序开发,对Webservice一直很陌生,近来因工作需要,学习delphi开发WebService,担心遗忘,作此笔记. 特别感谢 中塑在线技术总监 大犇 ... 
- delphi XE7 中的消息
		在delphi XE7的程序开发中,消息机制保证进程间的通信. 在程序中,消息来自: 1)系统: 通知你的程序用户输入,涂画以及其他的系统范围的事件: 2)你的程序:不同的程序部分之间的通信信息. ... 
- Delphi XE7中新并行库
		Delphi XE7中添加了新的并行库,和.NET的Task和Parellel相似度99%. 详细内容能够看以下的文章: http://www.delphifeeds.com/go/s/119574 ... 
- DELPHI XE7 新的并行库
		DELPHI XE7 的新功能列表里面增加了并行库System.Threading, System.SyncObjs. 为什么要增加新的并行库? 还是为了跨平台.以前要并行编程只能从TThread类继 ... 
随机推荐
- Promise 对象与Generator 函数
			异步编程的方法,大概有下面四种: 回调函数 事件监听 发布/订阅 Promise 对象 传统的编程语言,早有异步编程的解决方案(其实是多任务的解决方案).其中有一种叫做"协程"(c ... 
- My sql之存储过程+游标
			sql 实例如下: /**************定义更改car_station_user_acct_his new_balance old_balance存储过程**************/ cr ... 
- 2017.10.5 QBXT 模拟赛
			题目链接 T1 从小到大排序,用sum记录前缀和,然后枚举1~n个数 ,如果当前的前缀和 + 1小于a[i]的话 那么 sum + 1永远不可能拼出来 直接输出sum + 1 ,否则统计前缀和.最后如 ... 
- UWP开发:应用文件存储
			应用设置由于数据量和数据类型的限制,有很大的局限性,所以还需要应用文件存储,以文件的方式存储数据.在每个应用的应用数据存储中,该应用拥有系统定义的根目录:一个用于本地文件,一个用于漫游文件,还有一个用 ... 
- 利用jieba第三方库对文件进行关键字提取
			已经爬取到的斗破苍穹文本以TXT形式存储 代码 import jieba.analyse path = 'C:/Users/Administrator/Desktop/bishe/doupo.text ... 
- Ruby中访问控制符public,private,protected区别总结
			重点关注private与protected public 默认即为public,全局都可以访问,这个不解释 private C++, “private” 意为 “private to this cla ... 
- 2012-2013 ACM-ICPC, NEERC, Central Subregional Contest J Computer Network1 (缩点+最远点对)
			题意:在连通图中,求一条边使得加入这条边以后的消除的桥尽量多. 在同一个边双连通分量内加边肯定不会消除桥的, 求边双连通分量以后缩点,把桥当成边,实际上是要选一条最长的链. 缩点以后会形成一颗树,一定 ... 
- TDB文件介绍
			samba在运行时,Samba 存储许多信息,从本地密码到希望从中收到信息的一系列客户端.这类数据其中一些是暂时的,在 Samba 重启时可能会被丢弃,但是另一些却是永久的,不会被丢弃.这类数据可能是 ... 
- bower使用
			1,先安装nodejs(npm),Git 2,安装bower cmd执行到在项目文件夹下路径,执行npm install bower 3,执行bower init 项目根目录下将生成bower.js ... 
- python-下拉框
			首先,从selenium.webdriver.support.ui里调用Select类,如下: 其次,找到下拉框元素,再找下拉框里要最终选择的元素,如下: 注意:调用Select类后,不必再加clic ... 
