Получить идентификатор процесса из исполняемого файла оболочки? - PullRequest
0 голосов
/ 28 июня 2010

Я делаю программу для портативных КПК, используя компактную среду .net 2.0, и у меня есть одна часть, которой я не горжусь, и я надеялся на более элегантное решение. По сути, проблема заключается в другом процессе, использующем мой файл, в данном случае это Windows Media Player. Я запускаю процесс, передавая расположение файла в Process.Start, но кажется, что возвращаемый процесс недолговечен и порождает другой процесс? Поэтому я попытался найти информацию о том, как получить информацию о дочерних процессах, но у меня возникли некоторые проблемы (я думаю, что по каким-то причинам процессы не возвращались).

Так что я сейчас делаю это хитрое исправление

            string processName = item.Text;
            Process proc = Process.Start(processName, null);
            if (!proc.Start())
                MessageBox.Show("Failed to start process", "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);
            else
            {
                IntPtr newWindow = IntPtr.Zero;
                TimeSpan limit = TimeSpan.FromSeconds(3);
                DateTime start = DateTime.Now;
                DateTime now = start;

                // do while the following:
                // window is not null
                // window is not ourself
                // under 3 seconds
                do
                {
                    newWindow = Win32.GetForegroundWindow();
                    now = DateTime.Now;

                    // taking too long
                    if (now - start > limit)
                        break;
                }
                while (newWindow == IntPtr.Zero || newWindow == this.Handle);

                if (newWindow != IntPtr.Zero && newWindow != this.Handle)
                {
                    uint processID = 0;
                    if (Win32.GetWindowThreadProcessId(newWindow, out processID) != 0)
                    {
                        //const int stringSize = 1024;
                        //StringBuilder sb = new StringBuilder(1024);
                        //Win32.GetWindowText(newWindow, sb, stringSize);
                        m_processes.Add(new ProcessIDWithName(processID, processName));
                    }
                }
            }

Как видите, мне это не нравится, и оно ненадежно, но пока работает (мне нужно было решение, было ли это плохо или нет). Зачем мне нужен идентификатор процесса? Поскольку Windows Media Player держит файл открытым для меня, и я не могу переместить / удалить файл, и поэтому мне нужно прекратить процесс, прежде чем я это сделаю. Я мог бы сделать подобное исправление с FindWindow, но я думал более обобщенно, поскольку это может быть не медиа-файл, открытый в Windows Media Player.

Так что, в принципе, я бы хотел лучшего решения, если это возможно!

Кроме того, если вам интересно, почему я не использую его секундомер, потому что, кажется, его нет в .net 2.0 cf, мне также не нужна точность в этом отношении.

Ответы [ 2 ]

1 голос
/ 28 июня 2010

Здесь появляется множество вопросов.

  1. Почему вы сами не запускаете медиаплеер вместо шелкса имени целевого файла?
  2. Как вы узнаете, когда закончится воспроизведение мультимедиа, чтобы закрыть файл?
  3. Почему бы не использовать API toolhelp для простого перечисления процессов вместо дурацких shenanigans GetForegroundWindow / GetWindowsThreadProcessId?
  4. Почему вы просто не используете элемент управления Media Player ActiveX вместо этого клуджа, чтобы на самом деле иметь контроль над вещами?

Если вы намереваетесь сделать это универсальным для любого файла (т.е. не только для мультимедиа, но, возможно, для чего-то вроде средства просмотра Word и т. Д.), То вам действительно не повезло, и вам нужно переосмыслить все, что вы пытаетесь сделать (вы не сказали нам, чего пытаетесь достичь, только как [решили это осуществить). Приложения обычно не закрываются в WinMo, они, как правило, просто теряют фокус, сводятся к минимуму, поэтому вы не знаете, когда пользователь «покончил» с файлом.

Возможно, приложение, связанное с файлом, уже запущено, поэтому его закрытие - недружелюбная вещь.

Целевое приложение действительно не предназначено для обратного вызова, когда оно выполняется с каким-либо конкретным файлом.

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

У меня нет опыта программирования на КПК, но вы можете попробовать использовать объекты Job (см. http://msdn.microsoft.com/en-us/library/ms684847.aspx#job_object_functions).. Что касается CreateJobObject, вы можете создать новую работу. Затем вы создаете приостановленный * 1005.* обработайте и используйте AssignProcessToJobObject, чтобы назначить новый процесс объекту задания. Затем вы сможете возобновить процесс.

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

...