Запустите процесс Win32 A, который запускает процесс B - получите ID / HWND для B - PullRequest
3 голосов
/ 01 июня 2011

Хорошо, я потратил немного времени на этом сайте, выясняя, как запустить «дочерний» процесс (т. Е. Новый процесс устанавливает для меня родительский элемент окна), используя вызовы Win32 из C #. Это работает, пока не пересекает границы UAC. Хорошо.

Теперь я пытаюсь сделать это с помощью программы удаления (процесс A), которая загружает временную программу (процесс B), которая фактически выполняет эту работу. Процесс A уходит после создания B. Моему коду требуется идентификатор процесса, из которого можно получить дескриптор окна, который передается в SetParent. Выглядит примерно так:

Process p = new Process();
try
{
    p.EnableRaisingEvents = true;
    p.StartInfo.FileName = fileName;
    p.StartInfo.Arguments = arguments;
    if (p.Start())
    {
        p.WaitForInputIdle(10000);
        IntPtr pHwnd = p.MainWindowHandle;
        if (pHwnd == IntPtr.Zero)
        {
            return null;
        }
        IntPtr currentHwnd = Process.GetCurrentProcess().MainWindowHandle;
        if (SetParent(pHwnd, currentHwnd) == 0)
        {
            if (Marshal.GetLastWin32Error() == 5) // access denied
            {
                // Need to launch privileged process that launches process 
                // and sets parent on UAC enabled OS.
            }
            else
            {
                return null;
            }
        }
        // AND SO ON AND SO FORTH

Прекрасно работает, пока р не уходит. В этом случае р начинает бум после запуска р '. Несмотря на это, р никогда не имеет дескриптора окна.

Итак, как мне контролировать p, чтобы увидеть, если он начинает p 'и получить идентификатор (или, что более важно, дескриптор окна) для p'? Я могу получить HWND из идентификатора, но мне нужно получить один или другой.

Спасибо!

1 Ответ

0 голосов
/ 01 июня 2011

Простое решение может быть, проверьте, если p равно нулю, прежде чем пытаться получить его MainWindowHandle. Вот пример кода, который вы можете адаптировать при необходимости.

           using (Process proc = new Process())
            {

                proc.StartInfo.FileName = filename;
                proc.StartInfo.UseShellExecute = false;
                proc.StartInfo.WorkingDirectory = ClientInstallPath;
                proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

                proc.Start();

                if (proc != null)
                {
                    proc.WaitForExit();
                    returnCode = proc.ExitCode;
                }
            }
...