如何在没有IDL或后期绑定调用远程处理方法的情况下访问CORBA接口

我们一直在使用SAP“COM许可证桥”来访问其许可证服务器并以编程方式查询系统的硬件密钥(以重复使用自己的许可)。 这在SAP Business One版本2007A,2007B和8.8上运行良好,但是在8.81中它们似乎更新了它们的CORBA接口而没有更新COM包装器,因为我们现在在尝试调用GetHardwareKey函数时获得内存exception。

所以我下载了IIOP.NET并开始尝试编写自己的界面。 无论如何我从来都不喜欢COM包装器。 但是我遇到了我的旧远程.NET远程控制 – 无法在服务器和客户端都没有定义公共接口的情况下调用远程方法。 我尝试使用IIOP.NET附带的IDL到CLS编译器,但我继续得到关于接口beign不兼容的错误(SAP没有提供IDL文件)。 我不知道IIOP和CORBA如何确定接口是否兼容。 但我甚至尝试调试IIOP.NET代码并强制它执行该方法尽管不兼容,但收到一个空字符串而不是我想要的硬件密钥。

我的下一步是尝试实现虚假的许可证服务器并检查来自生产客户端的请求,以期确定它们应该是什么样子,但考虑到我遇到的困难,我并不指望取得多大的成功。深入了解.NET远程的内容。

我真正的问题是如何获取或生成SAP Business One硬件密钥,但由此产生的问题包括:

  1. 如何反思或查询有关CORBA接口的信息? 我可以使用NamingContext类的list方法来检索可用对象的列表,但我不知道是否有办法查询对象上的可用方法。
  2. 我可以在没有接口的情况下动态调用.NET远程处理方法吗? 我看到有一个叫做DII的东西用于动态调用CORBA,但是我没有看到如何在IIOP.NET中使用它。
  3. 我可以仅使用委托或不完整的接口来调用.NET远程处理方法吗? 我尝试使用dynamic关键字,但它无法在我的MarshalByRef远程对象上调用一个方法……我认为它说我的MarshalByRef实例上不存在该方法。 我只是通过IIOP.NET尝试过这个(我想知道它是否适用于普通的.NET远程处理)。
  4. 如何在.NET远程处理框架中创建或检查Message实例?
  5. 我是否可以直接发送或检索远程处理消息,绕过底层代理?

编辑:我设法通过应用RepositoryID属性使IIOP.NET / CORBA相信我有一个兼容的接口:

[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); } 

但我仍然得到一个空字符串结果。

编辑2:经过一些更多的实验和调试,我发现响应消息确实包含我正在寻找的数据,但是没有正确地解析成客户端值,可能是因为我的接口定义不好。 希望进一步调试响应处理将帮助我弄清楚如何纠正我的界面。 奇怪的是,它从响应中解析的第一件事是一个空的盒装值,这似乎不适合“out string”参数。

编辑3:我发现我需要将字符串属性应用于这样的参数,以防止它们被视为盒装值:

 void GetHardwareKey([StringValue(), WideChar(true)] out string hwKey); 

但是,尽管有WideChar属性,我对CodeSet不支持WChar或其他东西的错误。 我已经非常接近搞清楚了。

编辑4:我很难理解如何为WChar设置代码集。 如果我没有设置它,我收到一个错误:“未指定或不支持WChar代码集。” 因为服务器返回了一个unicode字符串而没有覆盖默认字符集。 我找不到任何方法来覆盖客户端。 我试着打电话:

 omg.org.CORBA.OrbServices.GetSingleton().OverrideDefaultCharSets( CharSet.UTF8, WCharSet.UTF16); 

但这似乎对客户端没有任何影响。 示例代码显示在服务器端调用它。 但我没有写服务器,所以我无法控制它。 我唯一的选择就是为了我自己的目的而重写IIOP.NET代码,迫使默认的WChar CodeSet生效?

