Benutzer mit den meisten Antworten
Return PSCustomObject Problem

Frage
-
Hallo,
wenn ich folgenden Code ausführe bekomme ich den String "test123" ausgegeben.
function test1 { $test = New-Object PSObject $test | Add-Member -MemberType NoteProperty -Name "a" -Value "test123" $test | Add-Member -MemberType NoteProperty -Name "b" -Value "test456" return $test } $var1 = test1 $var1.a
Dieses Prinzip habe ich auf etwas komplexeres angewandt und bekomme nun nichts mehr zurückgegeben.
function test2 { [IO.FileInfo]$FilePath = "PFAD ZU EINER BELIEBIGEN MSI DATEI" $PropertyList = @("ProductCode","ProductVersion","ProductName") $ReturnObject = New-Object PSObject Try { $WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer $MSIDatabase = $WindowsInstaller.GetType().InvokeMember("OpenDatabase","InvokeMethod",$Null,$WindowsInstaller,@($FilePath.FullName,0)) Foreach ($Property in $PropertyList) { $Query = "SELECT Value FROM Property WHERE Property = '$Property'" $View = $MSIDatabase.GetType().InvokeMember("OpenView","InvokeMethod",$null,$MSIDatabase,($Query)) $View.GetType().InvokeMember("Execute", "InvokeMethod", $null, $View, $null) $Record = $View.GetType().InvokeMember("Fetch","InvokeMethod",$null,$View,$null) $Value = $Record.GetType().InvokeMember("StringData","GetProperty",$null,$Record,1) $ReturnObject | Add-Member -MemberType NoteProperty -Name "$Property" -Value $Value } } Catch { Write-Output $_.Exception.Message } return $ReturnObject } $var2 = test2 $var2.ProductCode
In der Variable
$var2
steht bei mir folgender Inhalt
PS C:\Windows\system32> $var2 | get-member TypeName: System.Management.Automation.PSCustomObject Name MemberType Definition ---- ---------- ---------- Equals Method bool Equals(System.Object obj) GetHashCode Method int GetHashCode() GetType Method type GetType() ToString Method string ToString() ProductCode NoteProperty System.String ProductCode={C43920E3-2939-455A-B1E2-8A0673A5FFCA} ProductName NoteProperty System.String ProductName=Cisco AnyConnect Start Before Login Module ProductVersion NoteProperty System.String ProductVersion=4.2.04018
trotzdem bekomme ich bei
$var2.ProductCode
keine Ausgabe.
PowerShell Version:
Name Value ---- ----- CLRVersion 2.0.50727.5485 BuildVersion 6.1.7601.17514 PSVersion 2.0 WSManStackVersion 2.0 PSCompatibleVersions {1.0, 2.0} SerializationVersion 1.1.0.1 PSRemotingProtocolVersion 2.1
Kann mir hier irgendwer Helfen oder einen Tipp geben?
Antworten
-
Funtioniert das hier?
function test2 { [IO.FileInfo]$FilePath = "PFAD ZU EINER BELIEBIGEN MSI DATEI" $PropertyList = @("ProductCode","ProductVersion","ProductName") $ReturnObject = New-Object PSObject Try { $WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer $MSIDatabase = $WindowsInstaller.GetType().InvokeMember("OpenDatabase","InvokeMethod",$Null,$WindowsInstaller,@($FilePath.FullName,0)) Foreach ($Property in $PropertyList) { $Query = "SELECT Value FROM Property WHERE Property = '$Property'" $View = $MSIDatabase.GetType().InvokeMember("OpenView","InvokeMethod",$null,$MSIDatabase,($Query)) $View.GetType().InvokeMember("Execute", "InvokeMethod", $null, $View, $null) > $null $Record = $View.GetType().InvokeMember("Fetch","InvokeMethod",$null,$View,$null) $Value = $Record.GetType().InvokeMember("StringData","GetProperty",$null,$Record,1) $ReturnObject | Add-Member -MemberType NoteProperty -Name "$Property" -Value $Value } } Catch { Write-Host $_.Exception.Message } return $ReturnObject } $var2 = test2 $var2.ProductCode
Wie schon gesagt, es liegt am Output-Stream. Wenn du den Code nicht als Funktion ausführst, wird jeder Output an die Console übergeben. Wenn du es als Funktion ausführst wird es an die Rückgabe der Funktion übergeben. Als Beispiel versuch mal das hier:
function test { "ABC" $a = 42 Write-Host "Dies kommt direkt die Console" New-Item "C:\Temp\Test.txt" -ItemType File -Force return $a } $c = Test
und das hier:
function test { "ABC" > $null $a = 42 Write-Host "Dies kommt direkt die Console" New-Item "C:\Temp\Test.txt" -ItemType File -Force > $null return $a } $c = Test
Im ersten Fall hast du auch das "ABC" und das neu erstellte Datei-Objekt in der Rückgabe. In letzterem werden alle Ausgaben abgefangen, außer der, die wir wollen. Die return-Anweisung ist NICHT die ausschließliche Rückgabe bei einer PowerShell-Funktion!
Alle Antworten
-
Hallo,
ich habe deinen Code für meinen Test etwas reduziert und einfach Zufallszahlen eintragen lassen. Dabei konnte ich keinen Fehler finden.
Da Get-Member die Werte bei dir anzeigt, müssen sie auch vorhanden sein. Eigentlich muss es funktionieren.
Du könntest höchstens nochmal $var2.GetType() versuchen.
Viele Grüße
Christoph
- Bearbeitet hpotsirhc Donnerstag, 28. Juli 2016 09:52
-
Hey,
__________________________________________________________________________________________________________________________________________________________________________________________ PS C:\Windows\system32> $var1.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True False PSCustomObject System.Object __________________________________________________________________________________________________________________________________________________________________________________________ PS C:\Windows\system32> $var2.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array __________________________________________________________________________________________________________________________________________________________________________________________
danke für den Tipp mit .GetType()
Ich glaube hier liegt der Fehler.
Hast du auch eine Idee wie ich das am besten gefixt bekomme?
-
Moin,
caste doch den Wert von $Value zu String, bevor Du ihn zuweist:
$ReturnObject | Add-Member -MemberType NoteProperty -Name "$Property" -Value ([string]$Value)
oder
$ReturnObject | Add-Member -MemberType NoteProperty -Name "$Property" -Value ($Value.ToString())
je nachdem, was davon funktioniert.
Evgenij Smirnov
msg services ag, Berlin -> http://www.msg-services.de
my personal blog (mostly German) -> http://it-pro-berlin.de
Windows Server User Group, Berlin -> http://www.winsvr-berlin.de
Mark Minasi Technical Forum, reloaded -> http://newforum.minasi.comIn theory, there is no difference between theory and practice. In practice, there is.
-
Aha, es ist ein Array.
In PowerShell 4.0 (und wahrscheinlich auch 3.0) bekommst du beim Aufruf von $a.p die Werte der Eigenschaft p für alle Elemente des Arrays $a.
In PowerShell 2.0 geht das noch nicht. Wenn $a ein Einzelelement ist, wird dir mit $a.p der Wert der Eigenschaft p wiedergegeben. Ist es ein Array, kommt einfach nichts.
Versuch mal $Var2[0].ProductCode.
Übrigens: Get-Member hat die Werte angezeigt, weil es nicht das Objekt selbst untersucht, sondern im Falle eines Arrays die einzelnen Elemente.
- Bearbeitet hpotsirhc Donnerstag, 28. Juli 2016 12:02
-
Ich sehe gerade, aber ich kann deinen Code leider nicht bei mir laufen lassen:
Diese Zeile
$View.GetType().InvokeMember("Execute", "InvokeMethod", $null, $View, $null)
Ist eine Methode, deren Output in den Output-Stream geht. Wenn Sie einen Output hat. Versuch mal die Zeile mit
> $null
oder
| Out-Null
abzuschließen. Funktionen sammeln die Rückgaben, die sonst in der Console angezeigt würden. Es wird nicht nur der mit return angegebene Rückgabewert übergeben, sondern der gesamte Output-Stream. Daher sollten in Funktionen oder aufgerufenen Skripten alle Methodenaufrufe immer ein "=" enthalten oder in die $null-Variable (ins Schwarze Loch) verbannt werden.
-
-1 Funktioniert.
Ich vermute das es an der Funktion liegt und weniger an dem Code, weil wenn ich folgenden Code ausführe
[IO.FileInfo]$FilePath = "F:\Dev\psbase\anyconnect-gina-win-4.2.04018-pre-deploy-k9.msi" $PropertyList = @("ProductCode","ProductVersion","ProductName") $ReturnObject = New-Object PSObject $WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer $MSIDatabase = $WindowsInstaller.GetType().InvokeMember("OpenDatabase","InvokeMethod",$Null,$WindowsInstaller,@($FilePath.FullName,0)) Foreach ($Property in $PropertyList) { $Query = "SELECT Value FROM Property WHERE Property = '$Property'" $View = $MSIDatabase.GetType().InvokeMember("OpenView","InvokeMethod",$null,$MSIDatabase,($Query)) $View.GetType().InvokeMember("Execute", "InvokeMethod", $null, $View, $null) $Record = $View.GetType().InvokeMember("Fetch","InvokeMethod",$null,$View,$null) $Value = $Record.GetType().InvokeMember("StringData","GetProperty",$null,$Record,1) $ReturnObject | Add-Member -MemberType NoteProperty -Name "$Property" -Value $Value }
st alles Super...
PS C:\Users> $ReturnObject.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True False PSCustomObject System.Object PS C:\Users> $ReturnObject ProductCode ProductVersion ProductName ----------- -------------- ----------- {C43920E3-2939-455A-B1E2-8A0673A5FFCA} 4.2.04018 Cisco AnyConnect Start Before Login Module
Wenn ich das Ganze in eine Funktion packe mit einem
return $ReturnObject
und das Ergebis in eine Variable schreibe dann kommt das dabei raus..
PS C:\Users> $blub.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array
-
Funtioniert das hier?
function test2 { [IO.FileInfo]$FilePath = "PFAD ZU EINER BELIEBIGEN MSI DATEI" $PropertyList = @("ProductCode","ProductVersion","ProductName") $ReturnObject = New-Object PSObject Try { $WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer $MSIDatabase = $WindowsInstaller.GetType().InvokeMember("OpenDatabase","InvokeMethod",$Null,$WindowsInstaller,@($FilePath.FullName,0)) Foreach ($Property in $PropertyList) { $Query = "SELECT Value FROM Property WHERE Property = '$Property'" $View = $MSIDatabase.GetType().InvokeMember("OpenView","InvokeMethod",$null,$MSIDatabase,($Query)) $View.GetType().InvokeMember("Execute", "InvokeMethod", $null, $View, $null) > $null $Record = $View.GetType().InvokeMember("Fetch","InvokeMethod",$null,$View,$null) $Value = $Record.GetType().InvokeMember("StringData","GetProperty",$null,$Record,1) $ReturnObject | Add-Member -MemberType NoteProperty -Name "$Property" -Value $Value } } Catch { Write-Host $_.Exception.Message } return $ReturnObject } $var2 = test2 $var2.ProductCode
Wie schon gesagt, es liegt am Output-Stream. Wenn du den Code nicht als Funktion ausführst, wird jeder Output an die Console übergeben. Wenn du es als Funktion ausführst wird es an die Rückgabe der Funktion übergeben. Als Beispiel versuch mal das hier:
function test { "ABC" $a = 42 Write-Host "Dies kommt direkt die Console" New-Item "C:\Temp\Test.txt" -ItemType File -Force return $a } $c = Test
und das hier:
function test { "ABC" > $null $a = 42 Write-Host "Dies kommt direkt die Console" New-Item "C:\Temp\Test.txt" -ItemType File -Force > $null return $a } $c = Test
Im ersten Fall hast du auch das "ABC" und das neu erstellte Datei-Objekt in der Rückgabe. In letzterem werden alle Ausgaben abgefangen, außer der, die wir wollen. Die return-Anweisung ist NICHT die ausschließliche Rückgabe bei einer PowerShell-Funktion!