I'm writing a small WinForms GUI utility in C#. It grabs an Access97 mdb file on the user's workstation, reads some data from it, converts the mdb file into a newer accdb file, uses the data it found in the old file to form part of the new file's name, and then copies the resulting file to a shared folder on the LAN.
I successfully implemented this by creating an Access object with the C# method Microsoft.Office.Interop.Access.Application(), and then calling ConvertAccessProject() with the necessary arguments. It started out working exactly as I wanted.
Then it started throwing a System.Runtime.InteropServices.COMException with HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE). This occurs as soon as I try to create the Access object. It has nothing to do with my files or their formats. The code never obtains an Access object from the COM server, and so, it never reaches the stage of querying or conversion. For three days, I've been trying to fix this.
A little background: After first I got this utility working, I ran into a problem with an SSIS module I'm building as part of the same project. It was having trouble using the Microsoft Jet 4.0 driver from Visual Studio to connect with the new file (or any other type of driver to connect to any Access file, for that matter). So, on a suggestion, I tried installing the driver update for Access 2007 and switching to the ACE.OLEDB driver in my SSIS project. I'm not sure that caused my current problem. Un-installing and re-installing the Access 2007 driver doesn't seem to change the behavior I get when I try to create an Access object in C# code.
From what I read in the various forums, the type of problem I'm having is endemic, and could be caused by, apparently, a set of machine states whose size is impossible to determine. As such, it might not be realistic for me to expect someone to post a direct, step-by-step procedure for fixing my problem that has a significant chance of working—-although I am still open to suggestions. Lacking a "silver bullet" fix, I would like pointers to in-depth, authoritative resources where I can learn how to figure what is happening under the hood on my own, without having to just blindly google other people's suggestions, and then "try this, and try that", hoping that one of the suggestions just so happens to work.
I know there are utilities like cdomcnfg and procmon that can give insight as to what is going on. I have found little public information on how to use them. I have a basic understanding of DCOM/ATL, although it's rather abstract. Other than taking Microsoft Certification training, what would be the best approach for me to educate myself? If there's a killer book out there on the interactions between DCOM, the registry, Interop, .Net, and the whole 32-bit versus 64-bit mess, I'll buy it.
FOLLOWUP #0 There is something I do not understand at all. In most other discussions of this topic, the suggestions (which are often effective solutions) center on going into dcomcnfg, opening Console root | Computers | My Computer | DCOM Config | Microsoft {applicable Office application}, and setting various properties on the applicable DCOM server--usually properties related to security or identity. In my case, there is no DCOM server for Microsoft Access in the branch. Nor for Excel, Word, Outlook, or any Office application. Is there supposed to be? On my machine at home, my Access file converter works just fine, and there is no Microsoft Access DCOM server available in dcomcnfg on that machine, either.
I'm assuming that the functionality of creating an instance of an Access Application ultimately resides in an old-school COM object housed in a dll somewhere. If it is possible for this functionality to work with no registered DCOM server, then what's the benefit of DCOM or dcomcnfg? Does .Net call into DCOM to access the dll, or does it use something else, like .Net/COM Interop? Is there some sort of an "interopcnfg" utility I can use to try to see what it's doing? If I install the Access 2016 redistributable, will it allow me to create an instance of a Microsoft.Office.Interop.Access object, or something else I can use to read data from and convert the file format of Access files? If yes, then will I have to manually install the Access 2016 redistributable on each user's machine, or can I just include it in the solution's build?
FOLLOWUP #1 I found something of interest Here. It states that "If you are using Office Interop from .Net Framework, then you are actually invoking a DCOM server through proxies included in the Office Interop tools." Yes, I am using .Net Framework to build my WinForms app. So then, I'm using a DCOM Server for Access. In that case, how did this thing ever work, and how is it working right now on my home computer, when there is no DCOM Server for Access on either machine? Oh, and I checked the CLSIDs, too, and it wasn't in there, either...
FOLOLOWUP #2 The minimal code to raise the Exception is as follows:
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var app = new Microsoft.Office.Interop.Access.Application();
}
}
}
FOLLOWUP #3 What I found in the Event Log was hard to interpret. Running my compiled sample code from the console results in two events, spaced about 0.1 seconds apart. The first one's source is .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)
The second one's source is Application Error:
- EventData
TestOfficeInterop.exe
1.0.0.0
619ae151
KERNELBASE.dll
10.0.19041.1466
e01c7650
e0434352
0000000000034f69
3fdc
01d80aed605afc3f
F:\TestOfficeInterop\TestOfficeInterop\bin\Debug\
netcoreapp3.1\TestOfficeInterop.exe
C:\WINDOWS\System32\KERNELBASE.dll e380ef6d-79ae-4f02-939b-26a0f3e6fcf0
Overall, I'm not sure how any of this information is more useful than what gets dumped out into my console:
F:\TestOfficeInterop\TestOfficeInterop\bin\Debug\netcoreapp3.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'
at TestOfficeInterop.Program.Main(String[] args)
I noticed something in procmon that looks interesting, but I'm not sure. Running my sample code results in this file being read:
C:\ProgramData\Microsoft\NetFramework\BreadcrumbStore\netcore,Microsoft.Office.Interop.Access,15.0.4420.1017
Notice the version specified. This is only one example of hundreds of file accesses that all specify the same version number.
But what I get dumped out into my terminal says that a file could not be found:
'office, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c'
Version 15.0.0.0 ??
What's up with that?