经过3天的IIOP调试以追踪其行为并检查响应中的数据,我已经确定了这个解决方案。

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using omg.org.CosNaming; using Ch.Elca.Iiop; using Ch.Elca.Iiop.Services; using System.Runtime.Remoting.Channels; using Ch.Elca.Iiop.Idl; [RepositoryID("IDL:LicenseInfo:1.0")] public interface ILicenseInfo { Int32 GetHardwareKey([IdlSequence(0)] out byte[] hwKey); Int32 GetInstallationNumberList([IdlSequence(0)] out byte[] instNum); } class Program { static void Main(string[] args) { IiopClientChannel channel = new IiopClientChannel(); ChannelServices.RegisterChannel(channel, false); CorbaInit init = CorbaInit.GetInit(); NamingContext context = init.GetNameService("MYLICSRV", 30000); NameComponent[] names = new NameComponent[] { new NameComponent("B1LicenseInfo") }; ILicenseInfo li = (ILicenseInfo)context.resolve(names); byte[] hwKey; byte[] instNum; li.GetHardwareKey(out hwKey); li.GetInstallationNumberList(out instNum); Encoding encoding = new System.Text.UnicodeEncoding(false, false, true); Console.WriteLine(encoding.GetString(hwKey)); Console.WriteLine(encoding.GetString(instNum)); } } 

