我正在用C#编写一个小型WinForms GUI实用程序。它获取用户工作站上的Access97 mdb文件,从中读取一些数据,将mdb文件转换为较新的accdb文件,使用在旧文件中找到的数据形成新文件名的一部分,然后将生成的文件复制到局域网上的共享文件夹。
我用C#方法Microsoft创建了一个Access对象,成功地实现了这一点。办公室Interop。通道Application(),然后使用必要的参数调用ConvertAccessProject()。它一开始完全按照我的意愿工作。
然后它开始抛出一个系统。运行时。InteropServices。COMException with HRESULT:0x80080005(CO_E_SERVER_EXEC_FAILURE)。一旦我尝试创建Access对象,就会出现这种情况。它与我的文件或它们的格式无关。代码从未从COM服务器获得Access对象,因此,它从未达到查询或转换的阶段。三天来,我一直在努力解决这个问题。
一个小背景:在我第一次使用这个实用程序后,我遇到了一个SSIS模块的问题,这个模块是我在同一项目中构建的。它在使用Visual Studio中的Microsoft Jet 4.0驱动程序连接新文件时遇到问题(或者使用任何其他类型的驱动程序连接任何Access文件)。因此,根据建议,我尝试安装Access 2007的驱动程序更新并切换到ACE。SSIS项目中的OLEDB驱动程序。我不确定是什么导致了我现在的问题。卸载和重新安装Access 2007驱动程序似乎不会改变我在C#代码中创建Access对象时的行为。
从我在各种论坛上看到的情况来看,我遇到的问题类型是地方性的,显然可能是由一组无法确定大小的机器状态引起的。因此,对我来说,期望有人发布一个直接的、循序渐进的程序来解决我的问题可能是不现实的——尽管我仍然愿意接受建议。缺少";银色子弹";修复,我想找到深入、权威的资源,在那里我可以学会如何独自了解引擎盖下发生的事情,而不必盲目地搜索其他人的建议,然后"试试这个,试试那个";,希望其中一个建议恰好奏效。
我知道有像cdomcnfg和procmon这样的实用程序可以深入了解正在发生的事情。我发现关于如何使用它们的公开信息很少。我对DCOM/ATL有一个基本的理解,尽管它相当抽象。除了参加微软认证培训,对我来说,最好的自学方法是什么?如果有一本关于DCOM、注册表、Interop之间交互的杀手级书籍。Net,以及整个32位与64位的混乱,我会买下它
跟进#0有些事情我根本不明白。在该主题的大多数其他讨论中,建议(通常是有效的解决方案)集中在进入dcomcnfg,打开控制台根目录|Computers|My Computer|DCOM Config|Microsoft{适用的Office应用程序},并在适用的DCOM服务器上设置各种属性,通常是与安全或标识相关的属性。在我的情况下,分支中没有用于Microsoft Access的DCOM服务器。也不适用于Excel、Word、Outlook或任何Office应用程序。应该有吗?在我家的机器上,我的Access文件转换器工作得很好,而且在那台机器上的dcomcnfg中也没有可用的Microsoft Access DCOM服务器。
我假设创建Access应用程序实例的功能最终驻留在某个dll中的老式COM对象中。如果这个功能可以在没有注册DCOM服务器的情况下工作,那么DCOM或dcomcnfg有什么好处?做Net调用DCOM来访问dll,或者它使用了其他东西,比如。Net/COM互操作?是否存在某种";interopcnfg";实用程序,我可以用来尝试看看它在做什么?如果我安装Access 2016可再发行版,它会允许我创建一个Microsoft实例吗。办公室Interop。Access对象,或者我可以用来从中读取数据并转换Access文件的文件格式的其他东西?如果是,那么我是否必须在每个用户的机器上手动安装Access 2016可再发行文件,或者我可以将其包含在解决方案的构建中?
following#1我在这里找到了一些感兴趣的东西。它指出;如果您使用的是.Net Framework中的Office Interop,那么您实际上是通过Office Interop工具中包含的代理调用DCOM服务器"是的,我正在使用.Net Framework来构建我的WinForms应用程序。因此,我使用DCOM服务器进行访问。在这种情况下,当两台计算机上都没有用于访问的DCOM服务器时,这个东西是如何工作的,现在它在我的家用计算机上是如何工作?哦,我也检查了CLSID,但它也不在那里。。。
FOLLOWUP#2引发异常的最小代码如下:
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var app = new Microsoft.Office.Interop.Access.Application();
}
}
}
FOLLOWUP#3我在事件日志中发现的内容很难解释。从控制台运行我编译的示例代码会导致两个事件,间隔约0.1秒。第一个来源是.Net Runtime:
- EventData
Application: TestOfficeInterop.exe CoreCLR Version: 4.700.21.56803 .NET Core Version: 3.1.22 Description: The process was terminated due to an unhandled exception. Exception Info: System.IO.FileNotFoundException: Could not load file or assembly 'office, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c'. The system cannot find the file specified. File name: 'office, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' at TestOfficeInterop.Program.Main(String[] args)
第二个来源是应用程序错误:
- EventData
TestOfficeInterop.exe
1.0.0.0
619ae151
KERNELBASE.dll
10.0.19041.1466
e01c7650
e0434352
0000000000034f69
3fdc
01d80aed605afc3f
F:TestOfficeInteropTestOfficeInteropbinDebug
netcoreapp3.1TestOfficeInterop.exe
C:WINDOWSSystem32KERNELBASE.dll e380ef6d-79ae-4f02-939b-26a0f3e6fcf0
总的来说,我不确定这些信息中有什么比转储到我的控制台中的信息更有用:
F:TestOfficeInteropTestOfficeInteropbinDebugnetcoreapp3.1>.TestOfficeInterop.exe
Unhandled exception. System.IO.FileNotFoundException: Could not load file or assembly 'office, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c'. The system cannot find the file specified.
File name: 'office, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c'
在TestOfficeInterop.Program.Main(String[]args)
我注意到procmon中有一些看起来很有趣的东西,但我不确定。运行我的示例代码会导致此文件被读取:
C:ProgramDataMicrosoftNetFrameworkBreadcrumbStorenetcore,Microsoft.Office.Interop.Access,15.0.4420.1017
请注意指定的版本。这只是数百个文件访问中的一个例子,这些文件访问都指定了相同的版本号。
但我被丢弃到我的终端上的信息表明,找不到一个文件:
'office, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c'
版本15.0.0.0??
怎么了?
然后它开始抛出System.Runtime.InteropServices.COMException,HRESULT:0x80080005(CO_E_SERVER_EXEC_FAILURE)。
这通常表示您在服务器端或从任何无人参与的应用程序运行Office应用程序。
所有当前版本的Microsoft Office都经过设计、测试和配置,可以作为最终用户产品在客户端工作站上运行。它们采用交互式桌面和用户配置文件。它们没有提供必要的可重入性或安全性级别,以满足设计为无人值守运行的服务器端组件的需求。
Microsoft目前不建议也不支持从任何无人参与的非交互式客户端应用程序或组件(包括ASP、ASP.NET、DCOM和NT服务)自动化Microsoft Office应用程序,因为在这种环境中运行Office时,Office可能会表现出不稳定的行为和/或死锁。请参阅"Office服务器端自动化的注意事项"一文中的更多内容。
您也可能会发现类似的帖子很有帮助-服务器执行失败(HRESULT中的异常:0x80080005(CO_E_Server_EXEC_FAILURE))。
好吧,我最终还是屈服了。我运行了Office Repair实用程序,不知怎么的,发生了一些深层的黑暗魔法,现在我又开始运行了。或者至少,我会一直呆到下一次这个东西停止工作。。。
我的防御编码计划是,当FileNotFoundException发生时,我会捕捉到它,向用户报告他们(显然)需要运行Office修复实用程序,并显示执行此操作的说明。我还将编码一个";回退";如果发生异常,我将向用户提供实用程序作为一种替代方案。如果用户无法或不愿意执行Office修复,他们可以使用此实用程序将数据加载到SSIS中,尽管这一过程不可避免地会比我希望的全功能实用程序用户友好得多,也更容易出错。
我有点失望,因为我无法确定问题出在哪里。似乎每次我为Windows编写软件时,我都会花更多的时间来处理这种愚蠢的行为,而不是实际生成软件。考虑到Windows生态系统的大部分基本上都是一片破碎、笨重、脆弱的界面海洋,这些界面生活在用数字管道胶带固定在一起的黑盒子里,我更希望能够系统地深入到任何问题的根本原因,就像*nix和开源人士习惯的那样。
尽管如此,这并不是完全浪费时间。我确实以一些重要而有用的方式扩展了我的知识,这是我在这里寻求帮助的主要原因@user9938、@SimonMourier和@Charileface,我非常感谢您的宝贵意见!