none
System.Runtime.InteropServices.COMException Can't Be Handled by COM Client After .NET 4.5 is Installed RRS feed

  • Question

  • Problem Description

    We have discovered an issue in our application where a COM client (VB6) cannot handle a failing HRESULT returned from a .NET COM Interop component.  This issue only exists after our customer's machines had the .NET Framework 4.5 or later (4.5.1 and 4.5.2) pushed to them, replacing .NET 4.0.   

    The .NET component in question processes errors by creating System.Runtime.InteropServices.COMException instances and throwing them.  The CLR COM Interop layer catches the exception and returns a failing HRESULT to the COM caller.  In the case of VB6, we code the COM client to expect failing HRESULTS (VB6 errors) using On Error GoTo <label> processing.  And this has been working for our COM VB6 clients for years with .NET 2.0 and 4.0.

    However, as soon as we install .NET 4.5 (or later), our VB6 On Error statement is ignored and our application crashes.  There seems to be no way to trap the failing HRESULT.  When we connect a debugger to the crash, we see that 'System.Runtime.InteropServices.COMException' was thrown, but not handled.  It looks like this exception is not being caught/processed by the CLR in the COM Interop layer.

    Verification Using .NET 2.0 and .NET 4.0

    Our .NET component targets .NET 3.5, so I have the luxury of using EXE.CONFIG files to control the runtime.  When I specify the 3.5 framework (2.0 CLR), the code works as expected.  When I specify .NET 4.0 (CLR) but have .NET 4.5 installed, I get the crash. 

    Note that I am using the 'useLegacyV2RuntimeActivationPolicy="true" to avoid side by side .NET Frameworks. 

    Targeting .NET 4.0 for the .NET Component does not solve the problem.  We tried this and the exception was still crashing our COM client.

    Additional Information

    It should be noted that we have only found a few methods that have this problem and the CLR's issue seems to be related to the number and/or type of the parameters.  Our COM Client is calling the .NET Interop component's AddPointConnected method.  This method has 5 paramters.  The 4th parameter is an in,out parameter and the 5th parameter is an 'out' parameter.  There is something about this combination that causes the COMException to not be handled properly by the COM Interop layer of the CLR.

    We've tried many combinations of parameters, changing order, removing items, etc.  Some permutations continue to cause the exception and others don't.  The common issue appears to be the combination of the 'ref' and the 'return' parameters.

    Other Workarounds

    We tried targeting .NET 4.0 from Visual Studio 2010, but that did not fix the crash.

    Moving to Visual Studio 2013 is not possible in our current schedule.

    Sample Code

    I was able to create a complete sample problem that shows the issue.  It consists of only two parts.  The .NET Component is in a class library that exposes several interfaces and a component that implements the complex interface.  The method in question 'AddPointConnected' is implemented with only the following code:

    public IRoutePoint AddPointConnected(int PassKey, ConnectType connectType, IRoutePoint connectPt, ref ILeg newLeg)
    {
      throw new COMException("You cannot add anymore points");
    }

    The client uses the following code to try to trap the failing HRESULT:

    Private Sub Command2_Click()
    
    
      Dim clientEditor As DotNetClassLibrary.IComplexInterface
      Dim newLeg As ILeg
      Dim newPoint As IRoutePoint
      
      
      Set clientEditor = CreateObject("DotNetClassLibrary.ClientEditor")
      
      On Error GoTo CaughtError
      
      Set newPoint = clientEditor.AddPointConnected(0, DotNetClassLibrary.ConenctType_ADD_AFTER, Nothing, newLeg)
      
      MsgBox ("This message should not be seen.")
      
      Exit Sub
      
    CaughtError:
      MsgBox ("The exception was properly caught")
    End Sub

    I have attached the sample project here:

    <iframe src="https://onedrive.live.com/embed?cid=AE1D3AA8CFE3192F&resid=AE1D3AA8CFE3192F%21114&authkey=AA5xyH5tGKHeKYU" width="98" height="120" frameborder="0" scrolling="no"></iframe>

    https://onedrive.live.com/embed?cid=AE1D3AA8CFE3192F&resid=AE1D3AA8CFE3192F%21114&authkey=AA5xyH5tGKHeKYU

    Thanks


    Brian R.

    Wednesday, March 25, 2015 11:54 PM

