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类继 ...
随机推荐
- 求一个极大数的欧拉函数 phi(i)
思路: 因为当n>=1e10的时候,线性筛就不好使啦.所以要用一个公式 φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn) 证明详见:<公式 ...
- Android使用AchartEngine绘制曲线图
1.在布局文件中加入LinearLayout布局,如下: <LinearLayout android:id="@+id/chart" android:orientation= ...
- AJPFX关于JDK,JRE,JVM的区别与联系
很多朋友可能跟我一样,对JDK,JRE,JVM这三者的联系与区别,一直都是模模糊糊的. 今天我们来整理下三者的关系. JDK : Java Development ToolKit(Java开发工具包) ...
- Spring Bean的一生
Spring Bean的一生 When you work directly in Java, you can do anything you like with your objects and do ...
- Java面向对象(类、封装)
面向对象 今日内容介绍 u 面向对象 u 封装 第1章 面向对象 1.1 理解什么是面向过程.面向对象 面向过程与面向对象都是我们编程中,编写程序的一种思维方式. l 面向过程的程序设计方式,是遇到一 ...
- 解决Chrome浏览器自动记录用户名和密码的黄色背景问题和该解决方法与tab切换至下一个input冲突的问题。
哈哈哈,是不是标题很长呀,不逗你们了.其实这么长的标题主要就说了两件事: 第一件:解决Chrome浏览器自动记录用户名和密码的黄色背景问题. 第二件:输入完用户名后按下tab键切换至下一个输入密码in ...
- 织梦dedecms后台登陆密码充值工具
下载后解压,根据自己语言版本,把文件radminpass.php放入网站根目录下执行即可 点击下载:织梦dedecms后台登陆密码充值工具
- Google Chrome 浏览器的备用(离线)安装程序
Google Chrome 浏览器的备用(离线)安装程序(适用于 Windows) 如果您在使用 http://www.google.com/chrome 上的标准安装程序下载 Chrome 浏览器时 ...
- 使用Timer组件实现倒计时
实现效果: 知识运用: Timer组件的Enabed属性 实现代码: private void timer1_Tick(object sender, EventArgs e) { DateTime ...
- 用 label 控制 Pod 的位置
默认配置下,Scheduler 会将 Pod 调度到所有可用的 Node.不过有些情况我们希望将 Pod 部署到指定的 Node,比如将有大量磁盘 I/O 的 Pod 部署到配置了 SSD 的 Nod ...