【问题标题】:How to automate perl script in Delphi?如何在 Delphi 中自动化 perl 脚本?
【发布时间】:2009-12-08 20:26:49
【问题描述】:

目前,我正在使用 delphi 应用程序。我需要从 delphi 应用程序运行 perl 脚本。更清楚地说,我们在 unix 窗口中手动执行 perl 脚本。现在我需要从应用程序自动执行该 perl 脚本。

我尝试使用 ShellExecute:

ShellExecute(Handle, 'open', PChar('C:\loaderperl.bat'), nil, nil, SW_SHOW);

窗口闪烁一秒钟然后关闭。不知道脚本有没有执行。

您好,感谢您的所有回答,对于我迟到的回复感到抱歉。我仍然在与这种自动化作斗争。现在我将过程解释清楚,目前我打开putty窗口,连接到远程机器并执行perl脚本。 perl 脚本依次调用存储过程并更新表。现在我想通过单击按钮自动执行上述过程。所以当我点击一个按钮时,它应该调用一个连接到远程机器的函数,然后执行 perl 脚本。我对你清楚吗???请帮助解决这个问题。我在delphi中需要这段代码

【问题讨论】:

  • 是原生的delphi还是.NET?你说的unix窗口是什么意思?
  • 请说明您是要在本地执行还是在远程系统上执行,如果在本地执行,您要在哪个环境(CygWin、MSys)或哪个 shell(sh、bash、rxvt、...)使用。
  • 我不认为这是重复的,mghie - JVNR 似乎也想检查它是否也运行了,我认为其他 SO 问题并没有真正解决 - 而且它肯定不在接受的答案。另外,JVNR,我认为您可以将问题标题编辑得更清楚一点,或者帮助其他人找到问题——也许提到“运行”Perl 脚本,而不是“自动化”,以及检查它是否运行?
  • @David:我同意完整解决方案还有很多方面,当然值得讨论。然而,除非问题清楚地表明需要什么和不需要什么,否则我们无能为力。目前的问题是重复的 IMO。

标签: perl delphi


【解决方案1】:

(根据下面的 cmets 进行编辑。)

有几个步骤:首先,实际运行脚本;其次,检查它是否成功运行(它是否成功地启动了一个新进程以及该进程是否成功。)

第 1 部分,运行脚本:

要从您的 Delphi 应用程序运行脚本,使用 ShellExecuteEx 和“open”动词应该可以工作(下面的标志中有更多详细信息。)如果脚本与您的 Perl 可执行文件相关联,您可以执行脚本本身,或者运行将脚本作为命令行参数的 Perl exe。

This article 看起来是使用此 API 及其更简单的表亲 ShellExecute 的良好起点。

ShellExecute[Ex] 函数通常希望您的应用程序在之后运行消息循环。您的应用程序不太可能不是,只要在用户单击按钮启动此应用程序后,您的应用程序就会处于空闲状态,但如果由于某种原因它不会,您应该传递 SEE_MASK_NOASYNC 标志。 MSDN 有很多信息。

第 2 部分,检查它是否成功执行并成功完成任务:

要查看脚本是否执行,您应该获取已启动进程的进程句柄,如果有新进程,请检查其中的退出代码。如果任务失败,您应该修改脚本以返回非零代码。 (我对 Perl 不熟悉,所以我无法具体告诉您如何操作,但通常它是“main”函数或其他 first/startup 函数的返回值。)您可以通过以下方式执行此操作:

  • SEE_MASK_NOCLOSEPROCESS 标志传递给ShellExecuteEx。如果它成功启动了一个进程(如果没有,请检查GetLastError 找出原因。)如果这就是你需要知道的全部(如果它开始了,不管它是否有效)然后你就完成了。
  • 可选:使用WaitForSingleObject(YourParamStruct.hProcess, INFINITE) 等待进程结束(当然,如果你有一个有效的 hProcess)
  • 致电GetExitCodeProcess 查找退出代码。 (检查它是否返回STILL_ACTIVE,如果它仍在运行,请等待并重试。)通常,它应该以0 退出以表示成功。您应该修改您的脚本,以便如果出现问题,它会返回非零值。您可以根据需要使代码变得简单或复杂——例如,针对任何错误返回1,或者根据错误类型制作多个代码。 (避免使用259,因为这是STILL_ACTIVE 的值 - 这样做可能会导致您的 Delphi 代码进入无限循环,这取决于它的编码方式,认为它仍在等待获取退出代码,因为 Perl 脚本仍在运行时不是。)

