如何检测进程执行的应用程序是否由于无效输入而停止工作?

发布于 2024-10-20 06:57:24 字数 2369 浏览 5 评论 0原文

我想创建一个 LaTeX 编辑器来生成 pdf 文档。 在幕后,我的应用程序使用通过 Process 实例执行的 pdflatex.exe

pdflatex.exe 需要一个输入文件,例如 input.tex,如下所示

\documentclass{article}
\usepackage[utf8]{inputenc}
\begin{document}
\LaTeX\ is my tool.
\end{document}

为了简单起见,这里是使用的最小 c# 代码我的 LaTeX 编辑器:

using System;
using System.Diagnostics;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Process p = new Process();

            p.EnableRaisingEvents = true;
            p.Exited += new EventHandler(p_Exited);

            p.StartInfo.Arguments = "input.tex";
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.FileName = "pdflatex.exe";

            p.Start();
            p.WaitForExit();
        }

        static void p_Exited(object sender, EventArgs e)
        {
            // remove all auxiliary files, excluding *.pdf.
        }
    }
}

问题是

如何检测 pdflatex.exe 是否由于输入无效而停止工作?

编辑

这是最终的工作解决方案:

using System;
using System.Diagnostics;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Process p = new Process();

            p.EnableRaisingEvents = true;
            p.Exited += new EventHandler(p_Exited);

            p.StartInfo.Arguments = "-interaction=nonstopmode input.tex";// Edit
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.FileName = "pdflatex.exe";
            p.StartInfo.RedirectStandardError = true;
            p.Start();
            p.WaitForExit();

            //Edit
            if (p.ExitCode == 0)
            {
                Console.WriteLine("Succeeded...");
            }
            else
            {
                Console.WriteLine("Failed...");
            }
        }

        static void p_Exited(object sender, EventArgs e)
        {
            // remove all  files excluding *.pdf

            //Edit
            Console.WriteLine("exited...");
        }
    }
}

使用 -interaction=nonstopmode 的想法属于@Martin 此处

I want to create a LaTeX editor to produce pdf documents.
Behind the scene, my application uses pdflatex.exe executed through a Process instance.

pdflatex.exe needs an input file, e.g., input.tex as follows

\documentclass{article}
\usepackage[utf8]{inputenc}
\begin{document}
\LaTeX\ is my tool.
\end{document}

For the sake of simplicity, here is the minimal c# codes used in my LaTeX editor:

using System;
using System.Diagnostics;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Process p = new Process();

            p.EnableRaisingEvents = true;
            p.Exited += new EventHandler(p_Exited);

            p.StartInfo.Arguments = "input.tex";
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.FileName = "pdflatex.exe";

            p.Start();
            p.WaitForExit();
        }

        static void p_Exited(object sender, EventArgs e)
        {
            // remove all auxiliary files, excluding *.pdf.
        }
    }
}

The question is

How to detect the pdflatex.exe whether it stops working due to an invalid input?

Edit

This is the final working solution:

using System;
using System.Diagnostics;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Process p = new Process();

            p.EnableRaisingEvents = true;
            p.Exited += new EventHandler(p_Exited);

            p.StartInfo.Arguments = "-interaction=nonstopmode input.tex";// Edit
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.FileName = "pdflatex.exe";
            p.StartInfo.RedirectStandardError = true;
            p.Start();
            p.WaitForExit();

            //Edit
            if (p.ExitCode == 0)
            {
                Console.WriteLine("Succeeded...");
            }
            else
            {
                Console.WriteLine("Failed...");
            }
        }

        static void p_Exited(object sender, EventArgs e)
        {
            // remove all  files excluding *.pdf

            //Edit
            Console.WriteLine("exited...");
        }
    }
}

The idea using -interaction=nonstopmode belongs to @Martin here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

傾旎 2024-10-27 06:57:24

大多数命令行应用程序都会设置退出代码来指示成功或失败。你这样测试它:

p.WaitForExit();
if (p.ExitCode == 0) {
    // Success
} else {
    // Failure
}

Most command-line applications set an exit code to indicate success or failure. You test it thus:

p.WaitForExit();
if (p.ExitCode == 0) {
    // Success
} else {
    // Failure
}
晨曦慕雪 2024-10-27 06:57:24

我想您可以通过查看其输出来了解 pdflatex 是否已停止工作(例如,匹配错误消息,看到它在超过 30 秒内没有输出任何内容,类似的事情)。

为了能够执行此类检查,您应该重定向 pdflatex 的标准输出和标准错误(您可以通过 在SO中搜索,关键是您可以读取的流的ProcessStartInfo.RedirectStandardOutput属性)/您的函数的回调;通过这种方式,您应该能够检测到推断 pdflatex 卡住的情况,然后您可以使用 p.Kill() 杀死它。

I suppose that you can understand if pdflatex has stopped working by looking at its output (e.g. matching an error message, seeing that it doesn't output anything for more than 30 seconds, something like that).

To be able to perform such checks, you should redirect the standard output and standard error of pdflatex (you can find many examples just by searching in SO, the key is the ProcessStartInfo.RedirectStandardOutput property) to a stream that you can read/a callback to a function of yours; in this way you should be able to detect the condition whence you deduce that pdflatex is stuck, and then you can kill it with p.Kill().

天荒地未老 2024-10-27 06:57:24

如果您有办法检测进程已停止工作,则可以使用

p.Kill();

终止进程的

一种方法是超时。如果您有一个单独的线程来启动此进程,则可以启动该线程并使用

        if(processThread.Join(waitTime))
        {
            // worked
        }
        else
        {
            // Timeout. need to kill process
        }

waitTime 类型为 TimeSpan 的位置

If you have a means to detect your process has stopped working, you can use

p.Kill();

to terminate the process

One way to go about it is a timeout. If you have a separate thread to launch this proces, you can start the thread and use

        if(processThread.Join(waitTime))
        {
            // worked
        }
        else
        {
            // Timeout. need to kill process
        }

where waitTime is of type TimeSpan

似狗非友 2024-10-27 06:57:24

超时更适合执行后台处理的带壳应用程序。以下代码示例为脱壳应用程序设置超时。该示例的超时设置为 5 秒。您可能需要调整此数字(以毫秒为单位计算)以进行测试:

//Set a time-out value.
int timeOut = 5000;
//Start the process.
Process p = Process.Start(someProcess);
//Wait for window to finish loading.
p.WaitForInputIdle();
//Wait for the process to exit or time out.
p.WaitForExit(timeOut);
//Check to see if the process is still running.
if (p.HasExited == false)
{
    //Process is still running.
    //Test to see if the process is hung up.
    if (p.Responding)
    {
        //Process was responding; close the main window.
        p.CloseMainWindow();
    }
    else
    {
        //Process was not responding; force the process to close.
        p.Kill();
    }
}
//continue

Time-outs are better suited for a shelled application that performs background processing. The following code sample sets a time-out for the shelled application. The time-out for the example is set to 5 seconds. You may want to adjust this number (which is calculated in milliseconds) for your testing:

//Set a time-out value.
int timeOut = 5000;
//Start the process.
Process p = Process.Start(someProcess);
//Wait for window to finish loading.
p.WaitForInputIdle();
//Wait for the process to exit or time out.
p.WaitForExit(timeOut);
//Check to see if the process is still running.
if (p.HasExited == false)
{
    //Process is still running.
    //Test to see if the process is hung up.
    if (p.Responding)
    {
        //Process was responding; close the main window.
        p.CloseMainWindow();
    }
    else
    {
        //Process was not responding; force the process to close.
        p.Kill();
    }
}
//continue
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文