I am working on a project that extends .NET to a fairly large classic ASP project, using the many C ++ COM objects that have been in our code base forever. Unfortunately, there is a lot of hacker code on the C ++ side, and I'm afraid that I am not experienced enough to solve the problem that I am facing.
In short, I can create an instance of the COM object in question, and Visual Studio tells me that I should be able to make calls to its βmethodsβ (in quotation marks because they are actually displayed as parameterized properties). However, any method I try to call gives me the error "Indexed property" CoreAspLib.IComUser.LoginUser "has optional arguments that must be provided." The fact is that I use the same parameters that were used in the classic ASP world, and even IntelliSense help for properties tells me that I use the correct set of parameters. For example, the signature of the LoginUser property is "dynamic IComUser.get_LoginUser (string username, string password)" and I call it with two strings, but I still get the "optional arguments" error.
Here is some relevant code - firstly, a class where I am trying to call a method call. CComUtils is a helper class that simply accepts a COM identifier and a link to the target object, instantiates the desired COM object, and assigns the target link to the new object.
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); } } }
Here is the actual method signature from the source of the COM object:
STDMETHODIMP CComUser::get_LoginUser(BSTR bsUserName, BSTR bsPassword, IDispatch ** pResult)
Here is the interface definition from 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); };
And finally, here is the definition of a co-class:
[ uuid(BF748C0A-450D-4EAF-8C39-A36F6B455587), helpstring("ComUser Class") ] coclass ComUser { [default] interface IComUser; };
What should I do?
Edit: I should mention that I did not initially use named parameters; I just tried to do this, trying to make a mistake.