0
votes

I registered the Active Reports dll, arpro2.dll using regsvr32 Generating an interop assembly for Active Reports results in a servar fault: Main.cs

using System.Diagnostics;
using DDActiveReports2;

namespace TestActiveReports
{
    internal class Program
    {
        private static void Main()
        {
            var r = new ActiveReportClass();
            r.LoadLayout(@"C:\temp\RPTCUM20F.rpx");
            var s = r.Sections;
            Debug.Assert(s.Count() > 0);
        }
    }
}

.csproj:

<COMReference Include="DDActiveReports2">
  <Guid>{A7973091-BC64-4F16-84D4-A4BE059B4927}</Guid>
  <VersionMajor>2</VersionMajor>
  <VersionMinor>0</VersionMinor>
  <Lcid>0</Lcid>
  <WrapperTool>tlbimp</WrapperTool>
  <Isolated>False</Isolated>
  <EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>

The project is set to build to x86, so bitness is, I think, no issue.

An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in TestActiveReports.exe

Additional information: The server threw an exception. (Exception from HRESULT: 0x80010105 (RPC_E_SERVERFAULT))

DebugDiag reveals a Win32 access violation exception being thrown

However writing this stub wrapper in vb6, compiling it to a COM component, then referencing this COM component in .NET works:

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "VbActiveReport"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True
Private ar As activeReport

Option Explicit


'CONSTRUCTOR

Private Sub Class_Initialize()
Set ar = New activeReport
End Sub


'DECONSTRUCTOR

Private Sub Class_Terminate()
Set ar = Nothing
End Sub


'PROPERTIES

Public Property Get Sections() As Sections
    Set Sections = ar.Sections
End Property


'METHODS

Public Sub LoadLayout(path As String)
ar.LoadLayout path
End Sub

Writing a VB6 wrapper for all the functions and types feels both dirty. Also, after half a day fiddling with a home brewed generator, it doesn't sound as trivial as I first thought.

Why does .NET => COM compiled from VB6 => active reports work, while .NET => active reports fails?

Edit: This is the event log entry

Faulting application name: TestActiveReports.vshost.exe, version:12.0.30723.0, time stamp: 0x53cf4fe6
Faulting module name: arpro2.dll, version: 2.5.0.1322, time stamp: 0x4d252d15
Exception code: 0xc0000005
Fault offset: 0x0002b2a0
Faulting process id: 0x2368
Faulting application start time: 0x01d1b9b4eadc0f51
Faulting application path: C:\Users\myuser\Documents\Visual Studio 2013\Projects\TestActiveReports\TestActiveReports\bin\Debug\TestActiveReports.vshost.exe
Faulting module path: C:\temp\Active reports\arpro2.dll
Report Id: 2980b2a1-25a8-11e6-82c6-c4d987b41689

Not much more info in here :(

1
You can't effectively debug RPC_E_SERVERFAULT from your end, it is COM server process that fell over with something nasty. An access violation is as nasty and as undebuggable as they come. If the Windows Application log doesn't tell you anything more then you'll need help from the vendor to troubleshoot this problem. Be prepared to have a small repro project available that reproduces this problem. - Hans Passant

1 Answers

0
votes

Turns out the report files, .rpx, contain embedded VB6 code. I suspect this is the reason why going through a VB wrapper makes a difference. LoadLayout must be evaluating the VB6 code in the rpx, so it needs the VB runtime and/or libraries.

Turns out, a VB wrapper to forward function calls was not even necessary. A VB factory for the ActiveReport object does suffice.

Function CreateReport () As ActiveReport
    Set CreateReport = new ActiveReport
End Function

Having an intermediate factory com component with a single function within a single module is just good enough for now - very little work, no real need to maintain.

A possibly cleaner way would be to just load the VB runtime & libraries as references and expose them to the ActiveReports object created by newing up the Interop type. Trouble is, I didn't figure out how to do it.