【问题标题】:Delphi - TDosCommand issueDelphi - TDosCommand 问题
【发布时间】:2021-05-18 11:53:16
【问题描述】:

我需要从 Delphi 调用批处理脚本。 我使用 TDosCommand 是因为我想在外部进程完成之前显示来自批处理的回显消息。 如何在程序中等待脚本完成?

这是一个简单的演示示例。我在点击时调用 Test.bat。暂停仅用于测试目的。

Test.bat.

@echo off

echo Script start
echo First line 
ping 192.0.2.1 -n 1 -w 1000 >nul 
echo Second line  
ping 192.0.2.1 -n 1 -w 2000 >nul 
echo Third line
ping 192.0.2.1 -n 1 -w 3000 >nul 
echo Fourth line
ping 192.0.2.1 -n 1 -w 4000 >nul
echo Script end 

Pas 文件。过程 ExecuteBatch 调用批处理脚本。 添加了带有 Application.ProcessMessages 的等待循环。有没有比 Application.ProcessMessages 更好的解决方案?

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls, DosCommand;

type
  TForm1 = class(TForm)
    RichEdit1: TRichEdit;
    btnExecuteBatch: TButton;
    procedure ExecuteBatch;
    procedure btnExecuteBatchClick(Sender: TObject);
    procedure DosCommand1NewLine(ASender: TObject; const ANewLine: string; AOutputType: TOutputType);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ExecuteBatch;
var
  i: integer;
  DosCommand1: TDosCommand;
begin
  DosCommand1 := TDosCommand.Create(Self);
  DosCommand1.OnNewLine := DosCommand1NewLine;
  DosCommand1.CommandLine := '..\..\Test.bat';
  DosCommand1.Execute;

  repeat
    sleep(100);
    Application.ProcessMessages;
  until (DosCommand1.EndStatus <> esStill_Active);

  //here I need to wait until Test.bat script finishes
  // (repeat-until?)

  RichEdit1.Lines.Add('End of ExecuteBatch procedure.');

end;

procedure TForm1.DosCommand1NewLine(ASender: TObject; const ANewLine: string; AOutputType: TOutputType);
begin
  if AOutputType = otEntireLine then
  begin
    RichEdit1.Lines.Add(ANewLine);
  end;
end;

procedure TForm1.btnExecuteBatchClick(Sender: TObject);
begin
  RichEdit1.Clear;
  ExecuteBatch;
end;

end.

测试表格的Dfm文件。我正在使用 RichEdit,因为我需要更改某些线条的颜色。

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 645
  ClientWidth = 924
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object RichEdit1: TRichEdit
    Left = 8
    Top = 8
    Width = 633
    Height = 629
    Font.Charset = EASTEUROPE_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'Tahoma'
    Font.Style = []
    Lines.Strings = (
      'RichEdit1')
    ParentFont = False
    TabOrder = 0
    Zoom = 100
  end
  object btnExecuteBatch: TButton
    Left = 696
    Top = 16
    Width = 113
    Height = 41
    Caption = 'Execute Batch'
    TabOrder = 1
    OnClick = btnExecuteBatchClick
  end
end

【问题讨论】:

  • 为什么不使用 ICS 或 Indy 或其他用于 TCP/IP 的 Delphi 库?他们有一个 ping 组件?如果不是 TCP/IP 库,为什么要使用 DosCommand 而不是 ShellExecute 或 CreateProcess 来运行传递批处理文件的命令解释器?
  • 对不起,忽略批处理脚本中的内容。它与 ping 无关。在实际脚本中是 gcc 编译器的调用。我使用这个控件是因为它可以将外部进程消息写入 RichEdit (DosCommand1NewLine) 并且因为 Stop 和 SendLine 方法。
  • 你最好在你的问题中使用真实的东西。无论如何,您可以使用 ShellExecute 或 CreateProcess 运行任何东西,包括 gcc。无论如何,这就是 TDosCommand 所做的。 TDosCommand 使用线程让进程在后台运行,正是你不想要的...
  • 查看 TDosCommand 源代码,您有 3 种方法可以知道启动的进程是否正在运行:使用属性 ExitCode 或属性 EndStatus 或事件 OnTerminated。

标签: batch-file delphi


【解决方案1】:

查看TDosCommand source code,您有3种方法可以知道启动的进程是否正在运行:使用属性ExitCode,或属性EndStatus,或事件OnTerminated

使用OnTerminated 事件可以避免构建等待循环,这通常不是一个好主意。

【讨论】:

  • 添加了等待循环。还有比 Application.ProcessMessages 更好的解决方案吗?
  • 我想在外部进程终止之前显示来自批处理文件的回显消息。所以这不是一个选择。那么有没有办法使用DosCommand控件呢?
  • @Ivan 答案告诉你该怎么做——一定要使用OnTerminate 事件。根本不要使用繁忙的等待循环。将您的代码分成两个步骤。启动批处理文件运行,然后退出,让流程返回到主消息循环。稍后,将调用该事件,因此您可以根据需要继续编写代码。
【解决方案2】:

如果您想让您的代码尽可能接近原来的样子,您可以检查 IsRunning 属性。

while DosCommand1.IsRunning do
begin
    sleep(100);
    Application.ProcessMessages;
end;

【讨论】:

    猜你喜欢
    • 2011-06-12
    • 2013-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多