We have been using an SAP "COM License Bridge" to access their license server and query the hardware key of a system programatically (to reuse with out own licensing). This worked fine on SAP Business one Versions 2007A, 2007B and 8.8, but in 8.81 they seem to have updated their CORBA interface without updating the COM wrapper because we now get memory exceptions when attempting to call the GetHardwareKey function.
So I downloaded IIOP.NET and started trying to write my own interface. I never liked that COM wrapper anyway. But I encountered my old nemesis of .NET remoting -- the inability to invoke a remote method without having a common interface defined in both the server and the client. I tried using the IDL to CLS compiler included with IIOP.NET, but I continue to get errors about the interface beign incompatible (SAP did not provide an IDL file). I don't know how IIOP and CORBA determine whether an interface is compatible. But I even tried debugging into IIOP.NET code and forcing it to execute the method despite the incompatibility, but received an empty string back instead of the hardware key I wanted.
My next step is to try to implement a fake license server and examine the requests coming in from the production client in the hopes of identifying what they should look like, but I'm not counting on much success considering the difficulty I've had in peering into the innards of .NET remoting already.
My real problem is how to get or generate the SAP Business One hardware key, but questions stemming from that include:
- How do I reflect on or query information about a CORBA interface? I can use the list method of the NamingContext class to retrieve a list of available objects, but I don't see if there is a way to query available methods on an object.
- Can I dynamically invoke .NET remoting methods without having an interface? I see there's something called DII for dynamically invoking CORBA, but I don't see how to use it from IIOP.NET.
- Can I invoke .NET remoting methods with just a delegate or incomplete interface? I tried using the dynamic keyword, but it was unable to invoke a method on my MarshalByRef remote object... I think it said the method didn't exist on my MarshalByRef instance or something. I have only tried this via IIOP.NET, though (I wonder if it works for normal .NET remoting).
- How do I create or inspect Message instances in the .NET remoting framework?
- Can I send or retrieve remoting messages directly, bypassing the underlying proxies?
Edit: I managed to make IIOP.NET / CORBA believe that I had a compatible interface by applying the RepositoryID attribute:
[Ch.Elca.Iiop.Idl.InterfaceType(Ch.Elca.Iiop.Idl.IdlTypeInterface.ConcreteInterface)]
[Ch.Elca.Iiop.Idl.RepositoryID("IDL:LicenseInfo:1.0")]
public interface ILicenseInfo : Ch.Elca.Iiop.Idl.IIdlEntity
{
void GetHardwareKey(out string hwKey);
}
But I am still getting an empty string result.
Edit 2: After some more experimentation and debugging, I have found that the response messages do contain the data I'm looking for, but are not being parsed into the client values properly, probably because of my bad interface definition. Hoping that debugging into the response processing further will help me figure out how to correct my interface. Strangely the first thing it's parsing from the response is a null boxed value, which doesn't seem right for an "out string" parameter.
Edit 3: I have found that I need to apply string attributes to the parameters like this to prevent them from being treated as boxed values:
void GetHardwareKey([StringValue(), WideChar(true)] out string hwKey);
But despite the WideChar attribute, I am getting en error about the CodeSet not supporting WChar or something. I'm getting really close to figuring this out.
Edit 4: I am stumped at how to set the codeset for WChar. If I do not set it, I receive an error: "WChar Codeset either not specified or not supported." because the server has returned a unicode string without overriding the default character set. I can't find any way to override that from the client. I tried calling:
omg.org.CORBA.OrbServices.GetSingleton().OverrideDefaultCharSets(
CharSet.UTF8, WCharSet.UTF16);
But that does not seem to have any effect on the client end. The example code shows calling that on the server end. But I didn't write the server, so I can't control that. Is my only option to rewrite the IIOP.NET code for my own purposes forcing a default WChar CodeSet to go into effect?