9

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

所以我下载了 IIOP.NET 并开始尝试编写自己的界面。反正我从不喜欢那个 COM 包装器。但是我遇到了 .NET 远程处理的老对手——如果没有在服务器和客户端中定义的公共接口,就无法调用远程方法。我尝试使用 IIOP.NET 中包含的 IDL 到 CLS 编译器,但我继续收到有关接口不兼容的错误(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:经过更多的实验和调试,我发现响应消息确实包含我正在寻找的数据,但没有正确解析为客户端值,可能是因为我的接口定义错误。希望进一步调试响应处理将帮助我弄清楚如何更正我的界面。奇怪的是,它从响应中解析的第一件事是一个空框值,这对于“输出字符串”参数似乎不正确。

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

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

但是,尽管有 WideChar 属性,但我收到关于 CodeSet 不支持 WChar 或其他东西的错误。我真的很接近弄清楚这一点。

编辑 4:我对如何为 WChar 设置代码集感到困惑。如果我没有设置它,我会收到一个错误:“WChar Codeset 要么未指定或不受支持。” 因为服务器返回了一个 unicode 字符串而没有覆盖默认字符集。我找不到任何方法可以从客户端覆盖它。我试着打电话:

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

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

4

2 回答 2

8

在对 IIOP 进行了 3 天的调试以跟踪其行为并检查响应中返回的数据后,我决定采用此解决方案。

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 字符串。但这就是我想到的时候,为什么还要以字符串形式要求结果!?我可以直接获取字节并避免这种复杂性。我希望我早点想到这一点。

于 2011-05-18T16:44:05.973 回答
3

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

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);
};
于 2012-06-21T04:18:40.327 回答