第一次发这个,发现格式很乱,不好看,可以用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的更多相关文章

  1. Delphi xe7 up1 调用android振动功能

    Delphi xe7 up1 调用android振动功能 振动用到以下4个单元: Androidapi.JNI.App,Androidapi.JNIBridge,Androidapi.JNI.Os,A ...

  2. Delphi中线程类TThread实现多线程编程2---事件、临界区、Synchronize、WaitFor……

    接着上文介绍TThread. 现在开始说明 Synchronize和WaitFor 但是在介绍这两个函数之前,需要先介绍另外两个线程同步技术:事件和临界区 事件(Event) 事件(Event)与De ...

  3. Delphi XE7调用C++动态库出现乱码问题回顾

    事情源于有个客户需使用我们C++的中间件动态库来跟设备连接通讯,但是传入以及传出的字符串指针格式都不正确(出现乱码或是被截断),估计是字符编码的问题导致.以下是解决问题的过程: 我们C++中间件动态库 ...

  4. Delphi XE7的安卓程序如何调用JAVA的JAR,使用JAVA的类?

    本文使用工具和全部源码下载: http://download.csdn.net/detail/sunylat/8190765 为什么我们要在Delphi XE7的安卓程序调用JAVA的JAR,使用JA ...

  5. Delphi XE7调用Java Class,JAR

    Delphi XE5,XE6需要用户手工编译并将Classes.Dex加入到包中,不过Delphi XE7可以省掉这些工作了. 如何在XE7中调用Java,具体步骤如下: 1.将jar文件添加到XE7 ...

  6. delphi2010\delphi XE7 开发及调试WebService 实例

    使用delphi已经10多年了,一直搞桌面程序开发,对Webservice一直很陌生,近来因工作需要,学习delphi开发WebService,担心遗忘,作此笔记. 特别感谢 中塑在线技术总监 大犇  ...

  7. delphi XE7 中的消息

    在delphi XE7的程序开发中,消息机制保证进程间的通信. 在程序中,消息来自: 1)系统: 通知你的程序用户输入,涂画以及其他的系统范围的事件: 2)你的程序:不同的程序部分之间的通信信息.   ...

  8. Delphi XE7中新并行库

    Delphi XE7中添加了新的并行库,和.NET的Task和Parellel相似度99%. 详细内容能够看以下的文章: http://www.delphifeeds.com/go/s/119574 ...

  9. DELPHI XE7 新的并行库

    DELPHI XE7 的新功能列表里面增加了并行库System.Threading, System.SyncObjs. 为什么要增加新的并行库? 还是为了跨平台.以前要并行编程只能从TThread类继 ...

随机推荐

  1. 求一个极大数的欧拉函数 phi(i)

    思路: 因为当n>=1e10的时候,线性筛就不好使啦.所以要用一个公式 φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn) 证明详见:<公式 ...

  2. Android使用AchartEngine绘制曲线图

    1.在布局文件中加入LinearLayout布局,如下: <LinearLayout android:id="@+id/chart" android:orientation= ...

  3. AJPFX关于JDK,JRE,JVM的区别与联系

    很多朋友可能跟我一样,对JDK,JRE,JVM这三者的联系与区别,一直都是模模糊糊的. 今天我们来整理下三者的关系. JDK : Java Development ToolKit(Java开发工具包) ...

  4. Spring Bean的一生

    Spring Bean的一生 When you work directly in Java, you can do anything you like with your objects and do ...

  5. Java面向对象(类、封装)

    面向对象 今日内容介绍 u 面向对象 u 封装 第1章 面向对象 1.1 理解什么是面向过程.面向对象 面向过程与面向对象都是我们编程中,编写程序的一种思维方式. l 面向过程的程序设计方式,是遇到一 ...

  6. 解决Chrome浏览器自动记录用户名和密码的黄色背景问题和该解决方法与tab切换至下一个input冲突的问题。

    哈哈哈,是不是标题很长呀,不逗你们了.其实这么长的标题主要就说了两件事: 第一件:解决Chrome浏览器自动记录用户名和密码的黄色背景问题. 第二件:输入完用户名后按下tab键切换至下一个输入密码in ...

  7. 织梦dedecms后台登陆密码充值工具

    下载后解压,根据自己语言版本,把文件radminpass.php放入网站根目录下执行即可 点击下载:织梦dedecms后台登陆密码充值工具

  8. Google Chrome 浏览器的备用(离线)安装程序

    Google Chrome 浏览器的备用(离线)安装程序(适用于 Windows) 如果您在使用 http://www.google.com/chrome 上的标准安装程序下载 Chrome 浏览器时 ...

  9. 使用Timer组件实现倒计时

    实现效果: 知识运用:  Timer组件的Enabed属性 实现代码: private void timer1_Tick(object sender, EventArgs e) { DateTime ...

  10. 用 label 控制 Pod 的位置

    默认配置下,Scheduler 会将 Pod 调度到所有可用的 Node.不过有些情况我们希望将 Pod 部署到指定的 Node,比如将有大量磁盘 I/O 的 Pod 部署到配置了 SSD 的 Nod ...