COM Interop: проблемы с индексированными свойствами - PullRequest
5 голосов
/ 30 сентября 2010

Я работаю над проектом, который является расширением .NET для довольно большого классического ASP-проекта, использующего множество COM-объектов C ++, которые всегда были в нашей базе кода.К сожалению, на стороне C ++ много хакерского кода, и я боюсь, что у меня недостаточно опыта, чтобы решить проблему, с которой я столкнулся.

В двух словах, я могу создать экземпляр COMрассматриваемый объект, и Visual Studio говорит мне, что я должен иметь возможность вызывать его "методы" (в кавычках, потому что они фактически представлены как параметризованные свойства).Однако любой метод, который я пытаюсь вызвать, выдает ошибку «Индексированное свойство 'CoreAspLib.IComUser.LoginUser' имеет необязательные аргументы, которые должны быть предоставлены".Дело в том, что я использую те же параметры, которые использовались в классическом мире ASP, и даже справка по свойствам IntelliSense говорит мне, что я использую правильный набор параметров.Например, подпись свойства «LoginUser» - «dynamic IComUser.get_LoginUser (string username, string password)», и я вызываю его с двумя строками, но все равно получаю ошибку «необязательные аргументы».

Вот некоторый соответствующий код - во-первых, класс, в котором я пытаюсь сделать вызов метода.CComUtils - это вспомогательный класс, который просто принимает GUID COM и ссылку на целевой объект, создает экземпляр требуемого COM-объекта и назначает целевую ссылку для нового объекта.

public static class CurrentUser
{
    public static void Authenticate(string userName, string password)
    {
        CoreAspLib.ComUser userObject = Cache.Request<CoreAspLib.ComUser>("UserComObject");

        if (userObject == null) {
            Guid userGuid = new Guid("BF748C0A-450D-4EAF-8C39-A36F6B455587");
            CComUtils.CreateCOMInstance(userGuid, ref userObject);
            Cache.Request("UserComObject", userObject);
        }

        var result = userObject.LoginUser(sUserName:"foo", sPassword:"bar");

        if (result.Failed) {
            throw (new System.Security.Authentication.InvalidCredentialException("Bad username or password".tr()));
        } else {
            FormsAuthentication.SetAuthCookie(userName, false);
        }
    }
}

Вотфактическая сигнатура метода из источника COM-объекта:

STDMETHODIMP CComUser::get_LoginUser(BSTR bsUserName, BSTR bsPassword, IDispatch ** pResult)

Вот определение интерфейса из IDL:

[
    object,
    uuid(1F4D8A57-BDE1-4D47-A9BC-5F541A0ED184),
    dual,
    nonextensible,
    helpstring("IComUser Interface"),
    pointer_default(unique)
]
interface IComUser : IDispatch{
    [propget, id(1), helpstring("property LoginUser")] HRESULT LoginUser([in] BSTR sUserName, [in] BSTR sPassword, [out, retval] IDispatch ** pResult);
    [propget, id(2), helpstring("property m_nUserID")] HRESULT m_nUserID([out, retval] ULONG* pVal);
    [propget, id(3), helpstring("property m_nUserRightsMask")] HRESULT m_nUserRightsMask([out, retval] ULONG* pVal);
    [propget, id(4), helpstring("property SetPassword")] HRESULT SetPassword([in] BSTR sPassword, [in,optional] VARIANT nUserID, [out, retval] IDispatch ** pResult);
    [propget, id(6), helpstring("property VerifyLdapCredentials")] HRESULT VerifyLdapCredentials([in]BSTR sUserName, [in]BSTR sPassword, [in]BSTR sLdapServer,[in]ULONG nLdapPort,[in]BSTR sAuthorizeDn,[in]VARIANT_BOOL bSecure, [out, retval] IDispatch ** pResult);
    [propget, id(7), helpstring("property CreateUser")] HRESULT CreateUser([in] BSTR sUserName, [in] BSTR sPassword, [in]ULONG nUserRightsMask, [in] ULONG nAuthenticationType, [in] ULONG nHomeGroupID, [in] ULONG nLanguageID, [out, retval] IDispatch** pVal);
    [propget, id(8), helpstring("property m_nLanguageID")] HRESULT m_nLanguageID([out, retval] ULONG* pVal);
};

И, наконец, вот определение кокласса:

[
    uuid(BF748C0A-450D-4EAF-8C39-A36F6B455587),
    helpstring("ComUser Class")
]
coclass ComUser
{
    [default] interface IComUser;
};

Что мне делать?

Редактировать: я должен отметить, что изначально я не использовал именованные параметры;Я только что попробовал это, пытаясь устранить ошибку.

1 Ответ

13 голосов
/ 30 сентября 2010

Хм, ваш код предполагает, что вы на самом деле используете C # 4.0, поскольку используете именованные параметры.Эта версия поддерживает индексированные свойства в сценариях взаимодействия COM.Однако синтаксис индексатора требует [квадратных скобок].Не знаю, работает ли он с более чем одним аргументом, во всех примерах только один.Попробуйте сначала:

 var result = userObject.LoginUser["foo", "bar"];

Или решите проблему с:

 var result = userObject.get_LoginUser("foo", "bar");

Пожалуйста, дайте нам знать, что вы узнали, мне интересно узнать, если индексированные свойства с несколькими аргументамиподдерживается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...