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

Blu*_*kMN 9 .net c# remoting corba iiop

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

所以我下载了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);
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

void GetHardwareKey([StringValue(), WideChar(true)] out string hwKey);
Run Code Online (Sandbox Code Playgroud)

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

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

omg.org.CORBA.OrbServices.GetSingleton().OverrideDefaultCharSets(
    CharSet.UTF8, WCharSet.UTF16);
Run Code Online (Sandbox Code Playgroud)

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

Blu*_*kMN 8

经过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));
    }
}
Run Code Online (Sandbox Code Playgroud)

我暂时也在使用它,试图让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;
...
    }
Run Code Online (Sandbox Code Playgroud)

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