然后,您的 Delphi 应用程序可以检查此代码以查看 Perl 脚本是否有效,并在失败时执行某些操作 - 记录消息、告诉用户等。

另一件事 - 你说你只是想知道脚本是否执行,上面应该提供。鉴于它是一个 Perl 脚本并在命令行上运行,您可能想要做的另一件事是获取它的输出,如果您不返回错误代码,则扫描错误,或者记录或显示用户。您可以通过CreateProcesscapturing the output 运行它来做到这一点。不过,从你所说的来看,这可能对你所追求的有点过分了!

【讨论】:

  • 我总是会执行一个 shell 并将脚本名称作为参数传递给它,以允许通配符、输入/输出重定向等。 shebang 行将确保 perl 解释器已启动。
  • 自动化意味着人为干扰应该为零。单击按钮时,代码应自动执行 perl 脚本。我尝试使用 ShellExecute: ShellExecute(Handle,'open',Pchar('C:\loaderperl.bat'),nil,nil,SW_SHOW) ;窗口闪烁一秒钟然后关闭。我不知道脚本是否执行。你能在这给我澄清一下吗?
  • 感谢您的澄清,JVNR。我刚刚编辑了这个答案,希望能回答你如何知道它是否执行(以及脚本是否有效 - 脚本很有可能运行,但其中出现了问题,你可能也想知道.)
  • 您好,感谢您的所有回答,很抱歉我的回复晚了。我仍然在与这种自动化作斗争。现在我将过程解释清楚,目前我打开putty窗口,连接到远程机器并执行perl脚本。 perl 脚本依次调用存储过程并更新表。现在我想通过单击按钮自动执行上述过程。所以当我点击一个按钮时,它应该调用一个连接到远程机器的函数,然后执行 perl 脚本。我对你清楚吗???请帮助解决这个问题。我在delphi中需要这段代码。
  • 这是对您迟到的回复的迟到回复,JVNR - 也很抱歉。我在国外呆了几个月。我认为您实际上提出的问题与您在这里提出的问题完全不同,因此答案将完全不同。最好提出一个新的 SO 问题,或许可以参考这个问题和您的评论来澄清。
【解决方案2】:

使用 shellexecute 使用相关参数(perl 解释器 + 脚本位置 + 名称)启动 rsh 或任何你的 unix 窗口?

【讨论】:

    【解决方案3】:

    如果您想ShellExecute() 一个批处理文件,您需要执行cmd.exe 并将脚本作为参数传递,如下所示:

    ShellExecute(Handle, 'open', 'cmd.exe', '/C C:\loaderperl.bat', nil, SW_SHOW);
    

    您可以使用输出重定向来捕获文件中的脚本输出。如果您想查看脚本是否成功执行,您可以(出于测试目的)在其末尾添加pause

    【讨论】:

      【解决方案4】:

      您需要调用外部程序(perl 解释器在本地机器上执行,像这样的 ssh 或 smth 在远程机器上执行)。这是调用外部程序并等待它结束的过程(如果您不需要等到它结束,请删除 WaitForSingleObject 或按照其他人的建议调用 ShellExecute)。

      更新:要查看脚本输出,请尝试使用来自this article的解决方案

      function ExecAndWait(const FileName, Params: ShortString; const WinState: Word): boolean; export; 
      var 
        StartInfo: TStartupInfo; 
        ProcInfo: TProcessInformation; 
        CmdLine: ShortString; 
      begin 
        { Put the name of file between quotes, due to spaces in names of files in system Win9x } 
        CmdLine := '"' + Filename + '" ' + Params; 
        FillChar(StartInfo, SizeOf(StartInfo), #0); 
        with StartInfo do 
        begin 
          cb := SizeOf(SUInfo); 
          dwFlags := STARTF_USESHOWWINDOW; 
          wShowWindow := WinState; 
        end; 
        Result := CreateProcess(nil, PChar( String( CmdLine ) ), nil, nil, false, 
                                CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, 
                                PChar(ExtractFilePath(Filename)),StartInfo,ProcInfo);
        { Wait the finish of program } 
        if Result then 
        begin 
          WaitForSingleObject(ProcInfo.hProcess, INFINITE); 
          { Free the Handles } 
          CloseHandle(ProcInfo.hProcess); 
          CloseHandle(ProcInfo.hThread); 
        end; 
      end; 
      

      【讨论】:

        猜你喜欢
        • 2015-02-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-17
        • 1970-01-01
        • 2010-09-26
        相关资源
        最近更新 更多