none
Aufruf von COM-Methoden deren Argumente ByRef übergeben werden müssen RRS feed

  • Allgemeine Diskussion

  • Hallo Community,

    ich habe eine COM-Bibliothek die Methoden besitzt, deren Argumente ByRef definiert sind, z.B. Method GetVersion(ByRef majorVersion As Long) As WString. Die Methoden dieser COM-Bibliothek lassen sich nicht mit der Standardvorgehensweise ansprechen, so dass ich den Weg über InvokeMember/InvokeMethod gehen muss.

    #-Begin------------------------------------------------
    
      $Lib = $null
      try{
        $Lib = New-Object -ComObject COMLIB
      }
      catch{
        $rc = [System.Windows.Forms.MessageBox]::Show(
          "Can't create object COMLib", "Important hint", 0)
      }  
    
      if ($Lib -ne $null) {
        
        [int]$Major = 0
        [Object[]]$Argument = $Major
    
        [System.Reflection.ParameterModifier[]]$Modifier
        $Modifier += $Major.GetType().MakeByRefType()
    
        $Version = $Lib.GetType().InvokeMember("GetVersion",
          [System.Reflection.BindingFlags]::InvokeMethod,
          $null, $Lib, $Argument, $Modifier, $null, $null)
          
        $MsgBoxTxt = "MajorVersion: " + $Major
    
        $rc = [System.Windows.Forms.MessageBox]::Show($MsgBoxTxt, "", 0)
    
        $rc = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Lib)
      }  
      Remove-Variable Lib
    
    #-End--------------------------------------------------
    

    Wie ist via Invoke die richtige Vorgehensweise um ByRef definierte out-Argumente an eine COM-Methode zu übergeben resp. einen Rückgabewert zu erhalten?

    Mit meinem obigen Ansatz erhalte ich die folgende Fehlermeldung: Der Wert "type MakeByRefType()" vom Type "System.Management.Automation.PSMethod" kann nicht in den Typ "System.Reflection.ParameterModifier" konvertiert werden.

    Vielen Dank für Antworten und Tipps.

    Beste Grüße
    Stefan

    Sonntag, 4. Mai 2014 05:42

