L'Automatisation de Word - Fichier est utilisé par une autre application ou de l'utilisateur
J'ai une application WinForms où je suis à l'aide de l'Automatisation de Word pour créer des documents via un modèle, puis les enregistrer dans la base de données. Une fois le document créé, j'ai récupérer le document à partir de la base de données, l'écrire sur le système de fichiers dans un répertoire temporaire, puis ouvrez le document à l'aide de la Parole de l'Interopérabilité des services.
Il y a une liste de documents chargés et l'utilisateur peut ouvrir 1 seule instance de chaque document, mais peut ouvrir plusieurs documents simultanément. Je n'ai pas de problèmes avec l'ouverture, l'enregistrement et de clôture lors de l'ouverture 1 document, cependant, lors de l'ouverture simultanée de plusieurs documents, j'obtiens l'erreur suivante lors de la fermeture de l'un de mes instances de 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.
J'utilise le code suivant pour ouvrir le document et de gérer la BeforeDocumentClosed événement:
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);
}
}
Personne ne vois rien de mal que je fais à autoriser l'ouverture de plusieurs documents en même temps? Je suis assez nouveau à l'Automatisation de Word et la Parole de l'Interopérabilité des services, donc tout conseil est le bienvenue. Merci.
- Ne vous ouvrez directement le fichier verrouillé dans votre code (C:\...\Templates\Normal.dotm) ou est-ce accessible automatiquement? Si vous êtes l'un en l'ouvrant, vous pouvez créer une copie ou quelque chose comme ça pour éviter le blocage, ou d'essayer d'y accéder en lecture seule.
Vous devez vous connecter pour publier un commentaire.
J'ai trouvé la solution via cet article MSDN: http://support.microsoft.com/kb/285885
Vous devez le faire avant d'appeler l'Application.Quit();
Cela empêche Word d'essayer de sauver la Normale.dotm modèle. J'espère que cela aide quelqu'un d'autre.
J'ai utilisé le Mot en C# doc2pdf application. Avant de fermer doc, définissez l'option enregistrer comme ceci:
J'ai de l'aide des liens dans mon application et je voulais ouvrir un doc word à un signet. Si le document est déjà ouvert, il ne faut pas l'ouvrir à nouveau. Si le Mot est déjà ouvert, il ne doit pas ouvrir une nouvelle instance de Word.
Ce code a fonctionné pour moi:
Garder à l'esprit que le code:
toujours tourner une nouvelle instance de Word, même si il y a déjà une instance chargée.
Habituellement, vous êtes mieux de vérification pour une instance chargée (via la fonction GETOBJECT) et de l'utiliser si il y en a un, et seulement tourner une nouvelle instance, si vous en avez besoin.