My company has written a couple of .Net ActiveX components that have been running just fine for several years. The
components are written in C# and are dependent on .Net 4.5, but run okay on newer versions of .Net, including .Net 4.8. Recently,
we have had customer complaints that these components have stopped working after upgrading to Windows 10 1903. The
components appear to work fine for most users that have upgraded to 1903, though. We have not been able to reproduce
this issue in-house, so troubleshooting has been very difficult. We have spent many hours attempting to discover what is
not working properly through remote sessions with these customers.
We originally posted the question here:
https://social.technet.microsoft.com/Forums/windowsserver/en-US/739ef74c-5e7d-431a-a44b-a799222a8071/net-activex-component-failing-after-windows-10-1903-upgrade?forum=win10itproapps
Since that post we have determined that the issue is upgrade to .Net 4.8 and not Windows 10 1903. We know that Windows 1903 includes .Net 4.8, so those two things are tied together.
We do have a .Net dll compiled for x86, and we're running it on both 32bit and 64bit OSs. We have COM registry entries required.
It worked fine in .Net 4.7.2. We have proven that this can fail on Windows 7 PCs that have moved to .Net 4.8. I believe we have ruled out that this is a Windows 10 1903 problem. Instead it is a .Net 4.8 problem.
I’ll provide a summary here of what we have tried.
1. We
attempted to target .Net 4.8 specifically. This had no effect.
2. We
built a .Net C# test program that executes the ActiveX component directly and tests the interface. This test program was able to load the dll and execute tests without any issue on the broken Windows 10 1903 machines as well as a few broken Windows 7
machines with the .Net 4.8 upgrade.
3. We
built a .Net C# test program that attempts to load the ActiveX component via ActiveX. Basically it tries to instantiate the ActiveX component from the ProgID like this:
dynamic obj = Activator.CreateInstance(Type.GetTypeFromProgID("ISActiveX.ISActiveXMain"));
Then the test program calls methods on obj. When
tested on a working system, the test program runs great and can test the interface just fine. When run on a broken
Windows 10 1903 system, the call throws an exception. Here is the stack trace:
System.IO.FileNotFoundException: Retrieving the COM class factory for component with CLSID {3D5F3F28-F066-4F24-B142-6B8720A46691} failed
due to the following error: 80070002 The system cannot find the file specified. (Exception from HRESULT: 0x80070002).
at
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
at
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
at
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
at
System.Activator.CreateInstance(Type type, Boolean nonPublic)
at
System.Activator.CreateInstance(Type type)
at
ISActiveXTest2.Program.Main(String[] args)
Unfortunately, we haven’t been able to figure out what file is not found. Our
component doesn’t depend on anything other than the built-in .Net Framework assemblies. We suspect that some underlying
system dependencies are missing, but we have no way to know what those might be.
4. We
wrote a program to enumerate the registry keys we know to be required to properly register our ActiveX component. This generates a positive result on the broken Windows 10 1903 systems, so that was a nice double-check, but we did not learn anything new.
5. We
used Process Monitor to take a look at what registry keys and such are being accessed. We can see from the registry access that the program attempts to access many keys related to our ActiveX component in order to start it up. It actively attempts
to get keys from HKEY_CLASSES_ROOT first, and when it fails to find the entries, it goes to HKEY_CURRENT_USER instead. This seems to work happily for so many keys, but when it hits this key below, it does not try for the HKCU equivalent and it then seems
to go into an error state (noting this GUID below is owned by our component and the HKCU equivalent is present in the registry):
HKCR\WOW6432Node\CLSID\{3D5F3F28-F066-4F24-B142-6B8720A46691}\InprocServer32
Right after this last registry access, there are a number of file accesses related to mscorrc.dll. We
don’t know what mscorrc.dll does, but we did not see this dll being accessed when compared with a successful run of the component on other systems.
6. We ran some scans that didn't help.
sfc /scannow
Dism /Online /Cleanup-Image /CheckHealth
Dism /Online /Cleanup-Image /ScanHealth
DISM /Online /Cleanup-Image /RestoreHealth
So far, none of these have resolved the problem. Fortunately, we have finally found a PC in our own organization that is exhibiting this behavior, so we are able to run more experiments on a cloned VM of it without fear of destroying a customer PC.
7. We have reviewed Fusion logs and we don't see any binding issues:
https://www.inflectra.com/support/knowledgebase/kb171.aspx
8. We added COM tracing, but it didn't give any new information:
https://support.microsoft.com/en-us/help/926098/how-to-enable-com-and-com-diagnostic-tracing
9. We tried the .Net Framework repair tool, but apparently it doesn't even support .Net 4.8 (yet).
10. On Windows 7, we found combase.dll missing on these PCs, but adding it didn't seem to help. ProcMon showed that combase.dll was being requested, but after adding ProcMon showed it doing some activity on combase.dll but no change in the result.
11. We did run the old depends.exe program on mscoree.dll and found some differences in product and file version of dependency dlss on working vs non-working PCs. We're not convinced that depends is actually reporting the proper information, though, as
winsxs does a great deal of mysterious work to get the required dll loaded and we could very well be looking at the wrong things.
At this point, we’re looking into options to write an ActiveX interface layer in C++ to bypass the problem with .Net failing
to activate the component. That effort will take some time. We
could really use some suggestions on how to troubleshoot this any further. We know the direct cause is the 1903 upgrade
as rollback to the previous version resolves the issue. We also realize this could just be caused by the .Net 4.8
upgrade that comes along with 1903.
Is there any way to debug or log activity that occurs during .Net ActiveX component instantiation?
How can we find out what file is missing, as the stack trace indicates?