我暂时也在使用它,试图让IIOP给我回正确的字符串。 如果我发现我可以简单地接受回复作为字节数组并自己执行解码,我不会浪费一半时间试图找出如何让IIOP理解我想要我的字符串:

 class MyOrbInitializer : omg.org.PortableInterceptor.ORBInitializer { public void post_init(omg.org.PortableInterceptor.ORBInitInfo info) { // Nothing to do } public void pre_init(omg.org.PortableInterceptor.ORBInitInfo info) { omg.org.IOP.Codec codec = info.codec_factory.create_codec( new omg.org.IOP.Encoding(omg.org.IOP.ENCODING_CDR_ENCAPS.ConstVal, 1, 2)); Program.m_codec = codec; } } class Program { public static omg.org.IOP.Codec m_codec; static void Main(string[] args) { IOrbServices orb = OrbServices.GetSingleton(); orb.OverrideDefaultCharSets(CharSet.UTF8, WCharSet.UTF16); orb.RegisterPortableInterceptorInitalizer(new MyOrbInitializer()); orb.CompleteInterceptorRegistration(); ... MarshalByRefObject objRef = context.resolve(names); string origObjData = orb.object_to_string(objRef); Ch.Elca.Iiop.CorbaObjRef.Ior iorObj = new Ch.Elca.Iiop.CorbaObjRef.Ior(origObjData); CodeSetComponentData cscd = new CodeSetComponentData( (int)Ch.Elca.Iiop.Services.CharSet.UTF8, new int[] { (int)Ch.Elca.Iiop.Services.CharSet.UTF8 }, (int)Ch.Elca.Iiop.Services.WCharSet.UTF16, new int[] { (int)Ch.Elca.Iiop.Services.WCharSet.UTF16 }); omg.org.IOP.TaggedComponent codesetcomp = new omg.org.IOP.TaggedComponent( omg.org.IOP.TAG_CODE_SETS.ConstVal, m_codec.encode_value(cscd)); iorObj.Profiles[0].TaggedComponents.AddComponent(codesetcomp); string newObjData = iorObj.ToString(); MarshalByRefObject newObj = (MarshalByRefObject)orb.string_to_object(newObjData); ILicenseInfo li = (ILicenseInfo)newObj; ... } 

在运行了很多代码之后,我有了一个定义WChar CodeSet的对象,因此它会正确地解析返回字符串,避免“未指定或不支持WChar CodeSet”错误。 但毕竟,Unicode字节顺序也是倒退的! 据我所知,解决这个问题的唯一方法是将字符串重新解析为字节,然后再重新解析为Unicode字符串。 但是,当我遇到这种情况时,为什么甚至要求将结果作为字符串!? 我可以直接取字节并避免这么多的复杂化。 我希望我早点想到这一点。

SAP BO 882 //LicenseInterface.idl

 typedef sequence LicenseFileData; interface LicenseInfo { boolean IsUserLicensed(in wstring wstrUser, in wstring wstrModule, in wstring wstrInstallNo); long GetHardwareKey(out wstring pbstrHK); long GetInstallationNumberList(out wstring wbstrInstNum); long GetSystemNumber(out wstring wbstrSysNum, in wstring wstrInstallNo); long GetLicenseInfo(in wstring wstrModule, out long lNum, out long lAvailable, out long lStart, out long lEnd, in wstring wstrInstallNo); long GetLoggedInUsers(out wstring wbstrLogUsers); long StartLogging(); long StopLogging(); long GetLicenseNum(in wstring wstrKey, in wstring wstrInstallNo); long GetLogFileName(out wstring wstrLogFileName); boolean GetIsLogging(); long LoadLicenseFile (in LicenseFileData arg_licenseFileData); boolean IsLicenseFileExist(); long ResetAllLicenses(); long GetVersion(out wstring sVersion); //long DeleteLicenseFile (in wstring wstrInstallNo); }; 

SBOLicense.idl

 typedef sequence usBuffer; enum LicenseClientUTFType {LIC_UTF16 , LIC_UTF32}; exception NotAuthenticated {}; exception UserNotConnected {}; interface LicenseServer { long SBOConnect (in usBuffer User, in usBuffer Company, in usBuffer PCName, out usBuffer SessionE, in long lDate, in usBuffer sInstallNo) raises(NotAuthenticated); long AddOnGetLicense (in usBuffer Identifier, in usBuffer User, in usBuffer Company, in usBuffer PCName, out long plSessionID, out usBuffer SessionE, in long lDate, in usBuffer sInstallNo) raises(NotAuthenticated); long PollSession (in usBuffer User, in usBuffer SIDs, out usBuffer RetE) raises(NotAuthenticated); long SessionsInfo (in usBuffer User, in usBuffer SessionsInfo, out usBuffer SessionsInfoE, in long lDate) raises(NotAuthenticated); long SessionVerify (in usBuffer User, in long lSessionID, out usBuffer pSessionIdE) raises(NotAuthenticated); long CloseSession (in usBuffer User, in long lSessionId) raises(NotAuthenticated); long LockServer (in usBuffer User, in long lSessionID) raises(NotAuthenticated); long UnLockServer (in usBuffer User, in long lSessionID) raises(NotAuthenticated); long GetUserLicenseInfo (in usBuffer User, out usBuffer pModules, out boolean pbIsConnected) raises(NotAuthenticated); long GetAllModulesStatus (out usBuffer pModulesInfo) raises(NotAuthenticated); long LoadLicenseFile (in usBuffer NewLicenseFile) raises(NotAuthenticated); long GetHardwareKey (out usBuffer pHK) raises(NotAuthenticated); long CreateIdentifier (in usBuffer Addon, out usBuffer pIdentifier, in usBuffer sInstallNo) raises(NotAuthenticated); long GetAllUsersLicenseInfo(out usBuffer pUsersLicInfo) raises(NotAuthenticated); long SetAllUsersLicenseInfo(in usBuffer User, in usBuffer UsersLicInfo, out usBuffer pConnectedUser) raises(NotAuthenticated,UserNotConnected); long IsDevExist (in usBuffer sInstallNo); long GetInstallationNumberList(out usBuffer pInstNum); long GetSystemNumber (out usBuffer pSysNum, in usBuffer sInstallNo); long GetFutureExpired(in long lFutureDate, out usBuffer pModules, in usBuffer sInstallNo); long GetUserSessionsInfo(in usBuffer UserName,out usBuffer pRsltSessionsInfo); long GetBIGSLicense (in usBuffer User, in usBuffer Company, in usBuffer PCName, in long lNum, out usBuffer pSessionsE, in long lDate, in usBuffer sInstallNo) raises(NotAuthenticated); boolean IsLicenseFileExist(); long GetVersion(out usBuffer sVersion); long ClearUserLicenses (in usBuffer User) raises(NotAuthenticated); long UpdateUserLicenses (in usBuffer User, out usBuffer ModulesE, in long lDate, in long lSessionID, in usBuffer sCmpLocalization, in usBuffer sCmpVersion) raises(NotAuthenticated); long RequestNamedLicenses (in usBuffer User, out usBuffer ModulesE, in long lDate, in long lSessionID, in usBuffer sCmpLocalization, in usBuffer sCmpVersion) raises(NotAuthenticated); long IsLicenseConcurrent () raises(NotAuthenticated); long GetLicenseFileGenInfo(in usBuffer sInstallNo, out usBuffer sLicGenInfo); //long DeleteLicenseFile (in usBuffer sInstallNo) raises(NotAuthenticated); long HandShake(in long algorithm, in usBuffer publicKey, out usBuffer sessionKey) raises(NotAuthenticated); long GetCompanyDBCredentials(in long dbType, in usBuffer server, in usBuffer company, in usBuffer user, in usBuffer password, out usBuffer dbUser, out usBuffer dbPassword, out boolean useTrusted) raises(NotAuthenticated); long GetDBCredentials(in long dbType, in usBuffer server, in usBuffer siteUser, in usBuffer password, out usBuffer dbUser, out usBuffer dbPassword, out boolean useTrusted) raises(NotAuthenticated); long GetCompanyReadOnlyDBCredentials(in long dbType, in usBuffer server, in usBuffer company, in usBuffer user, in usBuffer password, out usBuffer dbUser, out usBuffer dbPassword) raises(NotAuthenticated); long GetReadOnlyDBCredentials(in long dbType, in usBuffer server, in usBuffer siteUser, in usBuffer password, out usBuffer dbUser, out usBuffer dbPassword) raises(NotAuthenticated); long GetListOfCompanies(in long dbType, in usBuffer server, in boolean refresh, out usBuffer listOfCompanies); long GetCompanyEncryptionConfig(in long dbType, in usBuffer server, in usBuffer company, in usBuffer user, in usBuffer password, out long algorithm, out usBuffer keyId, out usBuffer key) raises(NotAuthenticated); long GetEncryptionConfig(in usBuffer siteUser, in usBuffer password, out long algorithm, out usBuffer keyId, out usBuffer key) raises(NotAuthenticated); long SetDBCredentials(in long dbType, in usBuffer server, in usBuffer siteUser, in usBuffer password, in usBuffer dbUser, in usBuffer dbPassword, in boolean useTrusted) raises(NotAuthenticated); long RemoveDBCredentials(in long dbType, in usBuffer server, in usBuffer siteUser, in usBuffer password) raises(NotAuthenticated); long GetServerVersion(in long dbType, in usBuffer server, out usBuffer version, in usBuffer commonDBName); long SetReadOnlyDBCredentials(in long dbType, in usBuffer server, in usBuffer siteUser, in usBuffer password, in usBuffer dbUser, in usBuffer dbPassword) raises(NotAuthenticated); long SetEncryptionAlghorithm(in usBuffer siteUser, in usBuffer password, in long algorithm) raises(NotAuthenticated); long GenerateEncryptionKey(in usBuffer siteUser, in usBuffer password) raises(NotAuthenticated); long GetServicesUserCredentials(in usBuffer siteUser, in usBuffer password, out usBuffer servicesUser, out usBuffer servicesPassword) raises(NotAuthenticated); long ExportSecuritySettings(in usBuffer siteUser, in usBuffer password, out usBuffer xmlSettings) raises(NotAuthenticated); long ImportSecuritySettings(in usBuffer siteUser, in usBuffer password, in usBuffer xmlSettings) raises(NotAuthenticated); long GetListOfConfiguredServers(out usBuffer listOfServers); long GetSiteUserName(out usBuffer siteUser); long AuthenticateSiteUser(in usBuffer siteUser, in usBuffer password, out boolean result) raises(NotAuthenticated); long AuthenticateServicesUser(in usBuffer siteUser, in usBuffer password, out boolean result) raises(NotAuthenticated); long ChangeSiteUserPassword(in usBuffer siteUser, in usBuffer oldPassword, in usBuffer password) raises(NotAuthenticated); long ChangeSiteUserPasswordByDB(in long dbType, in usBuffer server, in usBuffer dbUser, in usBuffer dbPassword, in usBuffer password) raises(NotAuthenticated); long GetCompanyStaticKey(in long dbType, in usBuffer server, in usBuffer company, in usBuffer user, in usBuffer password, out usBuffer key) raises(NotAuthenticated); long GetStaticKey(in usBuffer siteUser, in usBuffer password, out usBuffer key) raises(NotAuthenticated); long GetEncryptionAlgorithm(out long algorithm); long IsNTTrusted(in long dbType, in usBuffer server, out boolean isNTTrusted); long IsDKeyUsed(out boolean result); long ExportDKeys(in usBuffer siteUser, in usBuffer password, out usBuffer xmlDKeys) raises(NotAuthenticated); long ImportDKeys(in usBuffer siteUser, in usBuffer password, in usBuffer xmlDKeys) raises(NotAuthenticated); long GenerateDKey(in usBuffer siteUser, in usBuffer password, out usBuffer xmlDKeys) raises(NotAuthenticated); long EnableDKey(in usBuffer siteUser, in usBuffer password, out usBuffer xmlDKeys) raises(NotAuthenticated); long GetCompanyKeyAndKeyState(in long dbType, in usBuffer server, in usBuffer company, in usBuffer user, in usBuffer password, in usBuffer compKeyId, out long keyState, out usBuffer compKey)raises(NotAuthenticated); long GetKeyAndKeyState(in usBuffer siteUser, in usBuffer password, in usBuffer compKeyId, out long keyState, out usBuffer compKey)raises(NotAuthenticated); }; interface LicenseServerFactory { LicenseServer GetLicenseServer(in LicenseClientUTFType ClientUTFType); };