none
WaitForExit() не ждет некоторые процессы RRS feed

  • Вопрос

  • Приложение должно открывать различные заранее неизвестные типы файлов. В части кода использую WaitForExit(), чтобы открыть процесс (показать файл в соответствующем расширению приложении), дождаться завершения этого стороннего приложения, а затем удалить файл.

    ProcessStartInfo startInfo = new ProcessStartInfo( destFile );
    startInfo.UseShellExecute = true;
    startInfo.CreateNoWindow = true;
    
    Process proc = new Process();
    proc.StartInfo = startInfo;proc.Start();
    proc.WaitForExit();
    
    File.Delete( destFile );

    Проблема в том, что WaitForExit() ждет завершения почему-то не всех процессов. Например документы word и excel ждет закрытия, а при открытии картинок и видео в стандартном просмотрщике фото и видео не ждет, и переходит сразу к File.Delete.

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

    Подскажите как решить.

    4 февраля 2017 г. 17:04

Ответы

  • Стандартный просмотрщик Windows не является, хм, программой, он - часть Windows Explorer. Технически, в XP он открывается в контексте Explorer.exe, в Win7 - dllhost.exe. Если процесс уже запущен, ShellExecute не вернет действительный дескриптор процесса, поэтому WaitForExit не будет работать.

    что делать? наверное находить окно в котором картинка отображается (его заголовок обычно содержит имя файла), и ждать пока оно не закроется

    • Помечено в качестве ответа Solaris-chel 4 февраля 2017 г. 19:27
    4 февраля 2017 г. 17:52
  • Создание окна занимает некоторое время. Добавьте после proc.Start() ожидание в 500 мс, чтобы окно успело создаться. В отладчике просто программа выполняется медленнее, и это не проявляется.
    • Помечено в качестве ответа Solaris-chel 5 февраля 2017 г. 15:57
    5 февраля 2017 г. 15:34

Все ответы

  • Стандартный просмотрщик Windows не является, хм, программой, он - часть Windows Explorer. Технически, в XP он открывается в контексте Explorer.exe, в Win7 - dllhost.exe. Если процесс уже запущен, ShellExecute не вернет действительный дескриптор процесса, поэтому WaitForExit не будет работать.

    что делать? наверное находить окно в котором картинка отображается (его заголовок обычно содержит имя файла), и ждать пока оно не закроется

    • Помечено в качестве ответа Solaris-chel 4 февраля 2017 г. 19:27
    4 февраля 2017 г. 17:52
  • Не пойму что за барабашка такой с этим просмотрщиком?

    Делаю так:

    using Microsoft.Win32; using System; using System.IO; using System.Windows.Forms; using System.Diagnostics; using System.Threading; using System.Runtime.InteropServices; namespace Test { classProgram { [DllImport( "user32.dll" )] [return: MarshalAs( UnmanagedType.Bool )] static extern bool EnumChildWindows( IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam ); [DllImport( "user32.dll", CharSet = CharSet.Auto, SetLastError = true )] private static extern bool EnumWindows( EnumWindowsProc callback, IntPtr extraData ); private delegate bool EnumWindowsProc( IntPtr hWnd, IntPtr lParam ); [DllImport( "user32.dll", CharSet = CharSet.Auto )] public static extern int GetWindowText( IntPtr handleWindow, char[] buffer, int max ); [DllImport( "user32.dll", CharSet = CharSet.Auto )] public static extern int GetWindowTextLength( IntPtr hWnd ); private static bool findWindow = false; private static string destFile; [STAThread] static void Main( string[] args ) {

    ProcessStartInfo startInfo = new ProcessStartInfo( destFile ); startInfo.UseShellExecute = true; startInfo.CreateNoWindow = false; Process proc = new Process(); proc.StartInfo = startInfo; proc.Start(); EnumWindows( Proc, ( IntPtr ) null ); if ( findWindow ) File.Delete( destFile ); } private static bool Proc( IntPtr hW, IntPtr lParam ) { char[] buffer = newchar[301]; GetWindowText( hW, buffer, 300 ); string windowTitle = newstring( buffer ); string fName = Path.GetFileNameWithoutExtension( destFile ); if ( windowTitle.Contains( fName ) ) { findWindow = true; while ( GetWindowTextLength( hW ) > 0 ) { Thread.Sleep( 100 ); } return false; } else { EnumChildWindows( hW, Proc, ( IntPtr ) null ); if ( findWindow == true ) { return false; } } return true; } }

    }

    Когда код работает в отладчике Visual Studio, всё замечательно отрабатывает. Но когда я запускаю скомпилированный файл программы, то файл (который я запускал) открывается но не удаляется. Т.е. опять программа не может найти окно ( if (windowTitle.Contains(fName) ). И опять это безобразие в просмотрщике видео и картинок. Другие файлы открываются корректно с последующим удалением.
               
    
    
    5 февраля 2017 г. 14:23
  • Создание окна занимает некоторое время. Добавьте после proc.Start() ожидание в 500 мс, чтобы окно успело создаться. В отладчике просто программа выполняется медленнее, и это не проявляется.
    • Помечено в качестве ответа Solaris-chel 5 февраля 2017 г. 15:57
    5 февраля 2017 г. 15:34
  • Спасибо огромное, помогло!
    5 февраля 2017 г. 15:58