6

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

加载了一个文档列表,用户只能打开每个文档的一个实例,但可以同时打开多个不同的文档。当他们打开 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 服务还很陌生,因此我很感激任何建议。谢谢。

4

4 回答 4

9

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

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

_wordApplication.NormalTemplate.Saved = true;

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

于 2010-12-06T14:41:50.193 回答
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);
于 2012-06-29T02:16:38.030 回答
1

我的应用程序中有帮助链接,并且想打开一个特定的单词文档到一个特定的书签。如果文档已经打开,则不应再次打开它。如果 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();
}
于 2013-08-16T05:11:57.183 回答
0

请记住,代码:

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

将始终启动一个新的 Word 实例,即使已经加载了一个实例。

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

于 2010-12-06T20:52:47.717 回答