PowerShell Function return value and further use of returned Variable
In your example:
function whichcsv(){
$location = New-Object System.Windows.Forms.OpenFileDialog
$location.initialDirectory = $initialDirectory
$location.filter = "CSV (*.csv)| *.csv"
$location.ShowDialog()
write-host $location.FileName "in Function"
}
$location
, as assigned in the function body, is local to the function's scope. In PowerShell you can read variables from a parent scope, but writing to a variable creates a local copy by default, not persisted in the caller's scope.
What you want to do is return
it's value from the scope, just like you would in a C-like language.
The caveat in PowerShell is that any value expression inside the function body that outputs anything will "bubble up" to the caller, not just the argument to return
. So if you have statements inside the function body that return any value, make sure you capture or suppress that output:
function whichcsv(){
$location = New-Object System.Windows.Forms.OpenFileDialog
$location.initialDirectory = $initialDirectory
$location.filter = "CSV (*.csv)| *.csv"
[void]$location.ShowDialog() # <-- ShowDialog() returns a DialogResult, suppress it
return $location.FileName # return the filename property value
}
Then in the calling scope:
$CsvPath = whichcsv
$CsvPath
will now contain the value of $location.Filename
after the function returns
For more information about variable scoping in PowerShell, see the about_Scopes
help topic
For more information about the behavior of return
, see the about_Return
help topic
For more information about the reason for this behavior in the first place, look into pipelines
Related videos on Youtube
Kevin
Updated on June 04, 2022Comments
-
Kevin almost 2 years
I don't get how the functions works in PowerShell. I tried it out a bit like C++ or C# but those languages I last tried out 7 years ago.
So as I try to work with the functions I have this function:
function whichcsv(){ $location = New-Object System.Windows.Forms.OpenFileDialog $location.initialDirectory = $initialDirectory $location.filter = "CSV (*.csv)| *.csv" $location.ShowDialog() write-host $location.FileName "in Function" }
which determines the location of the csv that is loaded afterwards but as soon as I try to load the variable
$location
outside of the function it's NULLWith the
write-host
statement you can see it has the full path of the file.As soon as I try to load it outside the function right after the code it won't work as its says its NULL
... #Select which CSV whichcsv ... $CSV = Import-Csv -Path $location.FileName -UseCulture $y = $CSV | Select Inventarnummer $Filter = "Inventarnummer"
I tried to set my code in a
int main(void)
like in C-languages but I don't know how to handle this as well as there it would have been on the same scoope so it should have worked so but somehow it doesn't works as then I only get all in the console prompt but nothing ever happensFull code for repro
#Importend: #This is Work in Progress and not completed work. Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing #Function Assembling Function SaveWorkingdestination () { $Saveworking = New-Object -Typename System.Windows.Forms.SaveFileDialog $Saveworking.filter = "CSV (*.csv)| *.csv" $Saveworking.ShowDialog() return $Saveworking } function Savefaileddestination () { $Savefailed = New-Object -Typename System.Windows.Forms.SaveFileDialog $Savefailed.filter = "CSV (*.csv)| *.csv" $Savefailed.ShowDialog() return $Savefailed } function Compare ($location) { #work in progress $CSV1 = Import-Csv -Path $location.FileName -UseCulture $CSV2 = Import-Csv -Path $location.FileName -UseCulture Compare-Object $CSV1 $CSV2 -property WhichColumn -IncludeEqual return comparedfilename } function whichcsv(){ $location = New-Object System.Windows.Forms.OpenFileDialog $location.initialDirectory = $initialDirectory $location.filter = "CSV (*.csv)| *.csv" $location.ShowDialog() write-host $location.FileName "in Funktion" } function Checktrough ($y , $Filter,$Saveworking,$Savefailed) { foreach($n in $y) { try { $Computer = [system.net.dns]::resolve($n.$Filter) | Select HostName,AddressList $IP = ($Computer.AddressList).IPAddressToString Write-Host $n.$Filter $IP New-Object PSObject -Property @{IPAddress=$IP; Name=$n.$Filter} | Export-Csv $Saveworking.FileName -NoTypeInformation -Append } catch { Write-Host "$($n.$Filter) is unreachable." New-Object PSObject -Property @{Name=$n.$Filter} | Export-Csv $Savefailed.FileName -NoTypeInformation -Append } } } #int main (void) #doesnt working so far #{ #Select which option Form $form = New-Object System.Windows.Forms.Form $form.Text = "CSV Liste" $form.Size = New-Object System.Drawing.Size(300,300) $form.StartPosition = "CenterScreen" $OKButton = New-Object System.Windows.Forms.Button $OKButton.Location = New-Object System.Drawing.Point(75,195) $OKButton.Size = New-Object System.Drawing.Size(75,23) $OKButton.Text = "OK" $OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK $form.AcceptButton = $OKButton $form.Controls.Add($OKButton) $CancelButton = New-Object System.Windows.Forms.Button $CancelButton.Location = New-Object System.Drawing.Point(150,195) $CancelButton.Size = New-Object System.Drawing.Size(75,23) $CancelButton.Text = "Cancel" $CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel $form.CancelButton = $CancelButton $form.Controls.Add($CancelButton) $label = New-Object System.Windows.Forms.Label $label.Location = New-Object System.Drawing.Point(10,20) $label.Size = New-Object System.Drawing.Size(280,20) $label.Text = "Welche CSV Liste soll geladen werden:" $form.Controls.Add($label) $listBox = New-Object System.Windows.Forms.ListBox $listBox.Location = New-Object System.Drawing.Point(10,40) $listBox.Size = New-Object System.Drawing.Size(260,20) $listBox.Height = 150 [void] $listBox.Items.Add("AS400 Computer") [void] $listBox.Items.Add("AS400 Personalstamm") [void] $listBox.Items.Add("ADComputer") [void] $listBox.Items.Add("ADBenutzer") #Formclosed $form.Controls.Add($listBox) $form.Topmost = $True $result = $form.ShowDialog() if ($result -eq [System.Windows.Forms.DialogResult]::OK) { #Select which CSV whichcsv $x = $listBox.SelectedItem switch ($x) { #Option 1 "AS400 Computer" { $CSV = Import-Csv -Path $location.FileName -UseCulture $y = $CSV | Select Inventarnummer $Filter = "Inventarnummer" #SaveWorkingdestination($Saveworking) #Export-Csv $Saveworking.FileName -NoTypeInformation -Append } #Option 2 "AS400 Personalstamm" { #not implemented yet $y = $CSV | Select SpaltennameBzwFilter $Filter = "Spaltennamme bzw Filter" } #Option 3 "ADComputer" { $CSV = Import-Csv -Path $location.FileName -Delimiter ',' $y = $CSV | Select Name $Filter = "Name" SaveWorkingdestination Savefaileddestination Checktrough } #Option 4 "ADBenutzer" { #not implemented yet $y = $CSV | Select SpaltennameBzwFilter $Filter = "Spaltenname bzw Filter" } } } #}
Maybe someone knows how to help me eather with getting the common code in something like the int main (void) from c languages or how to get a proper return from the functions... if there are still unclearitys i will clearly answer them and edit to get this working
edit: with script part it works perfectly fine so far, but now is there a format question to get some more structure in it. or is it common to have no wrap around in powershell scripts like you have in c languages with the
int main (void) { ... code ... }
-
Kevin over 6 yearsok this works out thank you, can i shorten the $script:locationfilename = $location.filename to something like $script:Fnp = $location.filename ?
-
Kevin over 6 yearsyeah its kinda confusing with those scopes in powershell when you first dont know about it and try to handle it like in c languages and so on... is there a ease and short explantion of those scopes from powershell? and if not to much for a question is there a wrap up like in c languages with the int main (void){}
-
Mathias R. Jessen over 6 years@Kevin Yeah, jumping into a fundamentally different programming environment with a similar syntax can be quite confusing :-) Look at the example in my code (the second block) -
[void](statement or expression in here)
is an easy way to suppress output. For scopes, have a look at the documentation -
ShanayL over 6 yearsYeah that works too... you can use anything you like you pretty much throwing
script
at the front of your variable. -
Kevin over 6 yearsallright its quite a lot of info to get into it but its a nice docu and i will work with it till i got the clue completly still one structre question open if there is a wrap up in scripting like in the c language or does the code "hang free", if i'm not wrong this would make a scope shift right? so now the free code is in local or whatever and then it would be in the "same scope" like the functions or am i wrong here?
-
Mathias R. Jessen over 6 yearsNo, it won't "shift scopes", it'll only swallow output