Hello community,
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-----------------------------------------------------------------
#-Function Create-Object----------------------------------------------
Function Create-Object {
param([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 {
param([String] $objectName)
[Microsoft.VisualBasic.Interaction]::GetObject($objectName)
}
#-Sub Free-Object-----------------------------------------------------
Function Free-Object {
param([__ComObject] $object)
[Void] [System.Runtime.Interopservices.Marshal]::ReleaseComObject($object)
}
#-Function Get-Property-----------------------------------------------
Function Get-Property {
param([__ComObject] $object, [String] $propertyName)
$object.GetType().InvokeMember($propertyName,
[System.Reflection.Bindingflags]::GetProperty,
$null, $object, $null)
}
#-Sub Set-Property----------------------------------------------------
Function Set-Property {
param([__ComObject] $object, [String] $propertyName,
$propertyValue)
[Void] $object.GetType().InvokeMember($propertyName,
[System.Reflection.Bindingflags]::SetProperty,
$null, $object, $propertyValue)
}
#-Function Invoke-Method----------------------------------------------
Function Invoke-Method {
param([__ComObject] $object, [String] $methodName,
$methodParameters)
$object.GetType().InvokeMember($methodName,
[System.Reflection.Bindingflags]::InvokeMethod,
$null, $object, $methodParameters, $null, $null, $null)
}
#-End-------------------------------------------------------------------
With this tiny include you can use COM functions in PowerShell almost like in VBScript.
Let the games begin.
Cheers
Stefan