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. 洛谷 P3870 [TJOI2009]开关

    题意简述 有n盏灯,默认为关,有两个操作: 1.改变l~r的灯的状态(把开着的灯关上,关着的灯打开) 2.查询l~r开着的灯的数量 题解思路 维护一个线段树,支持区间修改,区间查询 懒标记每次^1 代 ...

  2. 强烈推荐优秀的Vue UI组件库

    Vue 是一个轻巧.高性能.可组件化的MVVM库,API简洁明了,上手快.从Vue推出以来,得到众多Web开发者的认可.在公司的Web前端项目开发中,多个项目采用基于Vue的UI组件框架开发,并投入正 ...

  3. CentOS 安装 JDK 三种形式详细总结

    一.下载 JDK   点击下载:jdk-8u211-linux-x64.tar.gz   根据需要选择对应版本和位数,并将文件放入CentOS中的相关目录中,以 /java/jdk 目录为例,执行 m ...

  4. Java 8 为什么会引入lambda 表达式?

    Java 8 为什么会引入lambda ? 在Java8出现之前,如果你想传递一段代码到另一个方法里是很不方便的.你几乎不可能将代码块到处传递,因为Java是一个面向对象的语言,因此你要构建一个属于某 ...

  5. 阿里云部署 Flask + WSGI + Nginx 转载详解

    我采用的部署方案是: Web 服务器采用 uwsgi host Flask 用 Supervisor 引用 uwsgi 作常规启动服务 基于 Nginx 作反向代理 首先, 阿里云服务器可以通过 SS ...

  6. html利用j获取局域网内的本机IP(根据客户端浏览器的ip获取)

    根据客户端浏览器的ip获取 <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type ...

  7. day0203

    day02 1.for i in range() --->用于设置for循环的迭代设置. ranage 也是一个前闭后开的. 2.random.randrange() --->随机产生给予 ...

  8. FaceNet人脸识别研究

    https://github.com/WindZu/facenet_facerecognition (代码) https://segmentfault.com/a/1190000015917420?u ...

  9. tensorflow如何继续训练之前保存的模型

    https://blog.csdn.net/qq_23981335/article/details/81480220

  10. 实战docker,编写Dockerfile定制tomcat镜像,实现web应用在线部署

    最初在tomcat上部署web应用的方式,是通过maven的maven-compiler-plugin插件先打成war包,再将war包复制到tomcat的webapps目录下,后来用上了tomcat7 ...