Alle Antworten

  • Hallo Stefan!

    Der [Ref] Moifizierer müste es tun.

    Ungetested:

    #-Begin------------------------------------------------
    
      $Lib = $null
      try{
        $Lib = New-Object -ComObject COMLIB
      }
      catch{
        $rc = [System.Windows.Forms.MessageBox]::Show(
          "Can't create object COMLib", "Important hint", 0)
      }  
    
      if ($Lib -ne $null) {
        
        [int]$Major = 0
    
        $Version = $Lib.GetType().InvokeMember("GetVersion",
          [System.Reflection.BindingFlags]::InvokeMethod,
          $null, $Lib, [Ref]$Major, $Modifier, $null, $null)
          
        $MsgBoxTxt = "MajorVersion: " + $Major
    
        $rc = [System.Windows.Forms.MessageBox]::Show($MsgBoxTxt, "", 0)
    
        $rc = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Lib)
      }  
      Remove-Variable Lib
    
    #-End--------------------------------------------------


    PowerShell Artikel, Buchtipps und kostenlose PowerShell Tutorials + E-Books
    auf der deutschsprachigen PowerShell Community

    Mein 21 Teiliger PowerShell Video Grundlehrgang
    Deutsche PowerShell Videos auf Youtube
    Folge mir auf:
    Twitter | Facebook | Google+

    Sonntag, 4. Mai 2014 09:30
  • Hallo Peter,

    vielen Dank für Deine schnelle Antwort. Leider funktioniert [ref] nicht. Ich habe es u.a. wie folgt probiert:

    #-Begin------------------------------------------------
    
      $Lib = $null
      try{
        $Lib = New-Object -ComObject COMLIB
      }
      catch{
        $rc = [System.Windows.Forms.MessageBox]::Show(
          "Can't create object COMLib", "Important hint", 0)
      }  
    
      if ($Lib -ne $null) {
        
        [int]$Major = 0
        [Object[]]$Argument = [ref]$Major
    
        $Version = $Lib.GetType().InvokeMember("GetVersion",
          [System.Reflection.BindingFlags]::InvokeMethod,
          $null, $Lib, $Argument, $null, $null, $null)
          
        $MsgBoxTxt = "MajorVersion: " + $Major
    
        $rc = [System.Windows.Forms.MessageBox]::Show($MsgBoxTxt, "", 0)
    
        $rc = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Lib)
      }  
      Remove-Variable Lib
    
    #-End--------------------------------------------------

    Hier kommt der Fehler: Ausnahme beim Aufrufen von "InvokeMember" mit 8 Argument(en): "Typkonflikt. (Ausnahme von HRESULT: 0x80020005 (DISP_E_TYPEMISMATCH))"

    Der Weg über [Object[]]$Argument ist für mich wichtig, da ich auch Methoden habe, die mehrere Argumente besitzen.

    Hast Du noch eine weitere Idee?

    Vielen Dank und beste Grüße
    Stefan

    Sonntag, 4. Mai 2014 17:37
  • Ich habe die COMLIB nicht deshalb ist es sehr schwer für mich dir zu helfen.

    Die Fehlermeldung weist darauf hin das der Typ falsch ist.

    Deshalb probierst du es am besten mal ohne die Typisierung [int]

    #-Begin------------------------------------------------
    
      $Lib = $null
      try{
        $Lib = New-Object -ComObject COMLIB
      }
      catch{
        $rc = [System.Windows.Forms.MessageBox]::Show(
          "Can't create object COMLib", "Important hint", 0)
      }  
    
      if ($Lib -ne $null) {
        
        $Major = 0
        [Object[]]$Argument = [ref]$Major
    
        $Version = $Lib.GetType().InvokeMember("GetVersion",
          [System.Reflection.BindingFlags]::InvokeMethod,
          $null, $Lib, $Argument, $null, $null, $null)
          
        $MsgBoxTxt = "MajorVersion: " + $Major
    
        $rc = [System.Windows.Forms.MessageBox]::Show($MsgBoxTxt, "", 0)
    
        $rc = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Lib)
      }  
      Remove-Variable Lib
    
    #-End--------------------------------------------------

    Der Weg über [Object[]]$Argument ist für mich wichtig, da ich auch Methoden habe, die mehrere Argumente besitzen.

    Das ist erst der Zweite Schritt! Erstmal herausbekommen wie es grundsätzlich geht!



    PowerShell Artikel, Buchtipps und kostenlose PowerShell Tutorials + E-Books
    auf der deutschsprachigen PowerShell Community

    Mein 21 Teiliger PowerShell Video Grundlehrgang
    Deutsche PowerShell Videos auf Youtube
    Folge mir auf:
    Twitter | Facebook | Google+



    Montag, 5. Mai 2014 05:18
  • Hallo Peter,

    entschuldige meine Antwortverzögerung.

    Leider haben Deine Vorschläge nicht den gewünschten Erfolg gebracht, siehe die Kommentare im Listing.

    #-Begin-----------------------------------------------------------------
    
      $ComObj = $null
      try{
        $ComObj = New-Object -ComObject COMOBJ
      }
      catch{
        $rc = [System.Windows.Forms.MessageBox]::Show(
          "Can't create object COMOBJ", "Important hint", 0)
      }  
    
      if ($ComObj -ne $null) {
        
        #-Ein Argument------------------------------------------------------
          #Die explizite Typangabe macht keinen Unterschied
          #$Major1 = 0
          [int]$Major1 = 0
          [Object[]]$Arguments1 = $Major1
    
          #Die Nutzung von Referenzen [ref] führt zu Typkonflikten
          #[Object[]]$Arguments1 = [ref]$Major1
          
          $Version1 = $ComObj.GetType().InvokeMember("GetVersion",
            [System.Reflection.BindingFlags]::InvokeMethod,
            $null, $ComObj, $Arguments1, $null, $null, $null)
            #Die Nutzung von Referenzen [ref] führt zu PSReference-Fehler
            #$null, $ComObj, [ref]$Major1, $null, $null, $null)
    
          $MsgBoxTxt = "MajorVersion: " + $Major1
          $MsgBoxTxt = $MsgBoxTxt + "`r`n"
          $MsgBoxTxt = $MsgBoxTxt + "Version: " + $Version1
    
          $rc = [System.Windows.Forms.MessageBox]::Show($MsgBoxTxt, "", 0)
    
        #-Zwei Argumente----------------------------------------------------
          [int]$Major2 = 0
          [int]$Minor2 = 0
          [Object[]]$Arguments2 = $Major2, $Minor2
    
          $Version2 = $ComObj.GetType().InvokeMember("GetVersion2",
            [System.Reflection.BindingFlags]::InvokeMethod,
            $null, $ComObj, $Arguments2, $null, $null, $null)
          
          $MsgBoxTxt = "MajorVersion: " + $Major2
          $MsgBoxTxt = $MsgBoxTxt + "`r`n"
          $MsgBoxTxt = $MsgBoxTxt + "MinorVersion: " + $Minor2
          $MsgBoxTxt = $MsgBoxTxt + "`r`n"
          $MsgBoxTxt = $MsgBoxTxt + "Version: " + $Version2
    
          $rc = [System.Windows.Forms.MessageBox]::Show($MsgBoxTxt, "", 0)
    
        $rc = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($ComObj)
      }  
      Remove-Variable ComObj
    
    #-End-------------------------------------------------------------------

    Als VBScript funktioniert es wunderbar:

    '-Begin-----------------------------------------------------------------
    
      '-Variables-----------------------------------------------------------
        Dim oCom
        Dim res1, major1
        Dim res2, major2, minor2
    
      '-Main----------------------------------------------------------------
        Set oCom = CreateObject("COMOBJ")
        
        If IsObject(oCom) Then
    
          res1 = oCom.GetVersion(major1)
          MsgBox res1 & " " & CStr(major1)
    
          res2 = oCom.GetVersion2(major2, minor2)
          MsgBox res2 & " " & CStr(major2) & " " & CStr(minor2)
          
          Set oCom = Nothing
        
        End If
    
    '-End-------------------------------------------------------------------
    

    Ich bin für weitere Tipps und Hinweise dankbar.

    Beste Grüße
    Stefan

    Donnerstag, 8. Mai 2014 04:45
  • Hallo Alex,

    Danke für Deine Rückfrage. Leider bin ich hier noch nicht weitergekommen, hast Du eine Idee?

    Vielen Dank und beste Grüße
    Stefan

    Donnerstag, 29. Mai 2014 07:48