Process.Start 阻塞

发布于 2024-09-06 18:09:12 字数 2321 浏览 6 评论 0原文

我正在调用 Process.Start,但它会阻止当前线程。

pInfo = new ProcessStartInfo("C:\\Windows\\notepad.exe");

// Start process
mProcess = new Process();
mProcess.StartInfo = pInfo;
if (mProcess.Start() == false) {
    Trace.TraceError("Unable to run process {0}.");
}

即使进程关闭,代码也不再响应。

但 Process.Start 真的应该阻塞吗?这是怎么回事?

(进程正确启动)


using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;

namespace Test
{
    class Test
    {
        [STAThread]
        public static void Main()
        {
            Thread ServerThread = new Thread(AccepterThread);
            ServerThread.Start();

            Console.WriteLine (" ---  Press ENTER to stop service ---");
            while (Console.Read() < 0) { Application.DoEvents(); }

            Console.WriteLine("Done.");
        }

        public static void AccepterThread(object data)
        {
            bool accepted = false;

            while (true) {
                if (accepted == false) {
                    Thread hThread = new Thread(HandlerThread);
                    accepted = true;
                    hThread.Start();
                } else
                    Thread.Sleep(100);
            }
        }

        public static void HandlerThread(object data)
        {
            ProcessStartInfo pInfo = new ProcessStartInfo("C:\\Windows\\notepad.exe");

            Console.WriteLine("Starting process.");

            // Start process
            Process mProcess = new Process();
            mProcess.StartInfo = pInfo;
            if (mProcess.Start() == false) {
                Console.WriteLine("Unable to run process.");
            }
            Console.WriteLine("Still living...");
        }
    }
}

控制台输出为:

--- 按 ENTER 停止服务 --- 启动过程。


找到它:

[STAThread]

使 Process.Start 阻塞。我阅读了 STAThread 和多线程,但我无法将这些概念与 Process.Start 行为联系起来。

AFAIK,Windows.Form需要 STAThread。使用 Windows.Form 时如何解决此问题?


地狱新闻

如果我重建我的应用程序,第一次我运行应用程序时可以正常工作,但是如果我停止调试并再次重新启动 iy,则会出现问题。

当应用程序在没有调试器的情况下执行时,不会出现此问题。

I'm calling Process.Start, but it blocks the current thread.

pInfo = new ProcessStartInfo("C:\\Windows\\notepad.exe");

// Start process
mProcess = new Process();
mProcess.StartInfo = pInfo;
if (mProcess.Start() == false) {
    Trace.TraceError("Unable to run process {0}.");
}

Even when the process is closed, the code doesn't respond anymore.

But Process.Start is really supposed to block? What's going on?

(The process start correctly)


using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;

namespace Test
{
    class Test
    {
        [STAThread]
        public static void Main()
        {
            Thread ServerThread = new Thread(AccepterThread);
            ServerThread.Start();

            Console.WriteLine (" ---  Press ENTER to stop service ---");
            while (Console.Read() < 0) { Application.DoEvents(); }

            Console.WriteLine("Done.");
        }

        public static void AccepterThread(object data)
        {
            bool accepted = false;

            while (true) {
                if (accepted == false) {
                    Thread hThread = new Thread(HandlerThread);
                    accepted = true;
                    hThread.Start();
                } else
                    Thread.Sleep(100);
            }
        }

        public static void HandlerThread(object data)
        {
            ProcessStartInfo pInfo = new ProcessStartInfo("C:\\Windows\\notepad.exe");

            Console.WriteLine("Starting process.");

            // Start process
            Process mProcess = new Process();
            mProcess.StartInfo = pInfo;
            if (mProcess.Start() == false) {
                Console.WriteLine("Unable to run process.");
            }
            Console.WriteLine("Still living...");
        }
    }
}

Console output is:

--- Press ENTER to stop service ---
Starting process.


Found it:

[STAThread]

Makes the Process.Start blocking. I read STAThread and Multithreading, but I cannot link the concepts with Process.Start behavior.

AFAIK, STAThread is required by Windows.Form. How to workaround this problem when using Windows.Form?


