This is quite a long story so let me begin with what my goal is here:
The company I work for has its own reporting software which generates reports in MS Excel, this is done using C# and the normal Excel interop (powered by the Excel COM interface). Recently, a client of ours asked if we could implement a setting to choose what Excel version the program uses to generate reports and this sent me down a massive rabbit hole...
I have spent the last three days reading up on this so I think I understand the issue fairly well by now: all Excel versions use the very same CLSID for their COM Object. Therefore, I am unable to create a specific version of it.
What I've tried:
I have seen people spinning up an Excel process of the required version manually and then iterating through all of its windows to find a specific one that provides a COM Object. I have implemented this as a proof of concept already but it's honestly kind of janky (especially with newer versions of Excel) and I would like to use something a little more robust. Ideally, I would like to just use COM and it's internal mechanisms to spin up an Excel instance.
After reading up on COM I figured out how it decides which instance of Excel to start up when an object is requested:
HKCR\Classes\CLSID\{00024500-0000-0000-C000-000000000046}\LocalServer32
just contains a path to the executable.
(From poking around with Sysinternals ProcessMonitor it seems like it also checks HKCU\Software\Classes\CLSID\{00024500-0000-0000-C000-000000000046}\LocalServer32
first which is interesting)
At first I tried to just copy and paste the Excel entry and give it a new, unique CLSID so that i have a way of accessing it. This obviously did not work as the COM server will try to find the given CLSID within the Excel executable and wont find my newly assigned one.
My second Idea was to set up a temporary Registry redirect using RegOverridePredefKey
. Redirecting HKEY_CURRENT_USER
to HKEY_CURRENT_USER\Software\<company>\<program>\Sandbox
and then put an exact copy of the Excel COM entry (with the original CLSID) in there to then be able to change the path to whatever I'd like. Sadly, this did not work. I set up the redirect and COM just straight up ignored it, even tho the Registry requests came from the same thread and process...
So this is where I got stuck. I could try to create/overwrite a COM Object entry in HKCU
but I wouldn't want to change the client's Registry like that. Ideally, I'd use a temporary redirect like what I've tried.
I have read a few articles of people using COM components without registering them first. Would something like that work here? Would that even work with out-of-proc servers like Excel? Would it be possible to run an Excel server without registering it first or would it cause issues with Excel being already registered in the Registry?
I'm a bit at a loss here so I hope some Windows experts can help me out here! Cheers!