4

I have a method named GoLogon in a COM object named BS.Logon which requires 5 parameters:

  • Username
  • Password
  • ApplicationID
  • XMLRoot
  • IPAddress

This method logins to the web server with the username, password, and other details, and returns the session ID.

I have written the Powershell script to call the method GoLogon as below.

$obj=New-Object -ComObject BS.Logon
$sessionid=$obj.GoLogon([ref]$bUsername,$bPassword,$appid,$xmlroot,[ref]$ipad)
Write-Host $sessionid

When the script is executed, the method makes successful login. I can see the session ID details in the database, but I am not able to get the session ID details through script. The variable $sessionid returns null. Also the script throws exception as

Exception calling "GoLogon" with "5" argument(s): "Invalid callee. (Exception from HRESULT: 0x80020010 (DISP_E_BADCALLEE))"
At E:\Logon.ps1:18 char:1
+ $obj.Login([ref]$bUsername,$bPassword,$appid,$xmlroot,[ref]$ipad)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation`

The stacktrace is:

Exception             : System.Management.Automation.MethodInvocationException: Exception calling "GoLogon" with "5" argument(s): "Invalid callee. (Exception from HRESULT: 0x80020010 (DISP_E_BADCALLEE))" ---> System.Reflection.TargetInvocationException: 
Exception has been thrown by the target of an invocation. ---> System.Runtime.InteropServices.COMException: Invalid callee. (Exception from HRESULT: 0x80020010 (DISP_E_BADCALLEE))
--- End of inner exception stack trace ---
at System.RuntimeType.InvokeDispMethod(String name, BindingFlags invokeAttr, Object target, Object[] args, Boolean[] byrefModifiers, Int32 culture, String[] namedParameters)
at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
at System.Management.Automation.ComMethod.InvokeMethod(PSMethod method, Object[] arguments)
--- End of inner exception stack trace ---
at System.Management.Automation.ComMethod.InvokeMethod(PSMethod method, Object[] arguments)
at System.Management.Automation.Adapter.BaseMethodInvoke(PSMethod method, PSMethodInvocationConstraints invocationConstraints, Object[] arguments)
at System.Dynamic.UpdateDelegates.UpdateAndExecute6[T0,T1,T2,T3,T4,T5,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
at System.Management.Automation.Interpreter.DynamicInstruction 7.Run(InterpretedFrame frame) at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
TargetObject          : 
CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
FullyQualifiedErrorId : ComMethodTargetInvocation
ErrorDetails          : 
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, E:\Logon.ps1: line 18
PipelineIterationInfo : {}
PSMessageDetails      :

Please suggest me how to get the session ID value from the method.

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
Basavaraju B K
  • 71
  • 2
  • 11
  • Your problem is most likely that you are using [ref] in your parameters. *"[ref] is used by COM or RPC to declare pointer attributes. [ref] in .NET is used for parameter re-direction. These are in no way compatible."* – Jan Chrbolka May 29 '15 at 00:54
  • @Jan Chrbolka actually those two [ref] parameters which are arguments to method refers to pointers variables in COM. – Basavaraju B K May 29 '15 at 02:11
  • This has always been a problem for me in PowerShell. Have a look here ...[RE: "Invalid callee" calling a com object](http://www.archivum.info/microsoft.public.windows.powershell/2010-01/00361/RE--quot-Invalid-callee-quot--calling-a-com-object.html) This describes how to use a Variant wrapper. It may work in your case. `$variable = new-object object $wrapper = New-Object Runtime.InteropServices.VariantWrapper($variable) ## now call the method with the wrapped object $object.method([ref] $wrapper )` – Jan Chrbolka May 29 '15 at 02:20
  • @Jan Chrbolka Even I tried with the wrapper, but the script throws another exception. Can you please provide the wrapper usage for my script? Also forgot to mention, The method returns a pointer value. – Basavaraju B K May 29 '15 at 04:06
  • Sorry, that was a long shot, as I'm definitely no expert at .COM. Do you have source code for the .COM object? Could you add that to the question? Or at least show definitions for the ByRef parameters? For the wrapper in your code, `$wrapbUservame = New-Object Runtime.InteropServices.VariantWrapper($bUsername) $sessionid=$obj.GoLogon([ref]$wrapbUservame .... ` and the same for IP – Jan Chrbolka May 29 '15 at 04:44
  • @Basavaraju B K, you should give the C++ signature of Gologon method. – JPBlanc May 29 '15 at 05:01
  • @JanChrbolka This is the definition of the GoLogon method; `string GoLogon (Variant, string, string, string, Variant) ` @JPBlanc The signature of the GoLogon method in C++ `STDMETHODIMP CLOG::GOLogon(VARIANT *pvEmailId, BSTR bsPassword, BSTR bsIPAddress, BSTR bsSoloBuildVer, VARIANT *pvXML, BSTR *bsSessionId)` So here `BSTR *bsSessionId` will be returned. – Basavaraju B K May 29 '15 at 05:29
  • @JanChrbolka Thanks for the help. Wrapper worked. Now I am able to get the session id from the method. – Basavaraju B K May 29 '15 at 06:00
  • Glad it did. I will try and put all of the above into an answer. – Jan Chrbolka May 29 '15 at 06:04
  • @JanChrbolka Go Ahead. It Will be helpful for many. – Basavaraju B K May 29 '15 at 06:10
  • @JPBlanc Thanks for you too. – Basavaraju B K May 29 '15 at 06:10
  • @Basavaraju B K, Can you check that the answer reflects the code that worked for you in the end? Thanks. Jan – Jan Chrbolka May 29 '15 at 06:20
  • @JanChrbolka It works perfectly. – Basavaraju B K May 29 '15 at 06:40

1 Answers1

2

PowerShell seems to have a problem with COM parameters defined as VARIANT.

This is the case here, as the C++ signature of GoLogon suggests.

STDMETHODIMP CLOG::GOLogon(VARIANT *pvEmailId, BSTR bsPassword, BSTR bsIPAddress, BSTR bsSoloBuildVer, VARIANT *pvXML, BSTR *bsSessionId)

The answer suggested in this post "Invalid callee" calling a com object is to use a VariantWrapper.

In you case this should do the trick.

#define VariantWrapper for variables to be passesed as VARIANT
$wrapbUservame = New-Object Runtime.InteropServices.VariantWrapper($bUsername) 
$wrappvXML = New-Object Runtime.InteropServices.VariantWrapper($pvXML)

#pass a [ref]VariantWrapper to .COM method
$sessionid=$obj.GoLogon([ref]$wrapbUservame,$bPassword,$appid,[ref]$wrappvXML,$ipad)
Jan Chrbolka
  • 4,184
  • 2
  • 29
  • 38