News for the hell:

If I rebuild my application, the first time I run application work correctly, but if I stop debugging and restart iy again, the problem araise.

The problem is not raised when application is executed without the debugger.

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

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

发布评论

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

评论(6

浪推晚风 2024-09-13 18:09:12

不,Process.Start 不会等待子进程完成...否则您将无法使用重定向 I/O 等功能。

示例控制台应用程序:

using System;
using System.Diagnostics;

public class Test
{
    static void Main()
    {
        Process p = new Process { 
            StartInfo = new ProcessStartInfo("C:\\Windows\\notepad.exe")
        };
        p.Start();
        Console.WriteLine("See, I'm still running");
    }
}

这会打印“看,我仍在运行”,在我的盒子上没有任何问题 - 它在你的盒子上做什么?

No, Process.Start doesn't wait for the child process to complete... otherwise you wouldn't be able to use features like redirected I/O.

Sample console app:

using System;
using System.Diagnostics;

public class Test
{
    static void Main()
    {
        Process p = new Process { 
            StartInfo = new ProcessStartInfo("C:\\Windows\\notepad.exe")
        };
        p.Start();
        Console.WriteLine("See, I'm still running");
    }
}

This prints "See, I'm still running" with no problems on my box - what's it doing on your box?

友谊不毕业 2024-09-13 18:09:12

创建一个 ProcessStartInfo 并将 UseShellExecute 设置为 false(默认值是真的)。您的代码应为:

pInfo = new ProcessStartInfo("C:\\Windows\\notepad.exe");
pInfo.UseShellExecute = false;

// Start process
mProcess = new Process();
mProcess.StartInfo = pInfo;
if (mProcess.Start() == false) {
    Trace.TraceError("Unable to run process {0}.");
}

我遇到了同样的问题,并直接从可执行文件启动创建进程的可执行文件解决了该问题。

Create a ProcessStartInfo and set UseShellExecute to false (default value is true). Your code should read:

pInfo = new ProcessStartInfo("C:\\Windows\\notepad.exe");
pInfo.UseShellExecute = false;

// Start process
mProcess = new Process();
mProcess.StartInfo = pInfo;
if (mProcess.Start() == false) {
    Trace.TraceError("Unable to run process {0}.");
}

I had the same issue and starting the executable creating the process directly from the executable file solved the issue.

顾忌 2024-09-13 18:09:12

我在 WinForms 应用程序中遇到了与原始海报相同的阻塞行为,因此我创建了下面的控制台应用程序来简化测试此行为。

Jon Skeet 的示例使用记事本,正常加载只需要几毫秒,因此线程块可能不会被注意到。我试图启动 Excel,这通常需要更长的时间。

using System;
using System.Diagnostics;
using static System.Console;
using System.Threading;

class Program {

    static void Main(string[] args) {

        WriteLine("About to start process...");

        //Toggle which method is commented out:

        //StartWithPath();  //Blocking
        //StartWithInfo();  //Blocking
        StartInNewThread(); //Not blocking

        WriteLine("Process started!");
        Read();
    }

    static void StartWithPath() {
        Process.Start(TestPath);
    }

    static void StartWithInfo() {
        var p = new Process { StartInfo = new ProcessStartInfo(TestPath) };
        p.Start();
    }

    static void StartInNewThread() {
        var t = new Thread(() => StartWithPath());
        t.Start();
    }

    static string TestPath =
        Environment.GetFolderPath(Environment.SpecialFolder.Desktop) +
        "\\test.xlsx";
}

StartWithPathStartWithInfo 的调用会阻止控制台应用程序中的线程。在 Excel 初始屏幕关闭并打开主窗口之前,我的控制台不会显示“进程已启动”。

输入图片这里的描述

StartInNewThread 将立即在控制台上显示两条消息,而 Excel 的启动屏幕仍然打开。

I was experiencing the same blocking behavior as the original poster in a WinForms app, so I created the console app below to simplify testing this behavior.

Jon Skeet's example uses Notepad, which only takes a few milliseconds to load normally, so a thread block may go unnoticed. I was trying to launch Excel which usually takes a lot longer.

using System;
using System.Diagnostics;
using static System.Console;
using System.Threading;

class Program {

    static void Main(string[] args) {

        WriteLine("About to start process...");

        //Toggle which method is commented out:

        //StartWithPath();  //Blocking
        //StartWithInfo();  //Blocking
        StartInNewThread(); //Not blocking

        WriteLine("Process started!");
        Read();
    }

    static void StartWithPath() {
        Process.Start(TestPath);
    }

    static void StartWithInfo() {
        var p = new Process { StartInfo = new ProcessStartInfo(TestPath) };
        p.Start();
    }

    static void StartInNewThread() {
        var t = new Thread(() => StartWithPath());
        t.Start();
    }

    static string TestPath =
        Environment.GetFolderPath(Environment.SpecialFolder.Desktop) +
        "\\test.xlsx";
}

Calls to both StartWithPath and StartWithInfo block my thread in a console app. My console does not display "Process Started" until after the Excel splash screen closes and the main window is open.

enter image description here

StartInNewThread will display both messages on the console immediately, while the splash screen for Excel is still open.

苯莒 2024-09-13 18:09:12

当启动位于不同域(我们有双受信任域)的网络驱动器上的 .bat 脚本时,我们遇到了此问题。我运行了远程 C# 调试器,果然 Process.Start() 无限期地阻塞。

在 power shell 中以交互方式重复此任务时,会弹出一个安全对话框:

在此处输入图像描述

至于解决方案,这是我们前进的方向。完成这项工作的人修改了域 GPO 以实现信任。

We had this problem when launching a .bat script that was on a network drive on a different domain (we have dual trusted domains). I ran a remote C# debugger and sure enough Process.Start() was blocking indefinitely.

When repeating this task interactively in power shell, a security dialog was popping up:

enter image description here

As far as a solution, this was the direction we went. The person that did the work modified domain GPO to accomplish the trust.

昵称有卵用 2024-09-13 18:09:12

通过命令提示符启动服务器:

"C:\Program Files (x86)\IIS Express\iisexpress" /path:\Publish /port:8080

这可以访问操作系统树进程的子线程。

Start server via command prompt:

"C:\Program Files (x86)\IIS Express\iisexpress" /path:\Publish /port:8080

This take access to sub-threads of the tree process of OS.

溇涏 2024-09-13 18:09:12

如果您想启动进程,然后使进程独立于“启动器”/原始调用:

//Calling process
using (System.Diagnostics.Process ps = new System.Diagnostics.Process())
{
    try
    {
        ps.StartInfo.WorkingDirectory = @"C:\Apps"; 
        ps.StartInfo.FileName = @"C:\Program Files\Microsoft Office\Office14\MSACCESS.EXE"; //command
        ps.StartInfo.Arguments = @"C:\Apps\xyz.accdb"; //argument
        ps.StartInfo.UseShellExecute = false;
        ps.StartInfo.RedirectStandardOutput = false;
        ps.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Maximized;
        ps.StartInfo.CreateNoWindow = false; //display a windows
        ps.Start();
    }
    catch (Exception ex)
    {
        MessageBox.Show(string.Format("==> Process error <=={0}" + ex.ToString(), Environment.NewLine));
    }
} 

If you want to launch process and then make the process independent on the "launcher" / the originating call:

//Calling process
using (System.Diagnostics.Process ps = new System.Diagnostics.Process())
{
    try
    {
        ps.StartInfo.WorkingDirectory = @"C:\Apps"; 
        ps.StartInfo.FileName = @"C:\Program Files\Microsoft Office\Office14\MSACCESS.EXE"; //command
        ps.StartInfo.Arguments = @"C:\Apps\xyz.accdb"; //argument
        ps.StartInfo.UseShellExecute = false;
        ps.StartInfo.RedirectStandardOutput = false;
        ps.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Maximized;
        ps.StartInfo.CreateNoWindow = false; //display a windows
        ps.Start();
    }
    catch (Exception ex)
    {
        MessageBox.Show(string.Format("==> Process error <=={0}" + ex.ToString(), Environment.NewLine));
    }
} 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文