【问题标题】:Word Automation - File is in use by another application or userWord 自动化 - 文件正被其他应用程序或用户使用
【发布时间】:2023-03-15 10:32:01
【问题描述】:

我有一个 WinForms 应用程序,我在其中使用 Word 自动化通过模板构建文档,然后将它们保存到数据库中。创建文档后,我从数据库中检索文档,将其写入临时目录中的文件系统,然后使用 Word 互操作服务打开文档。

有一个加载的文档列表,用户只能打开每个文档的一个实例,但可以同时打开多个不同的文档。当他们打开 1 个文档时,我在打开、保存和关闭时没有任何问题,但是,当他们同时打开多个文档时,我在关闭我的任何 Word 实例时收到以下错误:

The file is in use by another application or user. (C:\...\Templates\Normal.dotm) 
This error is commonly encountered when a read lock is set on the file that you are attempting to open.

我正在使用以下代码打开文档并处理 BeforeDocumentClosed 事件:

public void OpenDocument(string filePath, Protocol protocol, string docTitle, byte[] document)
{
    _protocol = protocol;
    documentTitle = docTitle;
    _path = filePath;

    if (!_wordDocuments.ContainsKey(_path))
    {
        FileUtility.WriteToFileSystem(filePath, document);

        Word.Application wordApplication = new Word.Application();
        wordApplication.DocumentBeforeClose += WordApplicationDocumentBeforeClose;

        wordApplication.Documents.Open(_path);

        _wordDocuments.Add(_path, wordApplication);
    }
    _wordApplication = _wordDocuments[_path];
    _currentWordDocument = _wordApplication.ActiveDocument;

    ShowWordApplication();
}

public void ShowWordApplication()
{
    if (_wordApplication != null)
    {
        _wordApplication.Visible = true;
        _wordApplication.Activate();
        _wordApplication.ActiveWindow.SetFocus();
    }
}

private void WordApplicationDocumentBeforeClose(Document doc, ref bool cancel)
{
    if (!_currentWordDocument.Saved)
    {
        DialogResult dr = MessageHandler.ShowConfirmationYnc(String.Format(Strings.DocumentNotSavedMsg, _documentTitle), Strings.DocumentNotSavedCaption);

        switch (dr)
        {
            case DialogResult.Yes:
                SaveDocument(_path);
                break;
            case DialogResult.Cancel:
                cancel = true;
                return;
        }
    }

    try
    {
        if (_currentWordDocument != null)
            _currentWordDocument.Close();
    }
    finally
    {
        Cleanup();
    }
}

public void Cleanup()
{
    if (_currentWordDocument != null)
        while(Marshal.ReleaseComObject(_currentWordDocument) > 0);

    if (_wordApplication != null)
    {
        _wordApplication.Quit();
        while (Marshal.ReleaseComObject(_wordApplication) > 0);
        _wordDocuments.Remove(_path);
    }
}

是否有人发现我在允许同时打开多个文档时做错了什么?我对 Word Automation 和 Word Interop 服务还很陌生,所以我很感激任何建议。谢谢。

【问题讨论】:

  • 您是直接在代码中打开锁定的文件(C:\...\Templates\Normal.dotm)还是自动访问?如果你是打开它的人,你可以创建一个副本或类似的东西来避免锁定,或者尝试以只读方式访问它。

标签: c# .net winforms ms-word word-automation


【解决方案1】:

我通过这篇 MSDN 文章找到了解决方案:http://support.microsoft.com/kb/285885

您需要在调用 Application.Quit(); 之前执行此操作

_wordApplication.NormalTemplate.Saved = true;

这会阻止 Word 尝试保存 Normal.dotm 模板。我希望这对其他人有帮助。

【讨论】:

  • 你应该接受你自己的答案,我知道这听起来很奇怪,但却是正确的做法
  • 不幸的是,我必须等待几天才能让我这样做。
【解决方案2】:

我在 C# doc2pdf 应用程序中使用过 Word。在关闭文档之前,请像这样设置保存选项:

object saveOption = Microsoft.Office.Interop.Word.WdSaveOptions.wdDoNotSaveChanges;
oDoc.Close(ref saveOption, ref oMissing, ref oMissing);
oWord.Quit(ref saveOption, ref oMissing, ref oMissing);

【讨论】:

    【解决方案3】:

    我的应用程序中有帮助链接,我想打开一个特定的 word 文档到一个特定的书签。如果文档已经打开,则不应再次打开它。如果 Word 已打开,则不应打开 Word 的新实例。

    这段代码对我有用:

    object filename = @"C:\Documents and Settings\blah\My Documents\chapters.docx";
    object confirmConversions = false;
    object readOnly = true;
    object visible = true;
    object missing = Type.Missing;
    Application wordApp;
    
    object word;
    try
    {
        word = System.Runtime.InteropServices.Marshal.GetActiveObject("Word.Application");
    }
    catch (COMException)
    {
        Type type = Type.GetTypeFromProgID("Word.Application");
        word = System.Activator.CreateInstance(type);
    }
    
    wordApp = (Application) word;
    wordApp.Visible = true;
    Console.WriteLine("There are {0} documents open.", wordApp.Documents.Count);
    var wordDoc = wordApp.Documents.Open(ref filename, ref confirmConversions, ref readOnly, ref missing,
                                            ref missing, ref missing, ref missing, ref missing,
                                            ref missing, ref missing, ref missing, ref visible,
                                            ref missing, ref missing, ref missing, ref missing);
    wordApp.Activate(); 
    object bookmarkName = "Chapter2";
    if (wordDoc.Bookmarks.Exists(bookmarkName.ToString()))
    {
        var bookmark = wordDoc.Bookmarks.get_Item(bookmarkName);
        bookmark.Select();
    }
    

    【讨论】:

      【解决方案4】:

      记住代码:

      Word.Application wordApplication = new Word.Application();
      

      总是会启动一个新的 Word 实例,即使已经加载了一个实例。

      通常,您最好检查已加载的实例(通过 GETOBJECT)并在有实例时使用它,并且仅在需要时启动一个新实例。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-06-11
        • 2011-07-22
        • 2012-05-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多