[英]How to access CORBA interface without IDL or late-bound invoke remoting methods
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). 我们一直在使用SAP“COM许可证桥”来访问其许可证服务器并以编程方式查询系统的硬件密钥(以重用自己的许可证)。 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.
这在SAP Business One版本2007A,2007B和8.8上运行良好,但是在8.81中它们似乎更新了它们的CORBA接口而没有更新COM包装器,因为我们现在在尝试调用GetHardwareKey函数时获得了内存异常。
So I downloaded IIOP.NET and started trying to write my own interface. 所以我下载了IIOP.NET并开始尝试编写自己的界面。 I never liked that COM wrapper anyway.
无论如何我从来都不喜欢COM包装器。 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.
但是我遇到了我的旧远程.NET远程控制 - 无法在服务器和客户端都没有定义公共接口的情况下调用远程方法。 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).
我尝试使用IIOP.NET附带的IDL到CLS编译器,但我继续得到关于接口beign不兼容的错误(SAP没有提供IDL文件)。 I don't know how IIOP and CORBA determine whether an interface is compatible.
我不知道IIOP和CORBA如何确定接口是否兼容。 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.
但我甚至尝试调试IIOP.NET代码并强制它执行该方法,尽管不兼容,但收到一个空字符串而不是我想要的硬件密钥。
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. 我的下一步是尝试实现虚假的许可证服务器并检查来自生产客户端的请求,以期确定它们应该是什么样子,但考虑到我遇到的困难,我并不指望取得多大的成功。深入了解.NET远程的内容。
My real problem is how to get or generate the SAP Business One hardware key, but questions stemming from that include: 我真正的问题是如何获取或生成SAP Business One硬件密钥,但由此产生的问题包括:
Edit: I managed to make IIOP.NET / CORBA believe that I had a compatible interface by applying the RepositoryID attribute: 编辑:我设法通过应用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);
}
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. 编辑2:经过一些实验和调试之后,我发现响应消息确实包含了我正在寻找的数据,但是没有正确地解析成客户端值,可能是因为我的接口定义不好。 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.
奇怪的是,它从响应中解析的第一件事是一个空的盒装值,这似乎不适合“out string”参数。
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: 编辑3:我发现我需要将字符串属性应用于这样的参数,以防止它们被视为盒装值:
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. 但是,尽管有WideChar属性,我对CodeSet不支持WChar或其他东西的错误。 I'm getting really close to figuring this out.
我已经非常接近搞清楚了。
Edit 4: I am stumped at how to set the codeset for WChar. 编辑4:我对如何为WChar设置代码集感到困惑。 If I do not set it, I receive an error: "WChar Codeset either not specified or not supported."
如果我没有设置它,我收到一个错误:“未指定或不支持WChar代码集。” because the server has returned a unicode string without overriding the default character set.
因为服务器返回了一个unicode字符串而没有覆盖默认字符集。 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?
我唯一的选择是为了我自己的目的重写IIOP.NET代码,强制默认的WChar CodeSet生效?
After 3 days of debugging into IIOP to track down its behavior and inspect the data coming back in the response, I have settled on this solution. 经过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));
}
}
I temporarily was also using this in an attempt to make IIOP give me back the right strings. 我暂时也在使用它,试图让IIOP给我回正确的字符串。 If it had occurred to me that I could simply accept the reply as a byte array and perform the decoding myself, I wouldn't have wasted half the time trying to work out how to get IIOP to understand how I wanted my string back:
如果我发现我可以简单地接受回复作为字节数组并自己执行解码,我不会浪费一半时间试图找出如何让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;
...
}
After that much code ran, I had an object that would define the WChar CodeSet so it would parse the return strings properly, avoiding the "WChar CodeSet either not specified or not supported" error. 在运行了很多代码之后,我有了一个定义WChar CodeSet的对象,因此它会正确解析返回字符串,避免“未指定或不支持WChar CodeSet”错误。 But after all that, the Unicode byte ordering was backwards too!
但毕竟,Unicode字节顺序也是倒退的! And the only way to fix that, as far as I could tell, was to re-parse the string into bytes and then back into a Unicode string.
据我所知,解决这个问题的唯一方法是将字符串重新解析为字节,然后再重新解析为Unicode字符串。 But that's when it occurred to me, why even ask for the result as a string!?
但是,当我遇到这种情况时,为什么甚至要求将结果作为字符串!? I could just take the bytes directly and avoid so much of this complication.
我可以直接获取字节并避免这种复杂化。 I wish I had thought of that earlier.
我希望我早点想到这一点。
SAP BO 882 //LicenseInterface.idl SAP BO 882 //LicenseInterface.idl
typedef sequence<octet> 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 SBOLicense.idl
typedef sequence<octet> 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);
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.