【问题标题】:C#: How can I open a process, wait until the program in the process loads completely, and then use a new process to execute commands?C#:如何打开一个进程,等到进程中的程序加载完毕,再使用新进程执行命令?
【发布时间】:2020-10-08 23:36:27
【问题描述】:

使用C#,我需要打开一个程序,等到该程序完全加载完毕,然后我想运行cmd.exe运行附加命令来操作程序的原始实例。

我正在尝试让一个名为 GerbView 的特定程序以某种方式运行。该程序用于查看 Gerber 文件,PCB 制造商用于蚀刻 PCB 的文件。该程序可以使用自己的 Open 命令在内部加载 Gerber 文件。但是,我的程序旨在处理其中一些 Gerber 文件,然后使用 GerbView 加载这些已处理的 Gerber 文件。我能够完成此任务的唯一方法是通过命令行界面。可以打开 Gerber 文件的命令是 gerbview {filename}

我知道 Process 类可以使用 FileName 和 Arguments 属性轻松完成此操作,但我需要向同一个实例添加更多文件。执行此操作的命令是 gerbview /add {filename}

最后一个命令将启动程序,如果一个实例已经打开,它只会添加一个额外的文件来查看。现在这就是我的问题所在。在我提出最终解决方案(见下文)之前,我的程序一直打开多个实例(尽管使用了 /add 参数),可能是因为程序还没有准备好输入,而其余的 /add 参数正在执行。只有当我添加 1 秒延迟时,代码才能正确运行。但是,当我通过 Microsoft Teams 向某人展示时,旧行为又回来了,直到我增加了延迟(我假设 Teams 广播导致需要更大的延迟)。以下是我目前的解决方案(程序是windows窗体的一部分):

Process gerbView;
Process cmd;
bool gerbViewActive;

// The is the windows form constructor
public WindowsFormGUI()
{
    InitializeComponent();
    gerbViewActive = false;
}

private void buttonRunProgram_Click(object sender, EventArgs e)
{
    OpenFileDialog loadFiles = new OpenFileDialog
    {
        Multiselect = true,
        InitialDirectory = Directory.GetParent(Directory.GetCurrentDirectory()).FullName
    };

    if (loadFiles.ShowDialog() == DialogResult.OK)
    {
        if (!gerbViewActive)
        {
            gerbView = new Process();
            gerbView.EnableRaisingEvents = true;
            gerbView.Exited += new EventHandler(GerbView_Exited);
            gerbView.StartInfo.FileName = @"C:\Program Files\Software Companions\GerbView\gerbview.exe";
            gerbView.StartInfo.WindowStyle = ProcessWindowStyle.Maximized;
            gerbView.Start();
            gerbViewActive = true;
        }
        
        // wait until GerbView loads before running the cmd process.
        Thread.Sleep(2000);
        
        string[] files = loadFiles.FileNames;
        cmd = new Process();
        cmd.StartInfo.FileName = "cmd.exe";
        cmd.StartInfo.RedirectStandardInput = true;
        cmd.StartInfo.UseShellExecute = false;
        cmd.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        cmd.StartInfo.WorkingDirectory = @"C:\Program Files\Software Companions\GerbView\";
        cmd.Start();
        using (StreamWriter cmdInput = cmd.StandardInput)
        {
            for (int index = 0; index < files.Length; index++)
            {
                cmdInput.WriteLine("gerbview.exe /add " + files[index]);
            }
        }
        cmd.Close();
    }
}

private void GerbView_Exited(object sender, EventArgs e)
{
    gerbViewActive = false;
    gerbView.Close();
}

任何帮助或建议将不胜感激。

【问题讨论】:

  • 欢迎并祝贺您的​​第一篇文章!我喜欢您提供的详细信息,但我可以理解为什么有人会否决您-您需要更多地关注您的问题。此外,您可以展示更多的故障排除。祝您的解决方案一切顺利!

标签: c#


【解决方案1】:

首先,您正在执行的命令行工具必须尝试定位现有进程并与之通信。我会跳过运行cmd.exe,而自己运行每个gerbview.exe /add 进程。然后您可以.WaitForExit() 确保每个进程都已完成,然后再开始另一个进程。然而,这可能还不够。

接下来,您需要在主 UI 进程上 .WaitForInputIdle() 进行阻塞,直到主线程清除它的 win32 事件队列。这很可能是他们文件打开命令行成功与之通信的必要条件。

明确地说,您需要的最少步骤是:

  • 启动主进程“gerbview.exe”,然后循环文件;
    • 主进程.WaitForInputIdle
    • 使用参数 $"/add "{filename}"" 启动“gerbview.exe”
    • .WaitForExit 这个“gerbview.exe”进程

由于您要启动与主 UI 相同的查看器可执行文件并打开每个文件,因此它很可能是“Windows 子系统”可执行文件,而不是控制台可执行文件。 cmd.exe 将启动该进程,但在退出之前不会阻塞。确定它已经退出的唯一方法是自己开始这个过程。

您还可以尝试向查看器进程的窗口句柄发布或发送一些 noop 窗口消息,以确保 .WaitForInputIdle 有一些新的输入等待。

这些都不能保证这个过程会奏效。这完全取决于这个第 3 方应用程序的编写方式。

【讨论】:

  • "接下来,您需要 .WaitForInputIdle()" 和 "这很可能是必要条件" - 但这是仍然是一个假设,可能并非如此。如果这不起作用,问题就会变得更加困难
  • 我的程序 sn-p 显示我正在打开 GerbView 进程来激活程序,因为没有第一个实例,我无法自动将多个文件添加到查看器。我打开 cmd.exe 进程,以便自动运行 /add 参数。我无法手动运行 /add,因为它违背了自动化的目的。如果我使用 .WaitForExit() 方法,它将锁定程序,等待 GerbView 退出,这是我不想要的。我刚才尝试使用 .WaitForInputIdle() 并没有等到 GerbView 完全加载。正如代码 sn-p 所代表的那样,它可以按我的预期工作,但我希望
  • 用于允许动态等待而不是 Thread.Sleep() 代码行的选项。
  • " 我打开 cmd.exe 进程,这样我就可以自动运行 /add 参数" 只需自己传递参数stackoverflow.com/questions/5766574/…。然后您可以等待该进程退出,而不是 cmd 或主视图进程。否则你可能会在主视图进程中过早地 .WaitForInputIdle。
猜你喜欢
  • 2020-04-07
  • 1970-01-01
  • 2021-11-12
  • 2016-09-09
  • 1970-01-01
  • 2013-06-15
  • 2015-06-16
  • 2015-06-13
  • 1970-01-01
相关资源
最近更新 更多