Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
stefan_schnell
Active Contributor
Over two years ago I presented COM Connector (CCo) here - CCo makes the using of the NetWeaver RFC library very easy.

Slowly but surely the landscape of the script language environments changed in Windows OS - from Windows Script Host (WSH) to PowerShell. From this point of view it seems good to take also a movement.

Here a PowerShell example how to get all installed SAP components and its version numbers in comparison with a VBScript which offers the same information.
#-Begin-----------------------------------------------------------------

#-Constants-----------------------------------------------------------
$RFC_OK = 0
$VarByRef = -1

#-Includes------------------------------------------------------------
."Includes\COM.ps1"

#-Function Get-SAPComponents------------------------------------------
Function Get-SAPComponents {

$SAP = $null
$SAP = Create-Object "COMNWRFC"
if ($SAP -eq $null) {
Break
}

$hRFC = Invoke-Method $SAP "RfcOpenConnection" @(
"ASHOST=NSP, SYSNR=00, CLIENT=001, USER=BCUSER")
if ($hRFC -eq 0) {
Free-Object $SAP
Break
}

$hFuncDesc = Invoke-Method $SAP "RfcGetFunctionDesc" @(
$hRFC, "DELIVERY_GET_INSTALLED_COMPS")
if ($hFuncDesc -eq 0) {
$rc = Invoke-Method $SAP "RfcCloseConnection" $hRFC
Free-Object $SAP
Break
}

$hFunc = Invoke-Method $SAP "RfcCreateFunction" $hFuncDesc
if ($hFunc -eq 0) {
$rc = Invoke-Method $SAP "RfcCloseConnection" $hRFC
Free-Object $SAP
Break
}

$rc = Invoke-Method $SAP "RfcInvoke" @($hRFC, $hFunc)
if ($rc -eq $RFC_OK) {

$rc = Invoke-Method $SAP "RfcGetTable" @(
$hFunc, "TT_COMPTAB", $VarByRef)
if ($rc -eq $RFC_OK) {

$hTable = Get-Property $SAP "lngByRef"
$rc = Invoke-Method $SAP "RfcGetRowCount" @(
$hTable, $VarByRef)
$RowCount = Get-Property $SAP "lngByRef"

$rc = Invoke-Method $SAP "RfcMoveToFirstRow" $hTable

for ($i = 1; $i -le $RowCount ; $i++) {

$Row = Invoke-Method $SAP "RfcGetCurrentRow" $hTable

$rc = Invoke-Method $SAP "RfcGetChars" @(
$Row, "COMPONENT", $VarByRef, 30)
$charBuffer = Get-Property $SAP "strByRef"
$txt = $txt + $charBuffer

$rc = Invoke-Method $SAP "RfcGetChars" @(
$Row, "RELEASE", $VarByRef, 10)
$charBuffer = Get-Property $SAP "strByRef"
$txt = $txt + $charBuffer

$rc = Invoke-Method $SAP "RfcGetChars" @(
$Row, "EXTRELEASE", $VarByRef, 10)
$charBuffer = Get-Property $SAP "strByRef"
$txt = $txt + $charBuffer

$rc = Invoke-Method $SAP "RfcGetChars" @(
$Row, "COMP_TYPE", $VarByRef, 1)
$charBuffer = Get-Property $SAP "strByRef"
$txt = $txt + $charBuffer + "`r`n"

if ($i -lt $RowCount) {
$rc = Invoke-Method $SAP "RfcMoveToNextRow" $hTable
}

}
}
}

$rc = Invoke-Method $SAP "RfcDestroyFunction" $hFunc
$rc = Invoke-Method $SAP "RfcCloseConnection" $hRFC
Free-Object $SAP
Remove-Variable SAP
$txt
}

#-Function Main-------------------------------------------------------
Function Main {
$Components = Get-SAPComponents
Write-Host $Components
}

#-Main----------------------------------------------------------------
Main

#-End-------------------------------------------------------------------

 

Here now the VBScript:
'-Begin-----------------------------------------------------------------

'-Directives----------------------------------------------------------
Option Explicit

'-Constants-----------------------------------------------------------
Const RFC_OK = 0

'-Function GetSAPComponents-------------------------------------------
Function GetSAPComponents()

'-Variables-------------------------------------------------------
Dim SAP, hRFC, rc, hFuncDesc, hFunc, hTable, RowCount, i, Row
Dim charBuffer, strText

Set SAP = CreateObject("COMNWRFC")
If Not IsObject(SAP) Then
Exit Function
End If

