Процесс, порожденный через Process.Start в .NET, зависает поток - PullRequest
6 голосов
/ 17 августа 2010

В нашем приложении есть фоновый поток, который запускает процесс через System.Diagnostics.Process:

Process.Start(
    new ProcessStartInfo
    {
        FileName = url,
        UseShellExecute = true
    }
);

Раньше у него вообще не было проблем.Но теперь фоновый поток молча умирает;он никогда не возвращается из звонка на Process.Start.Блок catch для этого кода, который обрабатывает System.Exception, также не достигается.Даже если я включаю обработку исключений, когда они появляются в отладчике Visual Studio, я не вижу исключений.Странно, процесс порождается просто отлично;браузер по умолчанию для пользователя запускается с ожидаемым URL-адресом.

Точка входа нашего процесса помечена [STAThread], как рекомендовано.

Что может вызывать молчаливое завершение потока?Есть ли какие-либо методы, которые я могу использовать для отладки того, что происходит во время завершения потока?

Обновление:

Похоже, что поток все-таки жив;он просто не возвращается с звонка.Вот его трассировка стека:

  • [В режиме ожидания или присоединения]
  • System.dll! System.Diagnostics.ShellExecuteHelper.ShellExecuteOnSTAThread () + 0x63 байта
  • System.dll! System.Diagnostics.Process.StartWithShellExecuteEx (System.Diagnostics.ProcessStartInfo startInfo) + 0x19d байт
  • System.dll! System.Diagnostics.Process.Start () + 0x39 байт
  • System.dll! System.Diagnostics.Process.Start (System.Diagnostics.ProcessStartInfo startInfo) + 0x32 байта
  • Мой метод

Обновление 2:

Запуск cmd.exe без использования оболочки для выполнения работ в качестве обходного пути.Огромное спасибо!Тем не менее, я все еще хотел бы знать , почему звонок не возвращается.

Обновление 3:

Захваты оболочки звучат каклогичное объяснение того, что может быть причиной того, что звонок не вернулся.Я не смог найти модуль-мошенник, но после последней попытки выполнить все через выполнение оболочки вызов сделал return.

В любом случае, возможно, что у пользователей могут быть расширения оболочкизагружен, что может мешать запуску процесса и не возвращать мой код.Мы ничего не можем сделать с этим , поэтому правильный ответ - использовать обходной путь запуска процесса cmd.exe.

Ответы [ 2 ]

5 голосов
/ 17 августа 2010

Как упоминал Ганс Пассант, причиной может быть зависший Process.Start звонок. При использовании Process.Start с UseShellExecute, установленным на true, функция Windows API ShellExecuteEx вызывается из-под колпачка, который может не вернуться при определенных обстоятельствах.

Вы можете проверить, так ли это, добавив сообщения трассировки в ваш код:

System.Diagnostics.Trace.WriteLine("About to start process.");
Process.Start(
   new ProcessStartInfo
   {
       FileName = url,
       UseShellExecute = true
   }
);
System.Diagnostics.Trace.WriteLine("Process started.");

Для прослушивания сообщений трассировки вы можете использовать TraceListener, проверить окно вывода Visual Studio или использовать инструмент, такой как DebugView.

В качестве обходного пути вы можете использовать команду start. Следующий код запускает скрытое окно оболочки, которое «запускает» URL:

Process.Start(
    new ProcessStartInfo()
    {
        FileName = "cmd.exe",
        Arguments = "/c start http://www.google.com",
        WindowStyle = ProcessWindowStyle.Hidden,
        UseShellExecute = false
    });
5 голосов
/ 17 августа 2010

Нет, потоки не завершаются молча, они издают громкий звук kaboom. По крайней мере, вы увидите уведомление о выходе из потока в окне вывода. Блокирование метода Process.Start () было бы еще одним объяснением, хотя объяснения этому нет. Ваш фрагмент слишком короток, чтобы поставить приличную диагностику. Возможно, что-то экологическое.


Ваша трассировка стека помогает, ShellExecuteOnSTAThread () фактически выполняет блокировку Thread.Join () в небольшом вспомогательном потоке. Этот поток необходим для вызова собственной функции API ShellExecuteEx (), он может вызываться только из потока STA. У этого есть недостаток, хотя, поток STA должен также прокачать цикл сообщения. Этот маленький помощник не делает.

То, что это вызывает проблему на вашем компьютере, все еще указывает на проблему с окружающей средой, какое-то системное дополнение, которое перехватывает вызов ShellExecuteEx (). И рассчитывает на запуск реального потока STA. Вы должны быть в состоянии найти этот вспомогательный поток обратно в окне Debug + Windows + Threads. Он должен содержать «ShellExecuteFunction» в стеке. Например, «системное дополнение», запускающее такие трюки, - это антивирусные сканеры. Вы сможете найти эту чужеродную программу обратно в окне «Отладка + модули Windows +» после того, как отметите «Включить неуправляемую отладку» на вкладке «Отладка» проекта.

Обходной путь использования UseShellExecute = false вполне приемлем здесь, между прочим. Просто тот факт, что ваша машина вроде как испортилась, судя по всему, это, конечно, не так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...