none
.Net ActiveX component failing after .Net 4.8 upgrade RRS feed

  • Question

  • 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?

    Thursday, August 29, 2019 11:42 AM

Answers

  • We determined the cause and final solution to this problem.  The cause is a "bug fix" in .Net 4.8 related to COM activation as it related to UAC levels.  My understanding is that if the UAC level is set to the very lowest setting, then failed attempts to run elevated fail silently.  As an added bonus, with .Net 4.8, if the UAC setting is set to the lowest value, only HKLM / HKCR are used in .Net COM activation and so a "per user" .Net ActiveX component registration will not work since HKCU registry keys are ignored.

    We found that if our users raised the UAC level to anything above the lowest value, then our ActiveX component worked.

    • Marked as answer by JeremyHolland1 Wednesday, September 25, 2019 1:37 PM
    Wednesday, September 25, 2019 1:37 PM

All replies

  • can you share a minimum project to reproduce the issue?
    Thursday, August 29, 2019 2:35 PM
  • there is some contradiction in your description:
    "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."
    vs 
    "We have proven that this can fail on Windows 7 PCs that have moved to .Net 4.8. "

    Or do you mean: not all systems with .NET 4.8 show this problem?

    Thursday, August 29, 2019 2:39 PM
  • Correct, not all systems with .Net 4.8 show this problem.  We have seen our component working fine on Windows 10 1903 on the vast majority of our deployment field.  We only have a handful of failures - perhaps 20 or 30 PCs that present the problem on Windows 10 1903.  We don't have many Windows 7 customers left at all, but we have seen just a few failures on Windows 7 with .Net 4.8 upgrade.
    Thursday, August 29, 2019 3:10 PM
  • We do not have a minimum project to post yet.  That's something we can look into next while we wait for other suggestions.
    Thursday, August 29, 2019 3:30 PM
  • you could use ProcMon, filter on Process Name and File access.

    I can reproduce the exception with your call stack when the managed assembly which contains the COM callable class is neither in GAC nor side by side.


    • Edited by EckiS Thursday, August 29, 2019 4:05 PM
    Thursday, August 29, 2019 4:00 PM
  • Yes, we have used ProcMon extensively in our troubleshooting but we have not yet caught which file is actually missing.  I noted in a previous comment what we're seeing in registry access right before the program seems to fail.

    We are not using regasm to register our component.  We have the requirement to not require admin rights during installation, and so we put all of our registry entries into HKCU instead of HKLM and HKCR.  This has worked fine for quite some time.

    We also did manage to do a native debug session against cscript running a simple vbscript that loads the component and then calls one method on it.  The native debug session didn't tell us much, though.  We were able to see the exception thrown, but there's just no detail.  If we had a way to debug the clr (mscorlib) code, we might be able to see what is being called right before that.

    We continue to get new reports of customer PCs not working after Windows 7 upgrade to .Net 4.8.  The solution continues to be to role them back to 4.7 for now.  We have confirmed re-upgrading to .Net 4.8 again breaks the component.


    Monday, September 2, 2019 2:28 AM
  • Just want to give you something to check:

    According to this blog post, if a COM process is to be run elevated, only HKLM is consulted in order to avoid the possible privilege escalation.

    Please check whether the scenario when your application fails involves running it elevated. You may also want to add the registration to HKLM too and see if the problem will go away.

    Monday, September 2, 2019 3:11 AM
    Answerer
  • Thank you for the suggestion.  Our component does not run elevated.  Normally we use the component only from Internet Explorer.  The component allows a browser application to talk to other locally installed applications.  IE is not run elevated by our users.  Nothing within our component asks to run elevated, either.
    Monday, September 2, 2019 8:36 PM
  • We determined the cause and final solution to this problem.  The cause is a "bug fix" in .Net 4.8 related to COM activation as it related to UAC levels.  My understanding is that if the UAC level is set to the very lowest setting, then failed attempts to run elevated fail silently.  As an added bonus, with .Net 4.8, if the UAC setting is set to the lowest value, only HKLM / HKCR are used in .Net COM activation and so a "per user" .Net ActiveX component registration will not work since HKCU registry keys are ignored.

    We found that if our users raised the UAC level to anything above the lowest value, then our ActiveX component worked.

    • Marked as answer by JeremyHolland1 Wednesday, September 25, 2019 1:37 PM
    Wednesday, September 25, 2019 1:37 PM