COM<->Remoting(Client Side)<->(Server Side)Remoting<->COM E_NOINTERFACE
So, here it is. Basically, I have a VB5 client/server app that communicates via DCOM. Because of the horrendous times we have been having keeping it working, I have finally decided it was time to start phasing the DCOM out. The very first step to do this needs to be to create a .NET Remoting/WCF bridge between the client and server.
I have linked the server.com to the server.Remote and the client.remote is able to communicate with with com objects passed through the Remoting bridge. The problem lies in exposing the class that obtains the server.com objects back to the COM client. The same code that works within the Client.Remoting is unable to pass the same object one step further to the client.com when client.com asks for it. The error is E_NOINTERFACE. I am at a complete loss as why this is. Other methods on client.Remoting exposed over the same COM interface do work. So it seems somehow that an interface required to connect the object from server.com between client.Remoting and client.com is either broken or missing. The interface is in the references for all projects passing it along the way. And as indicated, it appears that the variables and methods are making it at least as far as the client.Remoting from the server.com.
I have also tried passing a variable bored through a function call to get the data all the way through with the same result. I have thought about trying to do a delegate/callback/addressof type thing to see if I can just pass back a pointer to it but I really don't like that idea.
I'm wondering if there is a marshalling issue or if I'm missing a reference or need to manually define an interface. I'm hoping someone can give me a better direction to go in.
I'm hoping this will make sense to someone before I paste any code in.
Client/Server VB5
Server COM EXE
Vb.NET Express 2013
Re: COM<->Remoting(Client Side)<->(Server Side)Remoting<->COM E_NOINTERFACE
Remote Server Side Interface:
Code:
Public Interface IRemotingServer
Function GetNewCOMObj() As VB6ComServer.ActiveX-EXE.ClassVB6ComServer
End Interface
Remoting Server side code:
Code:
Imports VB6ComServer.ActiveX-EXE 'ActiveX Exe COM Server
Public Class RemotingServer
Inherits MarshalByRefObject
Implements IRemotingServer
Public mgr As VB6ComServer.ActiveX-EXE.ClassVB6ComServer
Function GetNewCOMObj() As VB6ComServer.ActiveX-EXE.ClassVB6ComServer Implements IRemotingServer.GetNewCOMObj
Dim mgr As New VB6ComServer.ActiveX-EXE.ClassVB6ComServer
Return mgr
End Class
Remoting Server Remoting code:
Code:
Dim ServiceChannel As IChannel
Dim serverProv As BinaryServerFormatterSinkProvider = New BinaryServerFormatterSinkProvider
Dim clientProv As BinaryClientFormatterSinkProvider = New BinaryClientFormatterSinkProvider
Dim Props As IDictionary = New Hashtable
Dim IpInjProvider As New IpInjectorSinkProvider
serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full
Props("port") = "8000"
Props("name") = "RemoteServer.rem"
serverProv.Next = IpInjProvider
ServiceChannel = New TcpChannel(Props, clientProv, serverProv)
'---------------------------------------------
ChannelServices.RegisterChannel(ServiceChannel)
RemotingConfiguration.RegisterWellKnownServiceType( _
GetType(VB6ComServer.ActiveX-EXE.ClassVB6ComServer), _
"RemoteServer.rem", WellKnownObjectMode.Singleton)
Remoting Client Side Code:
Code:
Imports System.Runtime.InteropServices
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp
Imports System.Net
Imports System.ServiceModel
Imports System.Configuration
<Guid("6CC8BE47-2552-4832-8924-21C67A5EAFEB"), _
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> _
Public Interface _clsManager_Client
<DispId(1)> Function GetMonth() As Integer
<DispId(2)> Function GetDay() As Integer
<DispId(3)> Function GetYear() As Integer
<DispId(4)> Function GetNewManager() As VB6ComServer.ActiveX-EXE.ClassVB6ComServer
End Interface
<Guid("3d9e2e6f-5bf2-f14f-879b-4e5b0af104e9"), _
ClassInterface(ClassInterfaceType.AutoDual), _
ProgId("comDemo.demo")> _
Public Class clsManager_Client
Implements _clsManager_Client
Public Function GetMonth() As Integer Implements _clsManager_Client.GetMonth
GetMonth = DateTime.Now.Month
End Function
Public Function GetDay() As Integer Implements _clsManager_Client.GetDay
GetDay = DateTime.Now.Day
End Function
Public Function GetYear() As Integer Implements _clsManager_Client.GetYear
GetYear = DateTime.Now.Year
End Function
Public obj As New clsPrivateManager
Public Function GetNewManager() As VB6ComServer.ActiveX-EXE.ClassVB6ComServer Implements _clsManager_Client.GetNewManager
Dim thing As IRemotingServer
thing = obj.CreateProxyInstance
Dim mgr As VB6ComServer.ActiveX-EXE.ClassVB6ComServer
mgr = thing.GetNewManager
MsgBox("getting manager")
Return mgr
End Function
Public Sub New()
MyBase.New()
End Sub
Public Enum CommunicationPlatform
Remoting
End Enum
Public defaultPlatform As CommunicationPlatform
Public ReadOnly Property Platform As CommunicationPlatform
Get
Return defaultPlatform
End Get
End Property
Public factory As ChannelFactory(Of IRemotingServer) = Nothing
Public Sub ClientProxyFactory()
RemotingConfiguration.Configure("app.config", False)
defaultPlatform = [Enum].Parse(GetType(CommunicationPlatform), _
ConfigurationManager.AppSettings("communicationPlatform"))
End Sub
Public Function CreateProxyInstance() As IRemotingServer
Return CreateProxyInstance(defaultPlatform)
End Function
Public Function CreateProxyInstance(platform As CommunicationPlatform) As IRemotingServer
Dim proxy As IRemotingServer
proxy = Nothing
Select Case platform
Case CommunicationPlatform.Remoting
proxy = CType(Activator.GetObject(GetType(IRemotingServer), "tcp://localhost:8000/RemoteServer.rem"), IRemotingServer)
End Select
Return proxy
End Function
Private chan As TcpChannel
Public mgr As IRemotingServer
Private varIdling As Integer
Public Property Idling As Integer
Get
Return varIdling
End Get
Set(value As Integer)
varIdling = value
End Set
End Property
Public Sub New()
MyBase.New()
On Error Resume Next
Idling = 15
End Sub
End Class
COM Client Code:
Code:
Private mgr As VB6ComServer.ActiveX-EXE.ClassVB6ComServer
Private mgrs As New RemotingClient.clsManager_Client
Private Sub CreateManager()
Dim i As Integer
'Dim mgr As New cVB6ComServer.ActiveX-EXE.ClassVB6ComServer
i = mgrs.GetDay ' <-- THESE WORK
i = mgrs.GetMonth
i = mgrs.GetYear
mgr = mgrs.GetNewManager ' <-- THIS DOESN'T WORK. I get E_NOINTERFACE
End Sub
Re: COM<->Remoting(Client Side)<->(Server Side)Remoting<->COM E_NOINTERFACE
In case I'm not too late with offering help - and you're still interested...
Could you post the Interface of the old Serverside Class -> ClassVB6COMServer?
(if possible as VBClassic-Code, meaning only the Public Method-Signatures)
Basically I just want to look at the Types of the Arguments and ReturnValues,
of those Methods, whether there's something "special" in them.
And alongside the above request - was the serverside Class:
ClassVB6COMServer
...your only interface which got "remoted" over DCOM, or were there more
serverside Classes?
If it's the only Interface (the only serverside Class)... was it indeed used as a Singleton
(as some stuff in your posted snippets suggested) - meaning, was it used to
"share state" among connecting Clients, or was this Class internally implemented
as being "stateless"?
Olaf