2017-10-30 18 views
1

Ich mache mehrere Dinge mit einem Word-Dokument im Hintergrund und manchmal, wenn die App fehlschlägt, wird eine Instanz von MS Word im Hintergrund ausgeführt. Beim Neustart versucht es, die gleiche Datei zu öffnen, und es gibt einen Strom von Problemen im Zusammenhang damit.Überprüfen Sie, ob das Word-Dokument bereits geöffnet ist, bevor Sie es in C# öffnen

Ich würde gerne verstehen (konnte hier keine passende Antwort finden), wie man überprüft, ob die Datei, die ich öffnen möchte, bereits geöffnet ist.

Mein Code:

Microsoft.Office.Interop.Word.Application wordApp = new Microsoft.Office.Interop.Word.Application(); 
Document wordDoc = new Document(); 
wordDoc = wordApp.Documents.Open(ref oTemplatePath, ref oMissing, ref oMissing, ref oMissing); 
wordApp.Visible = false; 

Wie kann ich für die Datei, bevor wordApp.Documents.Open Ausführung ist bereits geöffnet überprüfen?

Danke!

+0

stand ich ein ähnliches Problem mit dem Excel-Interop-API, wo, wenn Sie COM-Objekte nicht richtig loslassen, wird die App einfach weiter ohne Fenster läuft auch nach Sie rufen die 'Quit()' - Methode auf. Anstatt zu überprüfen, ob das Dokument bereits geöffnet ist, sollten Sie sicherstellen, dass Word von vornherein korrekt angeordnet wird. [Probieren Sie diesen Thread aus] (https://stackoverflow.com/questions/6777422/disposing-of-microsoft-office-interop-word-application), ist die Wahrscheinlichkeit groß, dass dies der Fall ist – Nik

+0

Kann nicht gesucht werden, wenn die Datei geöffnet ist oder System.IO nicht verwendet wird. https://stackoverflow.com/questions/876473/is-there-a-way-to-check-if-a-file-isin-use#answer-937558 –

+0

Tha Nik Nik. Das mache ich schon, wenn die App fertig ist. Es gibt einige Umstände, unter denen es fehlschlagen kann und diese Instanz ausgeführt wird. Ich möchte das gerne beenden, aber wenn die App erneut ausgeführt wird, wird eine ganz neue Instanz erstellt. Ich vermute, dass die eigentliche Frage "Wie töte ich eine bestehende Version von MS Word, die im Hintergrund läuft" sein sollte? –

Antwort

0

Sie können versuchen, die Datei zu öffnen, wenn die Datei bereits geöffnet ist IOException geworfen werden und zeigen an, dass die Datei geöffnet ist:

public bool fileIsOpen(string path) 
{ 
    System.IO.FileStream a = null; 

    try 
    { 
     a = System.IO.File.Open(path, 
     System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.None); 
     return false; 
    } 
    catch (System.IO.IOException ex) 
    { 
     return true; 
    } 

    finally 
    { 
     if (a != null) 
     { 
      a.Close(); 
      a.Dispose(); 
     } 
    } 
} 
1

Sie können alle Fenster Wort aufzuzählen und versuchen Sie eine mit dem finden Dokument. Wenn Sie versuchen, diese Datei zu öffnen, während sie in Word geöffnet ist, erhalten Sie IOException. Aber es ist nicht perfekte Lösung :( Hier Lösung:

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Runtime.InteropServices; 
using System.Text; 

namespace WordExampleApp 
{ 
    class Program 
    { 
     const int ERROR_SHARING_VIOLATION = -2147024864; 
     static readonly string WORD_CLASS_NAME = "OpusApp"; 
     static readonly string WORD_DOCUMENT_CLASS_NAME = "_WwB"; 

     delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter); 

     static void Main(string[] args) 
     { 
      // Path to exist word document 
      string filePath = @"C:\temp\asdasd.docx"; 

      string documentName = Path.GetFileNameWithoutExtension(filePath); 
      var isDocOpened = IsDocumentOpened(documentName); 
      Console.WriteLine("Is document opened: {0}", isDocOpened); 

      bool canRead = CanReadFile(filePath); 
      Console.WriteLine("Can read file: {0}", canRead); 
     } 
     private static bool CanReadFile(string path) 
     { 
      try { 
       using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None)) { } 
       return true; 
      } 
      catch (IOException ex) { 
       if (ex.HResult == ERROR_SHARING_VIOLATION) 
        return false; 
       else throw; 
      } 
     } 

     private static bool IsDocumentOpened(string documentName) 
     { 
      IntPtr hwnd = FindWindow(WORD_CLASS_NAME, documentName + " - Word"); 
      List<IntPtr> childs = GetChildWindows(hwnd); 
      var classText = new StringBuilder("", 1024); 
      var windowText = new StringBuilder("", 1024); 

      foreach (var childHwnd in childs) 
      { 
       if (0 == GetClassName(childHwnd, classText, 1024)) { 
        // something wrong 
       } 
       if (0 == GetWindowText(childHwnd, windowText, 1024)) { 
        // something wrong 
       } 
       var className = classText.ToString(); 
       var windowName = windowText.ToString(); 
       if (className == WORD_DOCUMENT_CLASS_NAME && windowName == documentName) 
        return true; 

       classText.Clear(); 
       windowText.Clear(); 
      } 
      return false; 
     } 
     public static List<IntPtr> GetChildWindows(IntPtr parent) 
     { 
      List<IntPtr> result = new List<IntPtr>(); 
      GCHandle gcHandle = GCHandle.Alloc(result); 
      try { 
       EnumWindowProc childProc = new EnumWindowProc(EnumWindow); 
       EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(gcHandle)); 
      } 
      finally { 
       if (gcHandle.IsAllocated) 
        gcHandle.Free(); 
      } 
      return result; 
     } 
     private static bool EnumWindow(IntPtr handle, IntPtr pointer) 
     { 
      GCHandle gch = GCHandle.FromIntPtr(pointer); 
      List<IntPtr> list = gch.Target as List<IntPtr>; 
      if (list == null) 
       throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>"); 
      list.Add(handle); 
      return true; 
     } 

     [DllImport("user32", ExactSpelling = false, CharSet = CharSet.Auto)] 
     internal static extern IntPtr FindWindow(string lpClassName, string lpWindowName); 

     [DllImport("user32.dll")] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowProc lpEnumFunc, IntPtr lParam); 

     [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
     static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); 

     [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
     public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpWindowText, int nMaxCount); 
    } 
} 
Verwandte Themen