【Azure App Service】使用Microsoft.Office.Interop.Word来操作Word文档,部署到App Service后报错COMException
问题描述
在.NET项目中,使用Microsoft.Office.Interop.Word组件来操作Word文档,使用了Microsoft.Office.Interop.Word.Document对象中的Open和SaveAs方法。
##打开文件
doc = app.Documents.Open(ref inputFile, ref nullobj, ref nullobj, ref nullobj, ref nullobj,ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj,ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj);
##保存文件,关闭文件
doc.SaveAs(ref outputFile, ref nullobj, ref nullobj, ref nullobj, ref nullobj,ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj,ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj);
doc.Close(ref nullobj, ref nullobj, ref nullobj);
但是,在部署到App Service后,遇到 “System.Runtime.InteropServices.COMException (0x80040154): Retrieving the COM class factory for component with CLSID {000209FF-0000-0000-C000-000000000046} failed due to the following error: 80040154 Class not registered (0x80040154 (REGDB_E_CLASSNOTREG)).“ 错误。
完整的错误信息为:
System.Runtime.InteropServices.COMException (0x80040154): Retrieving the COM class factory for component with CLSID {000209FF-0000-0000-C000-000000000046} failed due to the following error: 80040154 Class not registered (0x80040154 (REGDB_E_CLASSNOTREG)).
at Services.Api.Controllers.v1.FileoOerationController.GetFileBasedOnTemplates() in D:\FileOperationController.cs:line 328
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
报错截图:
问题解答
Azure App Service 不支持Microsoft.Office.Interop,该扩展需要依赖本地安装的Office, App Service为Sandbox环境,无法安装Office。
替代方案是使用 Open-XML-SDK 来操作 Word 文档。
using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Wordprocessing; using System; OpenAndAddTextToWordDocument(args[0], args[1]); static void OpenAndAddTextToWordDocument(string filepath, string txt) { // Open a WordprocessingDocument for editing using the filepath. WordprocessingDocument wordprocessingDocument = WordprocessingDocument.Open(filepath, true); if (wordprocessingDocument is null) { throw new ArgumentNullException(nameof(wordprocessingDocument)); } // Assign a reference to the existing document body. MainDocumentPart mainDocumentPart = wordprocessingDocument.MainDocumentPart ?? wordprocessingDocument.AddMainDocumentPart(); mainDocumentPart.Document ??= new Document(); mainDocumentPart.Document.Body ??= mainDocumentPart.Document.AppendChild(new Body()); Body body = wordprocessingDocument.MainDocumentPart!.Document!.Body!; // Add new text. Paragraph para = body.AppendChild(new Paragraph()); Run run = para.AppendChild(new Run()); run.AppendChild(new Text(txt)); // Dispose the handle explicitly. wordprocessingDocument.Dispose(); }
(Open and add text to a word processing document : https://learn.microsoft.com/en-us/office/open-xml/word/how-to-open-and-add-text-to-a-word-processing-document?tabs=cs-0%2Ccs-1%2Ccs-2%2Ccs-3%2Ccs )
附录:使用Microsoft.Office.Interop操作Word的代码
Microsoft.Office.Interop.Word.Application app = new Microsoft.Office.Interop.Word.Application(); Microsoft.Office.Interop.Word.Document doc = null; string inputFilePath = ".\\testfile1.docx"; string outputFilePath = ".\\testfile1.docx"; object nullobj = Type.Missing; object inputFile = inputFilePath; object outputFile = outputFilePath; object oStory = WdUnits.wdStory; object oMove = WdMovementType.wdMove; Dictionary<string, string> datas = new Dictionary<string, string>(); datas["name"] = "namexxxxxxxxx"; datas["code"] = "codexxxxxxxxxx"; app.Visible = false; app.DisplayAlerts = WdAlertLevel.wdAlertsNone; doc = app.Documents.Open(ref inputFile, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj); object objReplace = Microsoft.Office.Interop.Word.WdReplace.wdReplaceAll; app.Selection.HomeKey(ref oStory, ref oMove); app.Options.ReplaceSelection = true; foreach (var item in datas) { app.Selection.Find.ClearFormatting(); app.Selection.Find.Replacement.ClearFormatting(); string oldStr = item.Key; string newStr = item.Value; if (newStr == null) { newStr = ""; } app.Selection.Find.Text = oldStr; app.Selection.Find.Replacement.Text = newStr; app.Selection.Find.Execute(ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref objReplace, ref nullobj, ref nullobj, ref nullobj, ref nullobj); } doc.SaveAs(ref outputFile, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj); if (doc != null) { doc.Close(ref nullobj, ref nullobj, ref nullobj); doc = null; } if (app != null) { app.Quit(ref nullobj, ref nullobj, ref nullobj); app = null; }
参考资料
Can we use Microsoft.Office.Interop.excel.dll in Azure funtions? https://stackoverflow.com/questions/51552404/can-we-use-microsoft-office-interop-excel-dll-in-azure-funtions
App Service Sandbox: https://github.com/projectkudu/kudu/wiki/Azure-Web-App-sandbox
Open and add text to a word processing document : https://learn.microsoft.com/en-us/office/open-xml/word/how-to-open-and-add-text-to-a-word-processing-document?tabs=cs-0%2Ccs-1%2Ccs-2%2Ccs-3%2Ccs
?? 和 ??= 运算符 - Null 合并操作符: https://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/operators/null-coalescing-operator
当在复杂的环境中面临问题,格物之道需:浊而静之徐清,安以动之徐生。 云中,恰是如此!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2022-11-05 【Azure 环境】把OpenSSL生产的自签名证书导入到Azure Key Vault Certificate中报错
2020-11-05 【Azure 环境】存储在Azure上的文件,使用IE/Edge时自动打开的问题,如何变为下载而非自动打开
2020-11-05 【Azure 环境】各种语言版本或命令,发送HTTP/HTTPS的请求合集