【问题标题】:Outlook VSTO - MS Word - Normal Template Warning - Word Cannot Save the file because it is already open elsewhere (normal.dotm)Outlook VSTO - MS Word - 普通模板警告 - Word 无法保存文件,因为它已在其他地方打开 (normal.dotm)
【发布时间】:2019-04-20 21:35:34
【问题描述】:

我正在 Outlook 中开发一个 VSTO,它调用 MSWord 创建一个 word 文档,将其保存为 PDF,之后 VSTO 退出 word。我正在使用 VS2017 Professional 和 Office365 - MSWord 版本 16。

如果 MSWord 未打开 - 下面的代码就像一种享受。但是,如果 MSWord 已打开,我会收到警告 “Word 无法保存文件,因为它已在其他地方打开 (normal.dotm)”。现在我知道这已经被讨论了很多次,并且我已经尝试了我可以在 StackExchange 和其他地方找到的所有解决方案。之前通过引用this question 中的答案解决了这个问题,但自从最近更新了 Office365 后,同样的警告又回来了。

以下是我正在使用的代码的子集 - 所有文件名等都是有效的。

                // start word to create PDF file
                Word.Application wordApp = new Word.Application();
                Word.Document wrdDoc = new Word.Document();
                object saveOption = false; 
                //Word.WdSaveOptions.wdDoNotSaveChanges;
                object oMissing = Type.Missing;
                Word.Documents d = wordApp.Documents;

                try
                { 
                    // set the word app invisible
                    wordApp.Visible = false;
                    // open the document with the tmpfilename
                    wrdDoc = d.Open(FileNameIn, Visible: true);
                    //set the page size ...
                    //wrdDoc.PageSetup.PaperSize = Word.WdPaperSize.wdPaperA4;

                }
                catch (COMException es)
                {
                    throw (es);
                }

                try
                {
                    //Save/Export our document to a PDF
                    wrdDoc.ExportAsFixedFormat(OutputFileName: FileNameOut, ExportFormat: Word.WdExportFormat.wdExportFormatPDF,
                    OpenAfterExport: false, OptimizeFor: Word.WdExportOptimizeFor.wdExportOptimizeForPrint,
                    Range: Word.WdExportRange.wdExportAllDocument, From: 0, To: 0, Item: Word.WdExportItem.wdExportDocumentContent,
                    IncludeDocProps: true, KeepIRM: true, CreateBookmarks: Word.WdExportCreateBookmarks.wdExportCreateNoBookmarks,
                    DocStructureTags: true, BitmapMissingFonts: true, UseISO19005_1: false);

                    // trick our Word App into thinking that we have been saved
                    wordApp.NormalTemplate.Saved = true;

                }
                catch (COMException es)
                {
                    // there is an actual error reporting mechanism here
                    throw (es);
                }
                finally
                {
                    try
                    {
                       // make our document think its been saved
                       wrdDoc.Saved = true;
                       // close our document
                       wrdDoc.Close(ref saveOption, ref oMissing, ref oMissing);

                       // trick our Word App into thinking that we have been saved
                       wordApp.NormalTemplate.Saved = true;
                       wordApp.Quit(ref saveOption, ref oMissing, ref oMissing);
                       // release our document object
                       Marshal.ReleaseComObject(wrdDoc);
                       // release our documents object
                       Marshal.ReleaseComObject(d);
                       // release our application object
                       Marshal.ReleaseComObject(wordApp);

                    }
                    catch (Exception es)
                    {
                       // there is an actual error reporting mechanism here
                       throw (es);
                    }
                    finally
                    {
                        //
                    }
                }

我有义务为解决此问题提供任何和所有帮助。 提前谢谢了 DWE

【问题讨论】:

  • 现在不能尝试你的代码,但是为什么你有这行Word.Document wrdDoc = new Word.Document();?您稍后使用 d.Open() 覆盖 wrdDoc,我怀疑可能有一个新文档的处理实例潜伏在周围。尝试删除它,看看它是否对您有所改变。
  • Nick,使该更改在我目前正在使用的计算机上运行......但我们正在测试的代码也是如此......所以我将在计算机上尝试它明天它在哪里失败(我在澳大利亚)......你知道这段代码是否受到线程或多个监视器的影响?在工作环境中,我们使用两个监视器,代码在一个线程上运行......会有所作为吗?
  • 您必须仅从在 STA 中运行的一个线程中使用自动化。这就是 WinForms 和 WPF 的 UI 线程。永远不要在任务和其他线程中使用 Office 自动化!至于多显示器,我们在开发和生产中都有多个显示器设置的自动化 Word 用例。因此没有问题。
  • Nick,我检查了工作环境中的代码,但在相关机器(有两个显示器)上仍然失败,而在单显示器机器上没有失败;奇怪。此外,我可以确认代码在线程上运行时正在 STA 中运行。

标签: c# vsto outlook-addin


【解决方案1】:

好吧,在过去的几天里,关于我在上面寻求帮助的错误,我学到了很多东西。

我了解到,为了正确调试 Outlook 和/或 MSWord 的问题,应该卸载当前正在运行的所有第三方插件,然后尝试解决问题。在我的特殊情况下,我发现一个名为 Nuance Paperport 的程序有一个用于将 word 文档转换为 PDF 的插件,该插件会锁定 normal.dotm 模板,并且在要求 word 在代码中退出时不遵守规则。虽然对某些人来说可能微不足道,但对我来说却是宝贵的一课。

