Word Automation - файл используется другим приложением или пользователем - PullRequest
6 голосов
/ 06 декабря 2010

У меня есть приложение WinForms, в котором я использую Word Automation для создания документов с помощью шаблона, а затем сохраняю их в базе данных. После создания документа я извлекаю документ из базы данных, записываю его в файловую систему во временном каталоге, а затем открываю документ с помощью служб Word Interop.

Существует список загруженных документов, и пользователь может открыть только 1 экземпляр каждого документа, но может одновременно открыть несколько разных документов. У меня нет проблем с открытием, сохранением и закрытием, когда они открывают 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 ]

9 голосов
/ 06 декабря 2010

Я нашел решение с помощью этой статьи MSDN: http://support.microsoft.com/kb/285885

Это необходимо сделать перед вызовом Application.Quit ();

_wordApplication.NormalTemplate.Saved = true;

Это не позволяет Word пытаться сохранитьшаблон Normal.dotm.Я надеюсь, что это поможет кому-то еще.

2 голосов
/ 29 июня 2012

Я использовал Word в приложении C # doc2pdf.Перед закрытием документа установите опцию сохранения следующим образом:

object saveOption = Microsoft.Office.Interop.Word.WdSaveOptions.wdDoNotSaveChanges;
oDoc.Close(ref saveOption, ref oMissing, ref oMissing);
oWord.Quit(ref saveOption, ref oMissing, ref oMissing);
1 голос
/ 16 августа 2013

У меня есть справочные ссылки в моем приложении, и я хотел открыть определенное слово doc для определенной закладки.Если документ уже открыт, он не должен открывать его снова.Если 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();
}
0 голосов
/ 06 декабря 2010

Имейте ввиду, что код:

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

всегда будет запускать новый экземпляр Word, даже если экземпляр уже загружен.

Обычно вам лучше проверить загруженный экземпляр (через GETOBJECT) и использовать его, если он есть, и только раскрутить новый экземпляр, если вам нужно.

...