1

I'm trying to make a GUI for an easy tool I need to check if a specific certificate is included in the file and Output the current and next line. This already works.

If I set the variables $INT1 and $Serial1 manually within the code it also works as intended. e.g. $INT1=31 and $Serial1="5AA61E07726DAC13".

I always get an Error that the variable is empty when inputing the same values into the GUI and clicking OK. What am I doing wrong?

The code:

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$objForm = New-Object System.Windows.Forms.Form
$objForm.StartPosition = "CenterScreen"
$objForm.Size = New-Object System.Drawing.Size(400,250)
$objForm.Topmost = $True

#Label+Textbox first question
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,30)
$objLabel.Size = New-Object System.Drawing.Size(800,20)
$objLabel.Text = "INT of certificate"
$objForm.Controls.Add($objLabel)

$objTextBox = New-Object System.Windows.Forms.TextBox
$objTextBox.Location = New-Object System.Drawing.Size(10,50)
$objTextBox.Size = New-Object System.Drawing.Size(200,20)
$objForm.Controls.Add($objTextBox)

#Label+Textbox second question
$objLabel2 = New-Object System.Windows.Forms.Label
$objLabel2.Location = New-Object System.Drawing.Size(10,130)
$objLabel2.Size = New-Object System.Drawing.Size(800,20)
$objLabel2.Text = "Serialnumber of the certificate"
$objForm.Controls.Add($objLabel2)

$objTextBox2 = New-Object System.Windows.Forms.TextBox
$objTextBox2.Location = New-Object System.Drawing.Size(10,150)
$objTextBox2.Size = New-Object System.Drawing.Size(200,20)
$objForm.Controls.Add($objTextBox2)

$INT1 = $objTextBox.Text;
$Serial1 = $objTextBox2.Text;

#OK Button
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(100,175)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.Name = "OK"
#$OKButton.DialogResult = "OK"
$OKButton.Add_Click({Invoke-WebRequest -Uri http://CENSORED.crl -OutFile crl.crl;
$test=certutil.exe -dump crl.crl |Out-String -stream | Select-String -pattern "$Serial1" -Context 0,1
[void] [Windows.Forms.MessageBox]::Show($test)})
$objForm.Controls.Add($OKButton)

[void] $objForm.ShowDialog()

Thank you!

J0nsan
  • 23
  • 1
  • 4
  • See here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scopes If you want the variables accessible after the GUI is closed you need to code for that. – Scepticalist Feb 08 '23 at 12:06
  • You need to configure form to stay open after returning. See my two form project in c# to see solution. After you return you can then query the text box. https://stackoverflow.com/questions/34975508/reach-control-from-another-page-asp-net?force_isolation=true – jdweng Feb 08 '23 at 12:25
  • I guess I'm still to new to Powershell. @Scepticalist both GUI windows are staying open. I though changing the scope of the variable to global just makes it accesible to other scripts. I had not luck changing the scope. – J0nsan Feb 08 '23 at 13:45
  • @jdweng I am not good enough yet to convert it from c# to powershell in my head, can you maybe give an example or expalin what I have to do? Thank you! – J0nsan Feb 08 '23 at 13:45
  • See following. You do not need the question to confirm closing. Just set the cancel to true. You can hide or not hide. Your preference. The form will close without the cancel true and then you will not be able to read the text box. https://stackoverflow.com/questions/57006334/capture-windows-form-close-event-in-powershell?force_isolation=true – jdweng Feb 08 '23 at 15:36

2 Answers2

0
  • All user interaction with your form happens in this, blocking call:
    [void] $objForm.ShowDialog()

  • Therefore, if you want to store results from that user interaction in variables, place the assignments after the call, and reference the controls of interest.

# ... form setup

# Show the form modally (as a dialog).
# The call blocks until the form is closed.
# Note:
#   You may want to examine the return value in case there
#   are multiple ways to close your form, and one of those ways
#   signals having *canceled*, for instance.
$null = $objForm.ShowDialog()

# Now you can get values from the controls and assign them to (script) variables.
$INT1 = $objTextBox.Text
$Serial1 = $objTextBox2.Text

Note: If you need to set script-level variables - i.e., variables visible after a .ShowDialog() call - from inside script blocks serving as event delegates (e.g., the script block passed to $OKButton.Add_Click()), you need to use the $script: scope, given that such script blocks run in a child scope too - see this answer.

mklement0
  • 382,024
  • 64
  • 607
  • 775
0

Here's a rewrite of your code. I'm assuming that you want variables $INT1 and $Serial1 to be available after the windows closes.
In that case, fill them inside the Click() scriptblock and refer to them using $script: scoping, otherwise they are just new variables local to the scriptblock.

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

# these variables need to visible inside the Click scriptblock of the button
# and be also available after the windows closes
$INT1    = $null
$Serial1 = $null

$objForm = New-Object System.Windows.Forms.Form
$objForm.StartPosition = "CenterScreen"
$objForm.Size = New-Object System.Drawing.Size(400,250)
$objForm.Topmost = $True

#Label+Textbox first question
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,30)
$objLabel.Size = New-Object System.Drawing.Size(800,20)
$objLabel.Text = "INT of certificate"
$objForm.Controls.Add($objLabel)

$objTextBox = New-Object System.Windows.Forms.TextBox
$objTextBox.Location = New-Object System.Drawing.Size(10,50)
$objTextBox.Size = New-Object System.Drawing.Size(200,20)
$objForm.Controls.Add($objTextBox)

#Label+Textbox second question
$objLabel2 = New-Object System.Windows.Forms.Label
$objLabel2.Location = New-Object System.Drawing.Size(10,130)
$objLabel2.Size = New-Object System.Drawing.Size(800,20)
$objLabel2.Text = "Serialnumber of the certificate"
$objForm.Controls.Add($objLabel2)

$objTextBox2 = New-Object System.Windows.Forms.TextBox
$objTextBox2.Location = New-Object System.Drawing.Size(10,150)
$objTextBox2.Size = New-Object System.Drawing.Size(200,20)
$objForm.Controls.Add($objTextBox2)

#OK Button
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(100,175)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.Name = "OK"
#$OKButton.DialogResult = "OK"

$OKButton.Add_Click({
    # you never seem to use variable $INT1, but if you do, refer to it as $script:INT1
    # set the variables defined OUTSIDE the scriptblock using script-scoping
    $script:INT1    = $objTextBox.Text
    $script:Serial1 = $objTextBox2.Text

    # create a full path and filename for the output of the Invoke-WebRequest call
    $crlFile = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath 'crl.crl'
    Invoke-WebRequest -Uri 'http://CENSORED.crl' -OutFile $crlFile
    $test = certutil.exe -dump $crlFile | Out-String -Stream | Select-String -Pattern $script:Serial1 -Context 0,1
    [void] [Windows.Forms.MessageBox]::Show($test)
    # delete the temporary file
    $crlFile | Remove-Item -Force
})
$objForm.Controls.Add($OKButton)

[void] $objForm.ShowDialog()
# clean up the form from memory'
$objForm.Dispose()

# here you can again see what is inside variables $INT1 and $Serial1
Write-Host "Last entered values: $INT1  $Serial1"
Theo
  • 57,719
  • 8
  • 24
  • 41