Delphi 调用外部程序并阻塞到外部程序中

背景说明:

前段时间开发一个数据转换的系统,业务逻辑中说明数据需要压缩成.tar.gz格式。

我在Windows系统下采用,先生成批处理文件,然后调用WinExec执行批处理文件,休眠等待一段时间,完成数据的自动压缩。

后来发现,待压缩文件的大小不确定,单纯的执行WinExec时Sleep固定时间,可能导致压缩失败、文件不全或损坏。

优化方案:

取代WinExe用CreateProcess用来启动进程, 执行批处理文件, 同时系统会自动填写TProcessInformation这个结构。

此时程序会自动阻塞到该批处理中,等待批处理句柄的进程结束或超时。这样就能解决压缩损坏问题。

给个实例Demo:

D7代码如下:

 unit uMain;

 interface

 uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, RzButton, StdCtrls; type
TFrmMain = class(TForm)
mmMsg: TMemo;
btnExecute: TRzBitBtn;
btnClear: TRzBitBtn;
procedure MsgDsp(v_Str: string);
procedure btnExecuteClick(Sender: TObject);
procedure btnClearClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end; var
FrmMain: TFrmMain; implementation {$R *.dfm} procedure TFrmMain.MsgDsp(v_Str: string);
begin
mmMsg.Lines.Add('[ admin ] - [' + v_Str + '] - [' + FormatDateTime('YYYY-MM-DD hh:mm:ss zzz', Now()) + ']');
end; procedure TFrmMain.btnExecuteClick(Sender: TObject);
var
sInfo: TStartupInfo;
pInfo: TProcessInformation;
cmdLine: string;
exitCode: Cardinal;
begin
MsgDsp('初始化参数');
cmdLine := 'C:\Program Files\7-Zip\7zFM.exe';
FillChar(sInfo, sizeof(sInfo), #);
sInfo.cb := SizeOf(sInfo);
sInfo.dwFlags := STARTF_USESHOWWINDOW;
sInfo.wShowWindow := SW_NORMAL;
MsgDsp('参数初始化完成,启动WinExec调试');
//CreateProcess用来启动进程, 进程启动后, 会填写TProcessInformation这个结构,
//此时程序阻塞到该句柄中,等待句柄的进程结束或超时
if not CreateProcess(nil, pchar(cmdLine), nil, nil, false, CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, sInfo, pInfo) then
begin
MsgDsp('WinExec调试失败!');
MessageBox(Application.handle, '指定程序启动失败!', '错误', MB_OK or MB_ICONSTOP);
end
else
begin
//等待指定句柄的进程结束或超时
WaitForSingleObject(pInfo.hProcess, INFINITE);
GetExitCodeProcess(pInfo.hProcess, exitCode);
MsgDsp('WinExec调试成功!');
end;
end; procedure TFrmMain.btnClearClick(Sender: TObject);
begin
mmMsg.Clear;
end; end.

运行效果如下:

封装成函数如下

 //Jeremy.Wu
//2019.09.19
//https://www.cnblogs.com/jeremywucnblog/
function TFrmMain.GetCreateProcess(vCmdLine: string): Boolean;
var
sInfo: TStartupInfo;
pInfo: TProcessInformation;
exitCode: Cardinal;
begin
Result := False;
FillChar(sInfo, sizeof(sInfo), #);
sInfo.cb := SizeOf(sInfo);
sInfo.dwFlags := STARTF_USESHOWWINDOW;
sInfo.wShowWindow := SW_NORMAL;
//CreateProcess用来启动进程, 进程启动后, 会填写TProcessInformation这个结构,
//此时程序阻塞到该句柄中,等待句柄的进程结束或超时
if not CreateProcess(nil, pchar(vCmdLine), nil, nil, false, CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, sInfo, pInfo) then
begin
Result := False;
end
else
begin
//等待指定句柄的进程结束或超时
WaitForSingleObject(pInfo.hProcess, INFINITE);
GetExitCodeProcess(pInfo.hProcess, exitCode);
Result := True;
end;
end;

作者:Jeremy.Wu
  出处:https://www.cnblogs.com/jeremywucnblog/

  本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

Delphi - 调用外部程序并阻塞到外部程序中的更多相关文章

  1. delphi调用外部程序打开文件

    delphi调用外部程序打开文件 ShellExecute的各种用法 一.利用系统默认的邮件收发器发送电子邮件 Uses ..., ShellAPI; Var lpHwnd: HWND; lpOper ...

  2. Delphi 调用外部程序并等待其运行结束

    转自:http://blog.csdn.net/xieyunc/article/details/4140620   如何让Delphi调用外部程序并等待其运行结束 1. uses     Window ...

  3. 发现个delphi调用vc写的Dll中包括pchar參数报错奇怪现象

    发现个delphi调用vc写的Dll中包括pchar參数奇怪现象 procedure中的第一行语句不能直接调用DLL的函数,否则会执行报错,在之前随意加上条语句就不报错了奇怪! vc的DLL源代码地址 ...

  4. Delphi调用DLL中的接口

    问题描述: 具体问题就是在隐式使用接口变量后,在FreeLibrary执行后,就会出现一个非法访址的错误. 这个错误的原因就是在FreeLibrary后,DLL以的代码均为不可用状态,而在代码执行完整 ...

  5. delphi调用web service出现 Unable to retrieve the URL endpoint for Service/Port .....

    delphi调用web service出现 Unable to retrieve the URL endpoint  for Service/Port, 错误截图如下 查了很长时间, 发现在DataM ...

  6. 【转】Delphi调用webservice总结

    原文:http://www.cnblogs.com/zhangzhifeng/archive/2013/08/15/3259084.html Delphi调用C#写的webservice 用delph ...

  7. Delphi 调用netsh命令修改IP地址

    Delphi 调用netsh命令修改IP地址 先介绍一下Netsh命令的使用方法: 在这里跟大家介绍几个简单的指令 1.Show IP 1.1Cmd Mode 直接在cmd下面输入 netsh int ...

  8. 教程-Delphi调用C# WEBSERVICE(二)

    第二步:将webserivce的WSDL导入到该dll工程中,如何导,方法至少有两种,我说简单的一种:  file->new->other->WebService->WSDL ...

  9. [转]Delphi调用cmd的两种方法

    delphi调用cmd的两种方法vars:string;begins:='cmd.exe /c '+edit1.Text+' >c:\1.txt';winexec(pchar(s),sw_hid ...

随机推荐

  1. 从原理层面掌握@ModelAttribute的使用(核心原理篇)【一起学Spring MVC】

    每篇一句 我们应该做一个:胸中有蓝图,脚底有计划的人 前言 Spring MVC提供的基于注释的编程模型,极大的简化了web应用的开发,我们都是受益者.比如我们在@RestController标注的C ...

  2. 五分钟学会悲观乐观锁-java vs mysql vs redis三种实现

    1 悲观锁乐观锁简介 乐观锁( Optimistic Locking ) 相对悲观锁而言,乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果 ...

  3. 深入浅出TCP与UDP协议

    深入浅出TCP与UDP协议 网络协议是每个前端工程师的必修课,TCP/IP协议族是一系列网络协议的总和,而其中两个具有代表性的传输层协议,分别是TCP与UDP,本文将介绍这两者以及他们之间的区别. 一 ...

  4. 使用注解的Hibernate one-to-many映射

    One to many映射关系指的是两个实体间一个实体可以和多个实体有关联关系,但是多的这一端只能和一的这一端的一个实例有关系.它是一个1 到 n的关系.例如在任何的公司员工可以注册多个银行账户,一个 ...

  5. 基于随机游走的三维网格分割算法(Random Walks)

    首先以一维随机游走(1D Random Walks)为例来介绍下随机游走(Random Walks)算法,如下图所示,从某点出发,随机向左右移动,向左和向右的概率相同,都为1/2,并且到达0点或N点则 ...

  6. python 13 内置函数2

    目录 内置函数(二) 匿名函数 内置函数(三) 闭包 内置函数(二) abs() #返回绝对值--返回的是正数 enumerate("可迭代对象","序号起始值" ...

  7. go语言实现分布式对象存储系统之单体对象存储

    对象存储 基本概念 主流存储类型分为三种:块存储.文件存储以及对象存储 NAS(文件存储):Network Attached storage,提供了存储功能和文件系统的网络服务器,客户端可以访问NAS ...

  8. MySQL的count(*)的优化,获取千万级数据表的总行数[转]

    一.前言 这个问题是今天朋友提出来的,关于查询一个1200w的数据表的总行数,用count(*)的速度一直提不上去.找了很多优化方案,最后另辟蹊径,选择了用explain来获取总行数. 二.关于cou ...

  9. codeforces 842 D. Vitya and Strange Lesson(01字典树+思维+贪心)

    题目链接:http://codeforces.com/contest/842/problem/D 题解:像这种求一段异或什么的都可以考虑用字典树而且mex显然可以利用贪心+01字典树,和线段树差不多就 ...

  10. codeforces 828 D. High Load(思维,水题)

    题目链接:http://codeforces.com/contest/828/problem/D 题解:任意去一个点为根然后有几个k就是几个子叶也就是根结点有几个分支然后最好的解法就是贪心,将剩下的点 ...