How retrieve string value from Function?

Hello !

I have a small problem (i think it’s a small problem.):

I created a small function with a code i found in the web to create a datepicker .I want reuse this code many times, for that i create a function datepicker, i would retrieve a string value inside this function but the value disappear outside the function, i don’t understand why :

[pre]

function DatePicker()
{

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

$form = New-Object Windows.Forms.Form

$form.Text = ‘Select the End date of the transert’
$form.Size = New-Object Drawing.Size @(243,230)
$form.StartPosition = ‘CenterScreen’

$calendar = New-Object System.Windows.Forms.MonthCalendar
$calendar.ShowTodayCircle = $false
$calendar.MaxSelectionCount = 1
$form.Controls.Add($calendar)

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Point(38,165)
$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(113,165)
$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)

$form.Topmost = $true

$result = $form.ShowDialog()
Write-Host $result # OK

}

$dapicker = DatePicker
Write-Host $result # emplty

[/pre]

 

I believe what you’re running into is a variable scope issue.

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scopes

One of the basic rules of scoping at the top of the link provided is this.

An item you include in a scope is visible in the scope in which it was created and in any child scope, unless you explicitly make it private. You can place variables, aliases, functions, or PowerShell drives in one or more scopes.
This means that because your $result is defined within your function (child of your script), it is only accessible within that function, and not in it's parent. By default scope access trickles down, but not up.

Try adding a line to the bottom of your function that returns your $result such as.

[pre]Write-Output $result[/pre] or [pre]return $result[/pre]

Then on line 42 your $dapicker variable will now hold the result value and you’ll no longer reference your $result variable outside of the function scope.

Write-host is only meant for the screen. Also variables in a function can’t be seen outside it.

function datepicker
{
  $result1 = 'hi'
  $result1
}

$result2 = datepicker
$result2

hi

Hey js… As for …

Write-host is only meant for the screen. Also variables in a function can't be seen outside it.

… as of PS5x, that is no longer true.

Yet agreed, Write-Host, outside of specific needs should not be used. You don’t even need Write-* to send to the screen. Write-Output is the default. So, all the below write to the screen without explicitly calling Write anything.

'Hello'
('Hello')
"Hello"
("Hello")
($SomeString = 'Hello')
$SomeString
"$SomeString"
($SomeString)
$($SomeString)

So, even using Write-Output explicitly is more of a style or internal coding standards choice.

We all historically have pointed folks to this…

http://www.jsnover.com/blog/2013/12/07/write-host-considered-harmful

… being the go to statement. However, Jeffrey Snover change his stance on this as of May 2016. With PowerShell v5 Write-Host no longer “kills puppies”. Data is captured into info stream …

https://twitter.com/jsnover/status/727902887183966208 https://docs.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Utility/Write-Information?view=powershell-5.1

herken97, just change this…

$result = $form.ShowDialog()

… to this…

$Script: result = $form.ShowDialog()

Demo

 function DatePicker()
{

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

$form = New-Object Windows.Forms.Form

$form.Text = 'Select the End date of the transert'
$form.Size = New-Object Drawing.Size @(243,230)
$form.StartPosition = 'CenterScreen'

$calendar = New-Object System.Windows.Forms.MonthCalendar
$calendar.ShowTodayCircle = $false
$calendar.MaxSelectionCount = 1
$form.Controls.Add($calendar)

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Point(38,165)
$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(113,165)
$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)

$form.Topmost = $true

$Script:result = $form.ShowDialog()
Write-Host $result # OK

}

DatePicker
OK

($dapicker = DatePicker)
OK

Write-Host $result # emplty
OK

Ok. If he wants to capture the output of his function to a variable…

function datepicker {
  $result1 = 'hi'                                               
  write-host $result1
}

$result2 = datepicker 6>&1
$result2

hi