将 word 文档转换为 PDF 的代码如下,这是我目前决定使用的代码。

        /// <summary>
    /// A test to see if word is working
    /// this function takes a valid word document and converts it to a PDF 
    /// and takes the user to explorer with the converted file selected
    /// </summary>
    /// <param name="WordDocIn">a valid path\filename to an existing word document (doc, docx, rtf, htm, mhtml</param>
    /// <returns>returns False if there are no errors and the function completed successfully</returns>
    private bool WordToPDF(string WordDocIn)
    {
        // check and make sure our file parameter actually exists
        if(!File.Exists(WordDocIn))
        {
            MessageBox.Show("The file does not exist\n\n" + WordDocIn + "\n\n", "Office Assist: Error()", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return true; // true meaning there are errors
        }
        string tmpFilename = WordDocIn;
        // create a temp filename in temp directory
        string opFileName = GetTempFilePathWithExtension("pdf");
        // set our return value
        bool ErrorsPresent = false; // false meaning there are NO errors

        // create our word app
        Word.Application wordApp = new Word.Application();
        // get our documents collection (if any)
        Word.Documents d = wordApp.Documents;
        // create our new document
        Word.Document wrdDoc = new Word.Document();
        // create our word options
        object saveOption = false;// Word.WdSaveOptions.wdDoNotSaveChanges;
        // create our missing object
        object oMissing = Type.Missing; ;// Type.Missing;

        try
        {
            // set the word app visisble for the moment sp
            // we can see what we're doing
            wordApp.Visible = false;

            // suppress our alerts
            wordApp.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone;

            // we dont need any addins - unload all of our addins
            // need to open word with no addins loaded ... 
            wordApp.AddIns.Unload(true);   // True to remove the unloaded add-ins from the AddIns collection 
                                            // (the names are removed from the Templates and Add-ins dialog box). 
                                            // False to leave the unloaded add-ins in the collection.

            // open the document with the tmofilename
            wrdDoc = d.Open(tmpFilename, Visible: true);
            //set the page size ... to A4 (note this will throw an error if the default printer does not produce A4)
            wrdDoc.PageSetup.PaperSize = Word.WdPaperSize.wdPaperA4;

            //
            // export our document to a PDF
            //
            wrdDoc.ExportAsFixedFormat(OutputFileName: opFileName, ExportFormat: Word.WdExportFormat.wdExportFormatPDF,
            OpenAfterExport: false, OptimizeFor: Word.WdExportOptimizeFor.wdExportOptimizeForPrint,
            Range: Word.WdExportRange.wdExportAllDocument, From: 0, To: 0, Item: Word.WdExportItem.wdExportDocumentContent,
            IncludeDocProps: true, KeepIRM: true, CreateBookmarks: Word.WdExportCreateBookmarks.wdExportCreateNoBookmarks,
            DocStructureTags: true, BitmapMissingFonts: true, UseISO19005_1: false);

            // trick our Word App into thinking that the document has been saved
            wrdDoc.Saved = true;
            // close our word document
            wrdDoc.Close(ref saveOption, ref oMissing, ref oMissing);
            // close our documents collection
            //d.Close(ref saveOption, ref oMissing, ref oMissing);

            foreach (Word.Template template in wordApp.Templates)
            {
                switch (template.Name.ToLower())
                {
                    case "normal.dotm":
                        template.Saved = true;
                        break;
                }
            }
            // quit word
            wordApp.Quit(ref saveOption, ref oMissing, ref oMissing);
        }
        // catch our errors
        catch (COMException es)
        {
            string errcode = "ComException : " + es.Message + "\n\n" + "Show this message to your admin";
            MessageBox.Show("Check the default printer has the ability to print A4\nSelect a new printer and try again\n\n" + errcode, "Office Assist: Error()", MessageBoxButtons.OK, MessageBoxIcon.Error);
            ErrorsPresent = true;
            //throw (es);
        }
        catch (Exception es)
        {
            string errcode = "Exception : " + es.Message + " \n\n " + "Show this message to your admin";
            MessageBox.Show(errcode, "Office Assist: Error()", MessageBoxButtons.OK, MessageBoxIcon.Error);
            ErrorsPresent = true;
            //throw (es);
        }
        finally
        {
            try
            {
                // release our objects
                Marshal.ReleaseComObject(wrdDoc);
                Marshal.ReleaseComObject(d);
                Marshal.ReleaseComObject(wordApp);
            }
            catch (Exception es)
            {
                string errcode = "Exception : " + es.Message + " \n\n " + "Show this message to your admin";
                MessageBox.Show(errcode, "Office Assist: Error()", MessageBoxButtons.OK, MessageBoxIcon.Error);
                ErrorsPresent = true;
            }
        }


        // if there are no errors present
        // open explorer and select the pdf created
        //
        if (!ErrorsPresent)
        {
            // set our switches
            string argument = "/select, \"" + opFileName + "\"";
            // open explorer and select the file
            Process.Start("explorer.exe", argument);
        }

        return ErrorsPresent;
    }

考虑到我尝试解决此问题所花费的时间以及我看到的与将 word 文档转换为 PDF 以及与规范模板类似的性质或类似问题相关的帖子数量,我认为发表评论是合适的关于我所学到的知识并发布对我有用的代码,希望将来能对其他人有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-13
    • 2013-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-01
    • 1970-01-01
    相关资源
    最近更新 更多