WaitForExit dla programów typu MS Word - proces już rozpoczęty.

0

Chce w mojej aplikacji otworzyć plik "*.rtf", a następnie poczekać aż zostanie on zamknięty. Nie zawsze, choć jednak zazwyczaj użytkownik ma MS Worda i tu jest problem. Poniższy kod działa, pod warunkiem, że proces "WINWORD" nie jest jeszcze uruchomiony. Gdy jest, to po wywołaniu metody Process.Start() otwiera się tylko nowe okno Worda, a większość danych z obiektu Process 'p' jest pusta. Nie można 'czekać' aż się zakończy, bo wywala exceptiona. Jak sobie z tym poradzić? Proszę o pomoc.

            Process p = new Process();
            p.StartInfo.FileName = @"C:\Users\UserName\Desktop\MyFile.rtf";
            p.Start();
            string name = p.ProcessName;
            p.WaitForExit();
            Console.WriteLine(name + " has exited");
            Console.ReadKey();
 
1

A próbowałeś uruchomić WINWORD.EXE, podając w argumentach ścieżkę do pliku .rtf?

1

A zastanów się, jaki proces właściwie reprezentuje twój proces p? Skąd twój program w ogóle ma wiedzieć, że chodzi ci o Worda?
Tworzysz obiekt, super, ale może tak użyj metody GetProcessByName, żeby przypisać go do procesu Worda?

Fakt, dalej nie będzie działało, gdy Word będzie wyłaczony. Wtedy sprawdź, czy dostałeś ten proces czy też nie i jeśli nie, to go odpal... przez zwykłe ShellExecute.

0

Czytając powyższe komentarze, uznałem, że mój sposób na oczekiwanie jest bezsensu. Z jednej strony chce dać możliwość otwarcia w kilku programach tego pliku *.rtf, zależnie co tam użytkownik ma na dysku. Z drugiej jednak, trzeba by obsłużyć to, że gdy aplikacja jest taka jak Word, to należy czekać na zamknięcie okna, a nie całego procesu. Jak sobie z tym poradzić?

1

Według mnie masz dwa podejścia: wykorzystanie Microsoft.Office.Interop.Word, dzięki czemu dostajesz szerszą kontrolę nad tym co się dzieje po stronie Worda, albo zaprzyjaźnienie się z VBA.
W obu przypadkach - musisz jakoś wyróżnić "twoje" dokumenty od tych użytkownika. Najprościej - nazywaj je jakoś specjalnie, z przedrostkiem czy coś. Jeśli po stronie VBA, to zmodyfikuj szablon normal.dot, tak by na event zamknięcia dokumentu sprawdzał jego nazwę i jeśli to twój to coś tam robił.

Jeżeli jednak chcesz, żeby twój dokument mógł być otwierany w różnych programach... to cóż, czeka cię większa jazda :P Musisz wiedzieć w jakim programie będzie to otwierane. Musisz zastosować oddzielny kod dla MS Office i oddzielny dla innych Office'ów. Według mnie gra niewarta świeczki, dużo prościej narzucić Worda, ewentualnie Wordpada.

1

Chyba czegoś nie rozumiem. Chcemy monitorować plik czy program z niego korzystający? Bo jeśli to pierwsze, to moim zdaniem wystarczy taki prościutki kod:

using System;
using System.IO;
using System.Timers;

namespace DocumentWatcher
{
    class Program
    {
        static string filePath = @"D:\Users\Dawid\Pulpit\Dupa.docx";
        static Timer timer = new Timer(1000);

        static void Main(string[] args)
        {
            timer = new Timer(1000);
            timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
            timer.Enabled = true;

            Console.WriteLine("Naciśnij ENTER aby zakończyć");
            Console.ReadLine();
        }

        static void timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            try
            {
                using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None))
                {
                    Console.WriteLine("Plik wolny");
                }
            }
            catch (IOException)
            {
                Console.WriteLine("Plik zajęty");
            }
        }

    }
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1