Answers

  • After opening a support ticket with Microsoft, a hotfix was provided.  This is an acknowledged Microsoft issue in the 4.5.X .NET Framework.  The following URL leads to the KB article and Issue 6 is the problem that we were experiencing:

    https://support.microsoft.com/en-us/kb/2996566?wa=wsignin1.0

    Microsoft provided the hotfix to me directly.  IF you need it, you will need to open a support ticket.  MS did not indicate if this issue would be rolled into the next .NET FW release.

    KB2996566


    Brian R.

    • Marked as answer by Brian R. _ Saturday, May 2, 2015 9:19 PM
    Saturday, May 2, 2015 9:19 PM

All replies

  • Hello Brian,

    I downloaded the sample and tested to by running the .bat file to register the assembly to a COM, and run the VB 6 application, this is the screenshot of the result:

    https://social.msdn.microsoft

    From your description, this should be a ok result. And as you mentions, on my test machine, the .NET Framework 4.5 is installed and I also tried to change the Framework to target to .NET Framework from .NET 3.5, however, the VB6 application could still catch this exception occurring from the .NET COM.

    My test environment is windows 7/8/8.1, VS2013 with .NET Framework 3.5/4.0/4.5,from your description, it is not very clear your detail environment, you could have a try with mine or provide yours to us so that we can create an exact test. And since you are using the VB6 to call the .NET COM component, do you have a try to create a .NET based application or other non VB6 applications to call this .NET component? If others could works, I suggest that you could ask it on the VB6 forum to confirm if there are some environment configuration about calling .NET 4.5 COM component from VB6:

    https://social.msdn.microsoft.com/Forums/vstudio/en-US/aa350a38-3bb9-4919-9cc1-afaf7fed52f5/where-to-post-your-vb-6-questions?forum=vblanguage

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Thursday, March 26, 2015 2:38 AM
    Moderator
  • Sorry, I did intend to provide the test and dev environment details, but clearly forgot.  And since I do see a difference only with one signature definition and differing .NET Frameworks, I'd like to investigate the problem here first.

    Lastly, I'd like to keep the problem in the CLR because when I attach my debugger to the crashed VB6 application, the problem is that COMException was not handled in VB6.  COMException should never make it out of the CLR Interop layer and shoudl be instead returned to VB6 as a failing HRESULT (which triggers a VB6 Error object).

    Environment (All cases show the same results)

    Developer Machine:  Windows 7 SP1 x64, Visual Basic 6, Visual Studio Pro SP1, .NET Framework 4.5.1 installed from Microsoft Downloads

    Test Machine #1: Windows 7 SP1 x64, No Development Tools, .NET Framework 4.5.1 installed from Microsoft Downlaods

    Test Machine #2: Windows 8.1 x64, No Development Tools, .NET Framework 4.5.1 installed from Microsoft Downloads

    Running the Sample Code

    In order to reproduce the issue, the .NET Framework 4.5 or later must be installed.  In all the testing we have done, we do not have Visual Studio 2012 or 2013 installed on our machines.  .NET 4.5.X is installed by running the download from Microsoft.  Wwe have downloaded multiple times to ensure we do not have a defective download. 

    These steps reproduce the problem on every machine we try it on:

    1. Extract the Zip file to a directory on the C Drive.  Example, C:\Temp.  This will yield a directory named C:\Temp\VB6ExceptionStandalone

    2. Browse the new directory and run 'RegisterNetCOMServer.bat' by right clicking on it and selecting 'Run as Administrator'

    3. Delete 'VB6ExceptionDriver.exe.config' to ensure a common starting point.

    4. Copy 'VB6ExceptionDriver.exe2.0.config' --> 'VB6ExceptionDriver.exe.config'

    5. Run VB6ExceptionDriver.exe and click both buttons.  Observe that the exception is properly handled in both cases.

    6. Exit the driver by clicking the X in the top right hand corner.

    7. Delete 'VB6ExceptionDriver.exe.config'.

    8. Copy 'VB6ExceptionDriver.exe4.0.config' --> 'VB6ExceptionDriver.exe.config'

    9. Run VB6ExceptionDriver.exe and click both buttons.  Observe that the exception is properly handled in the first case (For button 'Test Exception Method Std').  But clicking 'Test Ref Parameter Method' will crash the application.

    Please let me know if you have any trouble reproducing the problem.


    Brian R.

    Thursday, March 26, 2015 2:10 PM
  • Hello Brian,

    According to your description, i am trying to deploy a test environment, this could take some time and as soon as I get any result, i will tell you.

    Update:

    With your new  clarification, I created a tested with your provided steps, however, on both win7 and win8 environment, the exception is caught:

    Win7:

    Win8.1:

    This is confused, both my machine has installed all updates, I am not sure if your test machines has done that, I suggest that you could have a try.

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Friday, March 27, 2015 7:38 AM
    Moderator
  • Are you sure you have .NET 4.5 installed on your machines?  I cannot find a machine yet that has .NET 4.5, 4.5.1, or 4.5.2 that passes this test.  I've expanded my testing to other people's machines and keep having the problem when using the .NET 4.0 FW.

    Will you verify that you are using my config files with:

      <startup useLegacyV2RuntimeActivationPolicy="true">
         <supportedRuntime version="v4.0.30319"/>
      </startup>

    And, again, you're clicking both buttons.

    The only explanation I can figure is that you do not have .NET 4.5 installed.  Send me a screen capture of your registry here:

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client


    Brian R.

    Wednesday, April 1, 2015 7:43 PM
  • Hello Brian,

    >>Will you verify that you are using my config files with:

    If I understand correctly, the used configuration file should be VB6ExceptionDriver:

    The screen capture of registry HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client:

    The release version is 379893 and it represents the .NET 4.5.2 is installed:

    https://msdn.microsoft.com/en-us/library/hh925568%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396#net_b

    >>And, again, you're clicking both buttons.

    Yes, I tried both button. I do not have other .NET Framework, I will also try it to see if it would be caused by a specific .NET 4.5.X version.

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, April 3, 2015 10:24 AM
    Moderator
  • Again, I have no idea how you are not able to reproduce this issue. 

    So, in order to make sure that you can reproduce the problem, I have created a document that includes all the steps needed to build a Virtual Machine and test this out.  I used VMWare Workstation version 10.  I know the issue is not specific to VMs as I've had this crash on 5 independent physical machines as well.

    I developed explicit steps for creating the VM using Windows 7 x64 SP1, installing .NET 4.5.2 and then finally my test driver. 

    https://onedrive.live.com/redir?resid=ae1d3aa8cfe3192f%21107

    As expected, I was able to reproduce the issue following these steps.

    Also, if you don't have a VM, then a physical machine or other VM system would be fine.  I feel the steps are hardware and machine independent. 

    Thanks,


    Brian R.


    • Edited by Brian R. _ Thursday, April 9, 2015 3:28 PM
    Thursday, April 9, 2015 3:25 PM
  • Hello Brian,

    I checked the document in your onedrive, and what I done is the same with the steps you done. Since I cannot reproduce this issue, I am trying to invoke some experience to help look into this case, it would take some time and we will post it back as soon as we have any result.

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, April 10, 2015 6:57 AM
    Moderator
  • Fred,

    Is there some way that someone else can try this for me there?  Looking at your screen caps, it does not look like you have followed my steps verbatim and I think your machine is an exception.  I am up to testing this issue on 15 independent machines and all of them have the problem.  So far, you are the only one that can't reproduce this issue.

    Would you be willing to pass my instructions on to someone else there and have them execute them? 


    Brian R.

    Saturday, April 11, 2015 5:07 AM
  • I couldn't repro it either.  I didn't use VMWare (of course), but used a MSDN VM on Azure (which is Hyper-V based) running Windows 7 Enterprise SP1.

    Followed the instructions from 6, onward.  The copy of regasm.exe that you redisted wouldn't work, so I had to use the one installed with .NET.

    ::REM Update the configuration database with the Test Driver entries 
    @ECHO OFF
    CLS
    Set CURRENT_DIR=%~dp0
    cd %CURRENT_DIR%
    
    C:\Windows\Microsoft.NET\Framework\v4.0.30319\regasm.exe /codebase /tlb .\bin\DotNetClassLibrary.dll
    pause

    No repro.


    If you contact me through my blog I can give you access to the VM.

    David

    David http://blogs.msdn.com/b/dbrowne/



    Saturday, April 11, 2015 2:44 PM
  • This is super baffling and frustrating. 

    I assume that both of you created VMs in this manner?  There must be something different about them.  I see this fail on VMWare and physical machines.

    I am curious why the regasm that I provided didn't work for you.  Would you post the error you got?  When I created the brand new machine, I was able to right click on the script and run it as admin.  It gives a warning, but it runs properly. 

    Ultimately, this means that your machine is not the same as my VM that I created via the steps provided.  Otherwise, it would have registered.  Perhaps that is the difference.

    From the steps provided you can see that I had no hot fixes or anything else installed.  In fact here are the only items I have installed on the machine that I created this on:


    Brian R.



    • Edited by Brian R. _ Monday, April 13, 2015 2:17 PM
    Monday, April 13, 2015 2:15 PM
  • I added those versions of the Visual C++ redistributable, and verified that it was loading the 4.0 CLR:

    Have you tried inserting a specific HRESULT in your COMException, or throwing some other sort of exception in the .NET component?

    >I am curious why the regasm that I provided didn't work for you.

    regasm.exe is part of the .NET Framework, and so should never be individually redistributed.  You should verify that the problem repros for you when you register your assembly with the 32bit regasm.exe shipped with .NET 4.5.2.

    David


    David http://blogs.msdn.com/b/dbrowne/


    Monday, April 13, 2015 4:13 PM
  • Yes, we have tried customizing the internal error message (HRESULT) and get the same result.

    I think we are starting to see the differences in machines between yours and mine.  Those redistributables were installed by the .NET Framework 4.5.2 installer.  I didn't install them specifically.  It seems your .NET FW is different than mine even though versions are reporting the same thing.

    Would it be possible for you to build a machine (not an Azure VM) or other local VM using the exact products that I did (by downloading from Microsoft using the links I used)?

    Also, can you post the message you receive when you try to use the regasm that I provided?


    Brian R.

    Monday, April 13, 2015 4:26 PM
  • I used the .NET Framework installer specified in your document, and it does not install the C++ redistributables.  That was probably the VMWare tools.

    When trying to run the regasm.exe from .\DevTools I get

    Microsoft (R) .NET Framework Assembly Registration Utility 4.0.30319.1
    Copyright (C) Microsoft Corporation 1998-2004.  All rights reserved.
    
    RegAsm : error RA0000 : Could not load file or assembly 'file:///C:/Users/dbrown
    e/Downloads/VB6ExceptionStandalone/VB6ExceptionStandalone/DevTools/RegAsm.exe' o
    r one of its dependencies. Operation is not supported. (Exception from HRESULT:
    0x80131515)
    Press any key to continue . . .
    
    David


    David http://blogs.msdn.com/b/dbrowne/

    Monday, April 13, 2015 4:43 PM
  • Ok,  I've got it repro-ing on Windows 7.  There was a failure to follow directions on my part, and I was only running the "Test Exception Method Std", not the "Test Ref Parameter Method".

    Yep. The app is crashing.  I fully patched my VM and it's still crashing.

    I think you can avoid this error if you turn off useLegacyV2RuntimeActivationPolicy, and target the class library to .NET 4.0.

    eg

    <?xml version="1.0"?>
    <configuration>
      <runtime>
        <gcConcurrent enabled="true" />
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <publisherPolicy apply="yes" />
          <probing privatePath="" />
        </assemblyBinding>
      </runtime>
      <startup useLegacyV2RuntimeActivationPolicy="false">
         <supportedRuntime version="v4.0"/>
      </startup>
    </configuration>

    and then in the DotNetclassLibrary.csproj

    <?xml version="1.0" encoding="utf-8"?>
    <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <PropertyGroup>
        <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
        <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
        <ProductVersion>8.0.30703</ProductVersion>
        <SchemaVersion>2.0</SchemaVersion>
        <ProjectGuid>{055F6889-F6AB-44DE-AD4F-3939E1203B31}</ProjectGuid>
        <OutputType>Library</OutputType>
        <AppDesignerFolder>Properties</AppDesignerFolder>
        <RootNamespace>DotNetClassLibrary</RootNamespace>
        <AssemblyName>DotNetClassLibrary</AssemblyName>
        <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
        <FileAlignment>512</FileAlignment>
        <TargetFrameworkProfile />
      </PropertyGroup>

    Then msbuild

    C:\Users\dbrowne\Downloads\VB6ExceptionStandalone\VB6ExceptionStandalone\DotNetClassLibrary>c:\windows\Microsoft.NET\Framework\v4.0.30319\msbuild

    And retest.

    David


    David http://blogs.msdn.com/b/dbrowne/

    Monday, April 13, 2015 10:12 PM
  • Thank you for following up and trying both buttons.  I am glad that someone else on this post was able to reproduce the problem.  I still am surprised that Fred could not reproduce it.

    Proposed Workarounds

    David, you proposed the two following workarounds to this problem:

    1. Use side by side execution by specifying 'false' for useLegacyV2RuntimeActivationPolicy

    2. Target .NET 4.0 and then set useLegacyV2RuntimeActivationPolicy to false.

    Workaround Responses

    1. Unfortunately, side by side execution is not compatible with our code base of over 10 MSLOC+ as most objects have not derived from 'MarshallByRef' object and do not marshal across runtimes.  Our goal is to get all our enterprise components to Microsoft .NET 4.0, but that is not yet.  We rely heavily on the this policy to coerce all .NET objects into the same runtime.

    2. We are currently executing a plan to migrate to .NET 4.X across all components.  However, it will take a few years to transition everything.  As mentioned in the previous item, we rely on the activation policy to make sure all of our objects run in the same runtime and that the runtime is the .NET 4.0 CLR.

    Workaround Testing

    Despite our inability to incorporate the recommended workarounds, I did try them in the sample problem. 

    1. Setting the useLegacyV2RuntimeActivationPolicy value to false resulted in the proper handling of the COMException.  To me this is the same as using the .NET 2.0 EXE config file since it loads the runtime of the DLL, which is the .NET 2.0 CLR

    2. I then tried targeting the .NET DLL for .NET 4.0 and recompiled.  I re-registered the project after it built.  However, this had no effect on the results.  The COMException was not caught and it crashed the application.  No matter how useLegacyV2RuntimeActivationPolicy was set, the application crashed on the second step. 

    Conclusion

    So even if we were able to target .NET 4.0 in our code, I still see the crash for this method signature.  As a reminder, this application (and our application) runs fine in .NET 4.0 prior to the installation of .NET 4.5 (or later).  You can prove this by uninstalling .NET 4.5.X and reinstalling .NET 4.0.  You will see that the COMException is handled appropriately.

    It does not seem to be a viable workaround to go back in time and not move to the .NET 4.5 framework.


    Brian R.



    • Edited by Brian R. _ Tuesday, April 14, 2015 4:22 AM
    Tuesday, April 14, 2015 4:11 AM
  • Interestingly, the problem goes away after running .NET 4.5's msbuild.exe on the solution on the target machine, whether it's retargeted to .NET 4.0 or to 3.5. 

    David


    David http://blogs.msdn.com/b/dbrowne/

    Tuesday, April 14, 2015 1:32 PM
  • That may be the difference as I used Visual Studio 2010 to target .NET 4. 

    I am downloading VS 2013 Update 4 now to try that and let you know.

    It is in our plan to start building for .NET 4.X with VS 2013 later this year.  However, for our current and legacy builds, we still need a solution.

    Thanks,


    Brian R.

    Tuesday, April 14, 2015 1:37 PM
  • If this works, you don't have to build _for_ .NET 4.X you just need to build using .NET 4.5's version of msbuild.  So you can use VS 2013 targeting .NET 3.5, or you can just do a commandline build using msbuild.

    And you don't have to change all your .NET assemblies.  Only the ones that contain COM components that your COM client creates via CreateObject("ObjectName").  Once these initial assemblies are loaded into CLR 4.0, then any dependent assemblies they have will always load into the same AppDomain, and so will use CLR 4.0.

    So one option would be to refactor all your COM-visible interfaces into a single .NET assembly and have the implementation there be facades to forward the method calls to your various other .NET assemblies.

    David


    David http://blogs.msdn.com/b/dbrowne/


    Tuesday, April 14, 2015 2:35 PM
  • I'll play with that, but it will most likely be too much of a change for our enterprise.  The affected interfaces are COM TLBs that are our contracts for backwards compatibility.  We have an enterprise that is built off these libraries and we do not break interfaces.

    At this point, these are some interesting options and workarounds, but I really need Microsoft to take my sample, debug it and see if the error can be addressed in the CLR.

    It would by my preference to obtain a hotfix/patch or .NET Framework 4.5.3 that fixes the issue so that we can maintain our legacy code base and move forward towards VS 2013 at our pace.  Without a fix from Microsoft, our existing and legacy baselines are broken.


    Brian R.

    Tuesday, April 14, 2015 2:52 PM
  • >It would by my preference to obtain a hotfix/patch or .NET Framework 4.5.3 that fixes the issue

    Then your next step should be to open a case with Microsoft Support. 

    But it could be that the bug is in VS 2010, or even Windows 7. 

    David


    David http://blogs.msdn.com/b/dbrowne/


    Tuesday, April 14, 2015 3:20 PM
  • After opening a support ticket with Microsoft, a hotfix was provided.  This is an acknowledged Microsoft issue in the 4.5.X .NET Framework.  The following URL leads to the KB article and Issue 6 is the problem that we were experiencing:

    https://support.microsoft.com/en-us/kb/2996566?wa=wsignin1.0

    Microsoft provided the hotfix to me directly.  IF you need it, you will need to open a support ticket.  MS did not indicate if this issue would be rolled into the next .NET FW release.

    KB2996566


    Brian R.

    • Marked as answer by Brian R. _ Saturday, May 2, 2015 9:19 PM
    Saturday, May 2, 2015 9:19 PM