如何访问CORBA接口,而IDL或后期绑定调用远程方法 [英] How to access CORBA interface without IDL or late-bound invoke remoting methods

查看:673
本文介绍了如何访问CORBA接口,而IDL或后期绑定调用远程方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们一直在使用SAPCOM许可证桥访问他们的许可证服务器和查询系统的硬件按键编程(重用与出自己的牌)。这工作正常的SAP Business One的版本2007A,2007B和8.8,但在8.81,他们似乎已经更新了他们的CORBA接口,而无需更新COM包装,因为我们正试图调用GetHardwareKey功能时出现内存不足异常。

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.

所以,我下载IIOP.NET,开始尝试写我自己的界面。我从来不喜欢的COM包装反正。但是,我遇到了我的老克星NET远程的 - 无法无需在服务器和客户端中定义一个通用的接口来调用一个远程方法。我试着用IDL到CLS的编译器包含IIOP.NET,但我不断地获得接口beign不兼容(SAP没有提供一个IDL文件)的错误。我不知道该怎么IIOP和CORBA确定的接口是兼容的。不过,我甚至尝试调试到IIOP.NET code和迫使它尽管不兼容要执行的方法,但收到一个空字符串后面,而不是硬件密钥我想要的。

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.

我的下一步是设法实现一个假牌照服务器,然后检查从生产端进来确定他们的的希望的请求应的样子,但我不指望很多成功的考虑我已经在窥视到.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.

我的真正的问题是如何获得或产生的SAP Business One的硬件密钥,但问题而产生的,其中包括:

My real problem is how to get or generate the SAP Business One hardware key, but questions stemming from that include:

  1. 如何反映或查询有关CORBA接口的信息?我可以使用的NamingContext类的列表方法来检索可用对象的列表,但我没有看到,如果有一种方法可以查询可用的方法的对象上。
  2. 可以动态调用.NET远程方法,而无需一个接口?我看到有一些所谓的DII动态调用CORBA,但我看不出如何从IIOP.NET使用它。
  3. 我可以调用.NET远程方法只是一个委托或不完整的接口?我试着用动态的关键字,但它不能在我的MarshalByRef远程对象调用的方法...我认为这说的方法并没有对我的MarshalByRef实例或东西存在。我只是通过IIOP.NET试过,但(我不知道,如果它工作正常.NET远程)。
  4. 在.NET远程处理框架如何创建或检查消息实例?
  5. 可以发送或检索直接远程处理的消息,绕过底层的代理?

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

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.

编辑2:经过一些试验和调试,我发现,响应消息确实包含我正在寻找的资料,但并不被解析成客户端值正常,可能是因为我的坏接口定义。希望调试到响应处理将进一步帮助我弄清楚如何纠正我的界面。奇怪的第一件事,它从响应解析为空装箱值,这似乎不适合的出字符串参数。

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.

修改3:我发现,我需要申请字符串属性,像这样的参数prevent它们被视为盒装值:

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

但是,尽管WideChar属性,我得到的连接有关codeSET不支持WCHAR什么错误。我得到的真正的接近搞清楚了这一点。

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.

修改4:我难倒如何设置codeSET为WCHAR。如果我没有设置它,我收到一个错误:WCHAR codeSET未指定或不支持因为服务器返回一个单code字符串没有覆盖默认字符集。我找不到任何方法来覆盖从客户端。我打过电话:

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

但是,这似乎并没有对客户端没有任何影响。这个例子code显示调用一个在服务器端。但我没有写服务器,所以我无法控制的。是重写IIOP.NET code为我自己的目的强迫默认WCHAR codeSET才能生效我唯一的选择?

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?

推荐答案

3天之后的调试成IIOP追查其行为,并检查回来在响应中的数据,我也看中了这个解决方案。

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.

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明白我是多么希望我的字符串返回:

I temporarily was also using this in an attempt to make IIOP give me back the right strings. 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:

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;
...
    }

在那么多code跑了,我有一个对象,将定义WCHAR codeSET所以它会正确地解析返回的字符串,避免了WCHAR codeSET未指定或不支持错误。但毕竟如此,统一code字节顺序是倒退呢!而只有这样,才能解决这个问题,据我所知,是要重新解析字符串转换成字节,然后回一个统一code字符串。但是,这时候我突然想到,为什么连问的结果作为一个字符串!?我可以把字节直接,避免这么多的这种并发症。我希望我原以为前面的。

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. But after all that, the Unicode byte ordering was backwards too! 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. 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.

这篇关于如何访问CORBA接口,而IDL或后期绑定调用远程方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