I'm working on a project that's a .NET extension to a rather large classic ASP project, using a lot of C++ COM objects that have been around in our code base forever. Unfortunately, there's a lot of hack-ish code on the C++ side, and I fear that I'm not experienced enough to work out the problem I've encountered.
In a nutshell, I can instantiate the COM object in question and Visual Studio tells me that I should be able to make calls to its "methods" (in quotes because they're actually exposed as parameterized properties). However, any method I try to call gives me the error "Indexed property 'CoreAspLib.IComUser.LoginUser' has non-optional arguments which must be provided." The thing is, I'm using the exact same parameters that were used back in the classic ASP world, and even the IntelliSense help for the properties tells me I'm using the right set of parameters. For example, the "LoginUser" property's signature is "dynamic IComUser.get_LoginUser(string username, string password)" and I'm calling it with two strings, but I still get the "non-optional arguments" error.
Here's some relevant code - first, the class where I'm trying to make the method call. CComUtils
is a helper class that just takes the COM's GUID and a reference to the target object, creates an instance of the desired COM object, and assigns the target reference 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's the actual method signature from the COM object's source:
STDMETHODIMP CComUser::get_LoginUser(BSTR bsUserName, BSTR bsPassword, IDispatch ** pResult)
Here's the interface definition from the 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's the coclass definition:
[
uuid(BF748C0A-450D-4EAF-8C39-A36F6B455587),
helpstring("ComUser Class")
]
coclass ComUser
{
[default] interface IComUser;
};
What should I do?
Edit: I should mention that I wasn't initially using named parameters; I just tried that in my efforts to make the error go away.