hRFC = SAP.RfcOpenConnection("ASHOST=NSP, SYSNR=00, " & _
"CLIENT=001, USER=BCUSER")
If hRFC = 0 Then
Set SAP = Nothing
Exit Function
End If

hFuncDesc = SAP.RfcGetFunctionDesc(hRFC, _
"DELIVERY_GET_INSTALLED_COMPS")
If hFuncDesc = 0 Then
rc = SAP.RfcCloseConnection(hRFC)
Set SAP = Nothing
Exit Function
End If

hFunc = SAP.RfcCreateFunction(hFuncDesc)

If hFunc = 0 Then
rc = SAP.RfcCloseConnection(hRFC)
Set SAP = Nothing
Exit Function
End If

If SAP.RfcInvoke(hRFC, hFunc) = RFC_OK Then
If SAP.RfcGetTable(hFunc, "TT_COMPTAB", hTable) = RFC_OK Then
rc = SAP.RfcGetRowCount(hTable, RowCount)
rc = SAP.RfcMoveToFirstRow(hTable)
For i = 1 To RowCount
Row = SAP.RfcGetCurrentRow(hTable)
rc = SAP.RfcGetChars(Row, "COMPONENT", charBuffer, 30)
strText = strText & Trim(charBuffer) & " "
rc = SAP.RfcGetChars(Row, "RELEASE", charBuffer, 10)
strText = strText & Trim(charBuffer) & " "
rc = SAP.RfcGetChars(Row, "EXTRELEASE", charBuffer, 10)
strText = strText & Trim(charBuffer) & " "
rc = SAP.RfcGetChars(Row, "COMP_TYPE", charBuffer, 1)
strText = strText & Trim(charBuffer) & vbCrLf
If i < RowCount Then
rc = SAP.RfcMoveToNextRow(hTable)
End If
Next
End If
End If

rc = SAP.RfcDestroyFunction(hFunc)
rc = SAP.RfcCloseConnection(hRFC)
Set SAP = Nothing

GetSAPComponents = strText
End Function

'-Sub Main------------------------------------------------------------
Sub Main()
MsgBox GetSAPComponents()
End Sub

'-Main----------------------------------------------------------------
Main

'-End-------------------------------------------------------------------

 

As you can see it is very comparable.

To establish the comparibility I use an include file, which stores the COM access routines like Create-Object, Invoke-Method etc.
#-Begin-----------------------------------------------------------------

#-Load assembly-------------------------------------------------------
[Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualBasic") > $Null
[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") > $Null

#-Function Create-Object----------------------------------------------
Function Create-Object([String]$objectName) {
try {
New-Object -ComObject $objectName
}
catch {
[Void] [System.Windows.Forms.MessageBox]::Show(
"Can't create object", "Important hint", 0)
}
}

#-Function Get-Object-------------------------------------------------
Function Get-Object([String]$pathName, [String]$class) {
[Microsoft.VisualBasic.Interaction]::GetObject($pathName, $class)
}

#-Sub Free-Object-----------------------------------------------------
Function Free-Object([__ComObject]$object) {
[Void] [System.Runtime.Interopservices.Marshal]::ReleaseComObject($object)
}

#-Function Get-Property-----------------------------------------------
Function Get-Property([__ComObject]$object, [String]$propertyName,
$propertyParameters) {
$objectType = [System.Type]::GetType($object)
$objectType.InvokeMember($propertyName,
[System.Reflection.Bindingflags]::GetProperty,
$null, $object, $propertyParameters)
}

#-Sub Set-Property----------------------------------------------------
Function Set-Property([__ComObject]$object, [String]$propertyName,
$propertyValue) {
$objectType = [System.Type]::GetType($object)
[Void] $objectType.InvokeMember($propertyName,
[System.Reflection.Bindingflags]::SetProperty,
$null, $object, $propertyValue)
}

#-Function Invoke-Method----------------------------------------------
Function Invoke-Method([__ComObject]$object, [String]$methodName,
$methodParameters) {
$objectType = [System.Type]::GetType($object)
$output = $objectType.InvokeMember($methodName,
"InvokeMethod", $NULL, $object, $methodParameters)
if ( $output ) { $output }
}

#-End-------------------------------------------------------------------

 



With this tiny include you can use COM functions in PowerShell almost like in VBScript.

Let the games begin.

2016/03/08:
Minor changes for PowerShell 5 compatibility.
1 Comment