Как получить доступ к интерфейсу CORBA без IDL или методов удаленного вызова с поздним связыванием - PullRequest
9 голосов
/ 17 мая 2011

Мы использовали SAP "COM License Bridge" для доступа к их серверу лицензий и программного запроса аппаратного ключа системы (для повторного использования без собственного лицензирования).Это хорошо работало на версиях SAP Business One 2007A, 2007B и 8.8, но в 8.81 они, похоже, обновили свой интерфейс CORBA без обновления оболочки COM, потому что теперь мы получаем исключения из памяти при попытке вызвать функцию GetHardwareKey.

Поэтому я скачал IIOP.NET и начал пытаться написать свой собственный интерфейс.Мне никогда не нравилась эта оболочка COM.Но я столкнулся со своим старым врагом удаленного взаимодействия в .NET - невозможностью вызова удаленного метода без общего интерфейса, определенного как на сервере, так и на клиенте.Я попытался использовать компилятор IDL для CLS, включенный в IIOP.NET, но продолжаю получать ошибки о несовместимости интерфейса (SAP не предоставил файл IDL).Я не знаю, как IIOP и CORBA определяют, совместим ли интерфейс.Но я даже попытался отладить код IIOP.NET и заставить его выполнить метод, несмотря на несовместимость, но получил пустую строку вместо желаемого аппаратного ключа.

Мой следующий шаг - попытаться реализоватьфальшивый сервер лицензий и изучите запросы, поступающие от производственного клиента, в надежде определить, как они должны выглядеть, но я не рассчитываю на большой успех, учитывая трудности, с которыми я столкнулся ввнутренности удаленного взаимодействия .NET уже.

Моя настоящая проблема заключается в том, как получить или сгенерировать аппаратный ключ SAP Business One, но вытекающие из этого вопросы включают:

  1. Как мне отразитьили запросить информацию об интерфейсе CORBA?Я могу использовать метод list класса NamingContext для получения списка доступных объектов, но я не вижу, есть ли способ запросить доступные методы для объекта.
  2. Можно ли динамически вызывать удаленное взаимодействие .NETметоды без интерфейса?Я вижу, что есть что-то под названием DII для динамического вызова CORBA, но я не понимаю, как использовать это из IIOP.NET.
  3. Могу ли я вызывать методы удаленного взаимодействия .NET только с делегатом или неполным интерфейсом?Я попытался использовать динамическое ключевое слово, но он не смог вызвать метод для моего удаленного объекта MarshalByRef ... Я думаю, он сказал, что метод не существует в моем экземпляре MarshalByRef или что-то в этом роде.Я пробовал это только через IIOP.NET (интересно, работает ли он для обычного удаленного взаимодействия .NET).
  4. Как создать или проверить экземпляры сообщений в платформе удаленного взаимодействия .NET?
  5. Могу ли я отправлять или получать удаленные сообщения напрямую, минуя прокси-серверы?

Редактировать: Мне удалось заставить IIOP.NET / CORBA поверить, что у меня был совместимый интерфейс, применяяатрибут RepositoryID:

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

Но я все еще получаю результат пустой строки.

Edit 2: После еще нескольких экспериментов и отладки я обнаружил, чтоОтветные сообщения содержат данные, которые я ищу, но не анализируются в значениях клиента должным образом, возможно, из-за моего неверного определения интерфейса.Надеясь, что отладка в дальнейшей обработке ответов поможет мне понять, как исправить мой интерфейс.Как ни странно, первое, что он анализирует из ответа, это пустое значение в штучной упаковке, которое не подходит для параметра «out string».

Edit 3: Я обнаружил, что мне нужночтобы применить строковые атрибуты к таким параметрам, чтобы они не обрабатывались как упакованные значения:

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

Но, несмотря на атрибут WideChar, я получаю ошибку по поводу того, что CodeSet не поддерживает WChar или что-то в этом роде.Я действительно близок к тому, чтобы понять это.

Редактировать 4: Я поставлен в тупик, как установить кодовый набор для WChar. Если я не установил его, я получаю сообщение об ошибке: «WChar Codeset либо не указан, либо не поддерживается». потому что сервер возвратил строку юникода без переопределения набора символов по умолчанию. Я не могу найти способ переопределить это от клиента. Я пытался позвонить:

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

Но это, похоже, не влияет на клиентскую часть. Пример кода показывает вызов этого на стороне сервера. Но я не писал сервер, поэтому я не могу это контролировать. Является ли мой единственный вариант переписать код IIOP.NET для моих собственных целей, чтобы заставить WChar CodeSet по умолчанию вступить в силу?

Ответы [ 2 ]

8 голосов
/ 18 мая 2011

После 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. Но вот когда это пришло мне в голову, зачем даже спрашивать результат в виде строки !? Я мог бы просто взять байты напрямую и избежать такой сложности. Хотел бы я подумать об этом раньше.

3 голосов
/ 21 июня 2012

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