Запуск клиента удаленного рабочего стола. Нет контроля над PID Kill. Изменения PID после запуска ... WTF? - PullRequest
1 голос
/ 23 июня 2010

Я пишу программу (Visual Studio 2010 в C # Windows Forms), которая отслеживает несколько экземпляров клиента удаленного рабочего стола (mstsc.exe - протестировано с версией Windows 7).Я пытался запустить эту программу и получить ее PID со следующим кодом:

Process mstsc = Process.Start(mstscLocation, mstscConString);
int mstscProcessId = mstsc.Id;
DataRow row = openConn.NewRow();
row["RDP ID"] = mstscID;
openConn.Rows.Add(row);

Это запускает клиент и возвращает идентификатор, как и должно.Проблема в том, что если я пытаюсь завершить PID с помощью следующего кода, он не может это сделать:

int rdpID = Convert.ToInt32(dgvOpenConnections.Rows[selectedIndex].Cells["RDP ID"].Value.ToString());

try
{
    // kill off mstsc
    Process mstsc = Process.GetProcessById(rdpID);
    mstsc.Kill();
}

Я убедился, что PID, записанный из Process.Start, совпадает с тем, который полученDataGridView (dgvOpenConnections) и помещается в rpdID (попытка завершается с ошибкой и вызывает перехват, поскольку исходный PID больше не существует).Кроме того, я запустил «список задач» в командной строке после запуска одного экземпляра MSTSC.EXE и могу убедиться, что он изменяет PID (в этом тесте C # записал 4288, но в списке задач он работает как 8172).* Я не могу уничтожить все процессы MSTSC, так как пытаюсь контролировать более одного.Есть ли способ отследить второй PID, который MSTSC использует?Я предполагаю, что он либо запускает второй процесс и избавляется от первого, либо, возможно, это дочерний процесс (хотя возвращаемый PID больше не существует после запуска).

Как в C # я могу убедиться, что у меня естьправильный идентификатор процесса для последующего мониторинга или уничтожения определенного экземпляра клиента удаленного рабочего стола?

Ответы [ 2 ]

4 голосов
/ 05 июля 2012

Это происходит, если вы пытаетесь запустить mstsc из 32-битного приложения в 64-битной Windows.

(Источник: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/22c10140-a502-4aa1-98d3-3607b8b573e8/)

Есть две версии mstsc в 64-битной Windows:

  1. c:\windows\system32\mstsc.exe - это 64-битная версия
  2. c:\windows\syswow64\mstsc.exe -более или менее «перенаправление», которое откроет c:\windows\system32\mstsc.exe из процесса, отличного от вашего приложения.

У меня возникла та же проблема. Мое приложение запустило mstsc, процесс немедленно завершился и mstscвновь появился с другим родительским процессом и другим PID.

Это происходит потому, что 64-разрядная Windows использует перенаправление файловой системы для перенаправления вызовов на 64-разрядные c:\windows\system32 исполняемые файлы на c:\windows\syswow64.

Существует два решения:

  1. Перекомпилируйте ваше приложение в 64-битное. Тогда ваше приложение также будет использовать 64-битный mstsc.
  2. Отключить перенаправление файловой системы (см. http://blog.tonycamilli.com/2005/07/disabling-wow64-file-system.html) и получить доступ к 64-битному mstsc из вашего 32-битного приложения.

Я только попробовал перекомпилировать, и это сработало.: -)

Редактировать: Если вы не хотите, чтобы ваши пользователи использовали правильную версию (мы используем развертывание ClickOnce, поэтому мы скорее отправим one ссылка на всех), вот обходной путь:

Если вы используете файл .RDP для mstsc, просто добавьте уникальный токен к имени вашего файла.mstsc будет запущен из командной строки, например mstsc host_user_token.rdp.

Теперь, после того, как вы позвонили Process.Start, выполните Process.WaitForExit с коротким тайм-аутом (5 с).Если процесс не завершился, у вас есть нужный объект.

Если процесс did завершился, выполните небольшой цикл опроса (интервал 100 мс, время ожидания 5 с), который проверяет процессы с помощью вашего токена.:

var timeout = AppSettings.GetIntValue(
            Constants.SettingsKeyProcessFinderTimeout, Constants.ProcessFinderTimeoutDefault);
int elapsedTime = 0;
Process process = null;
while (elapsedTime <= timeout)
{
    process =
        Process.GetProcessesByName("mstsc").FirstOrDefault(p => p.StartInfo.Arguments.Contains(guid));
    Logger.TraceVerbose(
        string.Format(
            "Elapsed time: {0}; Found process with PID {1}", elapsedTime, process == null ? -1 : process.Id));
    if (process != null)
    {
        break;
    }

    Thread.Sleep(SleepInterval);
    elapsedTime += SleepInterval;
}

После этого цикла, если у вас все еще есть process == null, произошла какая-то ошибка (процесс не был найден или никогда не выполнялся вообще).Если у вас есть ссылка на процесс, это «новый» процесс mstsc.

0 голосов
/ 23 июня 2010

Я попробовал ваш пример с помощью Process Explorer, и я не смог увидеть создание второго или дочернего процесса.От начала до конца Процесс удаленного рабочего стола был одним и тем же, и после создания я смог убить процесс, используя тот же PID, который я видел в начале.

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