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 :(
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 eval
uating 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.
User contributions licensed under CC BY-SA 3.0