Retrieve Input from PowerShell TextBox - powershell

I am working on a PowerShell application which should take a user id as input from a text box, then search ActiveDirectory and return three fields; however, every time I try to use it I receive the following error:
Get-ADUser : Cannot validate argument on parameter 'Identity'. The argument is null. Provide a valid value for the argument, and then try running the command again.
At C:\Path\cc-lookup-gui.ps1:40 char:21
+ $y = Get-ADUser $script:x -Properties cC
+ ~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-ADUser], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.GetADUser
Here is the code for my GUI and search function:
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")|Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")|Out-Null
$net = New-Object -ComObject Wscript.Network
$form = New-Object System.Windows.Forms.Form
$form.Width = 525
$form.Height = 350
$form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::Fixed3D
$form.Text = "CC Lookup"
$form.MaximumSize = New-Object System.Drawing.Size(525,350)
$form.StartPosition = "centerscreen"
$form.KeyPreview = $true
$form.Add_KeyDown({if($_.KeyCode -eq "Enter"){$script:x=$input.Text;Search}})
$form.Add_KeyDown({if($_.KeyCode -eq "Escape"){$form.Close()}})
$input = new-object System.Windows.Forms.TextBox
$input.maxLength = 6
$input.Location = New-Object System.Drawing.Size(200,75)
add-type -assemblyName System.Windows.Forms
$label1 = New-Object System.Windows.Forms.Label
$label1.Location = New-Object System.Drawing.Size(200,25)
$label1.AutoSize = $true
$label1.Text = "Enter User ID:"
$Button1 = new-object System.Windows.Forms.Button
$Button1.Location = New-Object System.Drawing.Size(100,132)
$Button1.Size = New-Object System.Drawing.Size(80,20)
$Button1.Text = "Search"
$Button1.Add_Click({$script:x=$input.Text;Search})
$button2 = New-Object System.Windows.Forms.Button
$button2.Location = New-Object System.Drawing.Size(300,132)
$button2.Text = "Clear"
$button2.Add_Click({Clears})
function Search{
$y = Get-ADUser $script:x -Properties cC
$output = $y.samAccountName + '|' + $y.CN + '|' + $y.cC
Add-Type -AssemblyName System.Windows.Forms
$label = New-Object System.Windows.Forms.Label
$label.Text = $Output
$label.AutoSize = $true
$label.Location = New-Object System.Drawing.Size(200,100)
$form.controls.add($label)
}
function Clears{
$label.Text = $null
$input.Text = $null
}
$form.Controls.Add($label1)
$form.Controls.Add($button2)
$form.Controls.Add($input)
$form.Controls.Add($Button1)
$form.Add_Shown({$Form.Activate()})
$Form.ShowDialog()
$x = $input.Text
I have tried declaring the variable $x globally, directly calling $input.text for the search function, and converting $x into a string, all of which return this same error. I'm running PowerShell version 5.

$Input is a special variable name - see help about_Automatic_Variables - and won't do what you expect when you use it in your {} scriptblock, it will refer to scriptblock input (in this case, nothing), instead of your inputbox.
Try renaming it to something else.

Related

Use script variable inside textbox form

I’m trying to create a form which contains a message where I want to use some data imported from a CSV file.
The script will read the CSV rows and print a message that will contain data from it.
The issue is that the variables inside message textbox is not used instead a plain text is filled.
I think that this is related to System.Windows.Forms.TextBox but I can't figure it out
Any idea how I can resolve this?
Regards,
Adrian
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName PresentationFramework
function show_menu {
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$form = New-Object System.Windows.Forms.Form
$form.Text = 'menu'
$form.Size = New-Object System.Drawing.Size(630,370)
$form.StartPosition = 'CenterScreen'
$form.FormBorderStyle = 'FixedSingle'
#$form.Icon = [System.Drawing.Icon]::FromHandle((New-Object System.Drawing.Bitmap -Argument $stream).GetHIcon())
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(200,295)
$okButton.Size = New-Object System.Drawing.Size(75,23)
$okButton.Text = 'OK'
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$okButton.Add_Click({
$form.Tag = $textBox_recipient.Text;
$form.Tag = $textBox_message.Text;
$form.Close()
})
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)
$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Location = New-Object System.Drawing.Point(355,295)
$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)
$textBox_recipient = New-Object System.Windows.Forms.TextBox
$textBox_recipient.Location = New-Object System.Drawing.Point(210,70)
$textBox_recipient.Size = New-Object System.Drawing.Size(245, 20)
$textBox_recipient.ReadOnly = $true
$form.Controls.Add($textBox_recipient)
##
$textBox_recipient_select = New-Object System.Windows.Forms.Button
$textBox_recipient_select.Location = New-Object System.Drawing.Point(460, 70)
$textBox_recipient_select.Size = New-Object System.Drawing.Size(100, 20)
$textBox_recipient_select.Text = "Select CSV file"
$textBox_recipient_select.add_Click({
$ofd = New-Object system.windows.forms.Openfiledialog
#$ofd.Filter = 'Supported file types (*.csv,*.xlsx)|*.csv,*.xlsx'
$ofd.Filter = 'Supported file types (*.csv, *.xlsx)|*.csv; *.xlsx| All (*.*)|*.*'
$script:recipient_filename = 'Not found'
if ($ofd.ShowDialog() -eq 'Ok') {
$script:recipient_filename = $textbox_recipient.Text = $ofd.FileName
}
})
#$textBox_recipient.Text = "C:\Users\Ady\Desktop\test.csv"
$form.Controls.Add($textBox_recipient_select)
$label_message = New-Object System.Windows.Forms.Label
$label_message.Location = New-Object System.Drawing.Point(10,150)
$label_message.Size = New-Object System.Drawing.Size(200,20)
$label_message.BackColor = [System.Drawing.Color]::FromName("Transparent")
$label_message.Font = [System.Drawing.Font]::new("Microsoft Sans Serif", 10, [System.Drawing.FontStyle]::Bold)
$label_message.Text = 'Message:'
$form.Controls.Add($label_message)
$textBox_message = New-Object System.Windows.Forms.TextBox
$textBox_message.Multiline = $True
$textBox_message.Scrollbars = "Vertical"
$textBox_message.Location = New-Object System.Drawing.Point(210,150)
$textBox_message.Size = New-Object System.Drawing.Size(350, 135)
$textBox_message.Text = "Insert your text here. HTML format supported"
$form.Controls.Add($textBox_message)
$form.Topmost = $true
$form.Add_Shown({ $textBox_recipient.Select(),$textBox_message.Select() })
$result = $form.ShowDialog()
if ($result -eq [System.Windows.Forms.DialogResult]::OK) {
$script:filename = "$(($textBox_recipient).Text)"
$recipients = Import-csv -Path "$filename"
$total_recipient_nr = get-content "$filename" | select-string "#" | measure-object -line
$recipient_nr = 0
foreach ($recipient in $recipients) {
if (++$recipient_nr % 31 -eq 0)
{
Start-Sleep -Seconds 30
echo "waiting 1 minute"
}
$script:user_email = $recipient.email
$script:user_firstname = $recipient.firstname
$script:user_lastname = $recipient.lastname
$script:user_code = $recipient.code
$script:message = $textBox_message.Text
Write-Host $message
}
}
}
show_menu
For example, the following csv:
firstname, lastname, email, code ---- header of csv file
firstname1, lastname1, email1#domain, code1
firstname2, lastname2, email2#domain, code2
What I want to do is to use variables like $user_email, $user_code inside "$textBox_message.Text" field of the form and for each line of the CSV file, the message to use the value of those variables. (recipient is a row from the csv file that contains different values at each foreach run)
$script:user_firstname = $recipient.firstname
$script:user_code = $recipient.code
$script:message = $textBox_message.Text
I run the script, the form appears and I replace the default text "Insert your text here. HTML format supported" of $textBox_message.Text with the following:
Hi $user_firstname. This is your code: $user_code
The result (value of $message var) by executing line 96, should be:
Hi firstname1. This is your code: code1 - at first run of foreach loop
and
Hi firstname2. This is your code: code2 - at second run of foreach loop
Instead, the result is:
Hi $user_firstname. This is your code: $user_code --- plain text (the value) of $message
This is from what I have observed from Powershell when trying to writing a simple string with variables:
if you use single quotes i.e.
$firstName = "John"
write-host 'First name is $firstName'
The output is going to be:
First name is $firstName
However if you use double quotes, you should get the variable value instead of variable being displayed as plain text. i.e.
$firstName = "John"
write-host "First name is $firstName" or write-host "First name is $($firstName)"
you should get the desired output:
First name is John

powershell reopening subform

I am writing my first subform in PowerShell. When I write my code through everything fires off perfectly. When I close the subform by the x in the window and then reopen it I receive the error:
Exception setting "visible": "Cannot access a disposed object.
Object name: 'Form'."
At line:5 char:5
$ExampleForm.visible = $true
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], SetValueInvocationException
+ FullyQualifiedErrorId : ExceptionWhenSetting
My Code is below:
function TestFunction
{
$ExampleForm.enabled = $true
$ExampleForm.visible = $true
}
$Form = New-Object system.Windows.Forms.Form
$Form.Size = New-Object System.Drawing.Size(1050,425)
$form.MaximizeBox = $false
$Form.StartPosition = "CenterScreen"
$Form.FormBorderStyle = 'Fixed3D'
$Form.Text = "Test Form"
$ExampleForm = New-Object system.Windows.Forms.Form
$ExampleForm.Size = New-Object System.Drawing.Size(550,425)
$ExampleForm.MaximizeBox = $false
$ExampleForm.StartPosition = "CenterScreen"
$ExampleForm.FormBorderStyle = 'Fixed3D'
$ExampleForm.Text = "Example"
$ExampleForm.Visible = $False
$TestButton = new-object System.Windows.Forms.Button
$TestButton.Location = new-object system.drawing.size(401,140)
$TestButton.Size = new-object system.drawing.size(80,50)
$TestButton.Text = "Test"
$TestButton.Add_Click({TestFunction})
$TestButton.TabIndex = 33
$Form.Controls.Add($TestButton)
$Form.ShowDialog()
What am I doing wrong???
You'll want to create a new form every time:
function TestFunction
{
$ExampleForm = New-Object System.Windows.Forms.Form
$ExampleForm.Size = New-Object System.Drawing.Size(550,425)
$ExampleForm.MaximizeBox = $false
$ExampleForm.StartPosition = "CenterScreen"
$ExampleForm.FormBorderStyle = 'Fixed3D'
$ExampleForm.Text = "Example"
# ShowDialog will prevent re-focusing on parent form until this one closes
[void]$ExampleForm.ShowDialog()
# If you don't want this modal behavior, use `Show()` instead:
# [void]$ExampleForm.Show()
}
$Form = New-Object System.Windows.Forms.Form
$Form.Size = New-Object System.Drawing.Size(1050,425)
$Form.MaximizeBox = $false
$Form.StartPosition = "CenterScreen"
$Form.FormBorderStyle = 'Fixed3D'
$Form.Text = "Test Form"
$TestButton = New-Object System.Windows.Forms.Button
$TestButton.Location = New-Object System.Drawing.Size(401,140)
$TestButton.Size = New-Object System.Drawing.Size(80,50)
$TestButton.Text = "Test"
$TestButton.add_Click({TestFunction})
$TestButton.TabIndex = 33
$Form.Controls.Add($TestButton)
$Form.ShowDialog()

object $Button within foreach / how to reference it to change color

I'm building GUI using foreach,
Now... could do 16 buttons but trying to automate build a little:
1,2,3,4 | foreach { $Button...}
all this works and I get 16 buttons with correct offsets but got stuck a little when decided to use jobs within buttons, background job pings, sleeps, pings - if fail to ping job ends and at this point I want it to change button's color
Since all buttons are "$Button",
can foreach generate $button with different number at the end? ie $Button1, $Button2... etc ?
tried $Button$_ but this didn't work
or any thoughts on how to reference buttons so depending on which job finished could change color of that button?
Cheers
#Wasif_Hasan this didn't work
$i=120
1..4 | Foreach {Set-Variable -Name "Button$($_)" -Value "Value"
$i=$i+70
$Button = New-Object System.Windows.Forms.Button
$Button.Location = New-Object System.Drawing.Point(150,$i)
$Button.Size = New-Object System.Drawing.Size(75,23)
$Button.Text = 'Cancel'+$_
$Button.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $Button
$form.Controls.Add($Button)
}
$Button3.Text = 'ok'+$_
Error:
The property 'Text' cannot be found on this object. Verify that the property exists and can be set.
Code that can be saved as .PS1 to check...
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$form = New-Object System.Windows.Forms.Form
$form.Text = 'Select a Computer'
$form.Size = New-Object System.Drawing.Size(300,400)
$form.StartPosition = 'CenterScreen'
$i=10
1..4 | Foreach {Set-Variable -Name "Button$($_)" -Value "Value"
$i=$i+50
$Button = New-Object System.Windows.Forms.Button
$Button.Location = New-Object System.Drawing.Point(150,$i)
$Button.Size = New-Object System.Drawing.Size(75,23)
$Button.Text = "Number"+$_
$form.Controls.Add($Button)
}
$Button3.Text = "Test"
$result = $form.ShowDialog()
Error:
The property 'Text' cannot be found on this object. Verify that the property
exists and can be set.
At line:19 char:1
+ $Button3.Text = "Test"
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException
Solution, Thanks Wasif_Hasan!
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$form = New-Object System.Windows.Forms.Form
$form.Text = 'Select a Computer'
$form.Size = New-Object System.Drawing.Size(300,400)
$form.StartPosition = 'CenterScreen'
$Button=1,2,3,4
$i=10
$k=1
1,2,3,4 | Foreach {
$i=$i+50
New-Variable "Button$_" -Value $(new-object System.Windows.Forms.Button -Property #{
Name = 'Dvar'
Location = New-Object System.Drawing.Size(10,$i)
Size = New-Object System.Drawing.Size(75,23)
Text = $_
})
$form.Controls.Add($(Get-Variable "Button$_" -ValueOnly))
$k=$k++
}
$Button2.Text="Hello"
$result = $form.ShowDialog()
$k=5
Remove-Variable Button*
$form.ActiveControl.Text
Result:
1
Hello
2
3
Yes, to set them use this:
1..4 | Foreach {Set-Variable -Name "Button$($_)" -Value "Value"}
And you can also get the values like:
1..4 | Foreach {(Get-Variable -Name "Button$($_)").Value}
All will be created like $Button1,$Button2 etc.

Returning multiple values from multiple drop-downs in Powershell

I am a very new to powershell. I was tasked with creating a GUI that takes in several strings from multiple drop-downs and renames the computer according to those choices. I am testing it with two options, $FacilityInitials and $BuildingNumber. Powershell is returning only the $BuildingNumber choice.
I may be doing something wrong with returning? How should I do multiple return fuctions properly? Thank you! :)
I tried checking for typos.
#Edit This item to change the DropDown Values
[array]$DropDownArray1 = "LI", "BE", "HA"
# This Function Returns the Selected Value and Closes the Form
function Return-DropDown {
$script:Choice = $DropDown1.SelectedItem.ToString()
$Form.Close()
}
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$Form = New-Object System.Windows.Forms.Form
$Form.width = 350
$Form.height = 200
$Form.Text = ”Computer Renamer”
$DropDown1 = new-object System.Windows.Forms.ComboBox
$DropDown1.Location = new-object System.Drawing.Size(100,30)
$DropDown1.Size = new-object System.Drawing.Size(130,30)
ForEach ($Item in $DropDownArray1) {
[void] $DropDown1.Items.Add($Item)
}
$Form.Controls.Add($DropDown1)
$DropDown1Label = new-object System.Windows.Forms.Label
$DropDown1Label.Location = new-object System.Drawing.Size(10,30)
$DropDown1Label.size = new-object System.Drawing.Size(100,20)
$DropDown1Label.Text = "Facility Initials:"
$Form.Controls.Add($DropDown1Label)
################################################################################
#Edit This item to change the DropDown Values
[array]$DropDownArray2 = "01", "02", "03"
# This Function Returns the Selected Value and Closes the Form
function Return-DropDown {
$script:Choice2 = $DropDown2.SelectedItem.ToString()
$Form.Close()
}
$DropDown2 = new-object System.Windows.Forms.ComboBox
$DropDown2.Location = new-object System.Drawing.Size(100,60)
$DropDown2.Size = new-object System.Drawing.Size(130,30)
ForEach ($Item in $DropDownArray2) {
[void] $DropDown2.Items.Add($Item)
}
$Form.Controls.Add($DropDown2)
$DropDown2Label = new-object System.Windows.Forms.Label
$DropDown2Label.Location = new-object System.Drawing.Size(10,60)
$DropDown2Label.size = new-object System.Drawing.Size(100,20)
$DropDown2Label.Text = "Building Number:"
$Form.Controls.Add($DropDown2Label)
################################################################################
#Button
$Button = new-object System.Windows.Forms.Button
$Button.Location = new-object System.Drawing.Size(100,130)
$Button.Size = new-object System.Drawing.Size(150,20)
$Button.Text = "Rename Computer"
$Button.Add_Click({Return-DropDown})
$form.Controls.Add($Button)
################################################################################
$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()
$FacilityInitials = $Choice
$BuildingNumber = $Choice2
$newCompName = $FacilityInitials + "-" + $BuildingNumber
$AdminAcc = ""
#Add Restart and Force later
Rename-Computer -NewName $newCompName -DomainCredential $AdminAcc

Whitelisting IP using appcmd.exe in powershell?

I am running this script to whitelist IP using appcmd.exe.
import-module WebAdministration
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$Form = New-Object System.Windows.Forms.Form
$Form.Size = New-Object System.Drawing.Size(600,400)
$type="Allow"
function SaveConfig
{
if($Dropdownbox.text -eq "allow"){
$allowed = "true"
}
else{
$allowed = "false"
}
$outputbox.text = "IP " + $ip.text + " is Whitelisted for the URL " + $url.text + " with subnet mask as " + $mask.text + ". " + "User wants to " + $Dropdownbox.text + " this."
<# $url = "capitaliq/ciqdotnet/clientadmin/clientmgr.html"
$ip = "192.168.1.1" #>
$url.text
Set-Location "C:\Windows\System32\inetsrv"; .\appcmd.exe set config "$url.text" -section:system.webServer/security/ipSecurity /+"[ipAddress='$ip.text',allowed='True',subnetMask='$mask.text']" /commit:apphost
$ip.text
$url.text = ""
$ip.text = ""
$dropdownbox.text = ""
}
function close{
$Form.close()
}
$url_label = New-Object System.Windows.Forms.Label
$url_label.Location = New-Object System.Drawing.Size(40,20)
$url_label.Size = New-Object System.Drawing.Size(280,20)
$url_label.Text = "Please enter the URL"
$Form.Controls.Add($url_label)
$url = New-Object System.Windows.Forms.TextBox
$url.Location = New-Object System.Drawing.Size(40,50)
$url.Size = New-Object System.Drawing.Size(260,60)
$Form.Controls.Add($url)
$ip_label = New-Object System.Windows.Forms.Label
$ip_label.Location = New-Object System.Drawing.Size(40,110)
$ip_label.Size = New-Object System.Drawing.Size(280,20)
$ip_label.Text = "Please enter the IP address"
$Form.Controls.Add($ip_label)
$ip = New-Object System.Windows.Forms.TextBox
$ip.Location = New-Object System.Drawing.Size(40,140)
$ip.Size = New-Object System.Drawing.Size(260,60)
$Form.Controls.Add($ip)
$DropDownBox = New-Object System.Windows.Forms.ComboBox
$DropDownBox.Location = New-Object System.Drawing.Size(40,80)
$DropDownBox.Size = New-Object System.Drawing.Size(180,20)
$DropDownBox.DropDownHeight = 400
$Form.Controls.Add($DropDownBox)
$wksList=#("Allow","Deny")
foreach ($wks in $wksList)
{
$DropDownBox.Items.Add($wks)
}
$mask_label = New-Object System.Windows.Forms.Label
$mask_label.Location = New-Object System.Drawing.Size(40,170)
$mask_label.Size = New-Object System.Drawing.Size(280,20)
$mask_label.Text = "Please enter the Subnet Mask"
$Form.Controls.Add($mask_label)
$mask = New-Object System.Windows.Forms.TextBox
$mask.Location = New-Object System.Drawing.Size(40,200)
$mask.Size = New-Object System.Drawing.Size(260,60)
$mask.Text="255.255.255.0"
$Form.Controls.Add($mask)
$Button = New-Object System.Windows.Forms.Button
$Button.Location = New-Object System.Drawing.Size(40,230)
$Button.Size = New-Object System.Drawing.Size(110,50)
$Button.Text = "Save"
$Button.Add_Click({SaveConfig})
$Form.Controls.Add($Button)
$Button = New-Object System.Windows.Forms.Button
$Button.Location = New-Object System.Drawing.Size(170,230)
$Button.Size = New-Object System.Drawing.Size(110,50)
$Button.Text = "Close"
$Button.Add_Click({Close})
$Form.Controls.Add($Button)
$outputBox = New-Object System.Windows.Forms.TextBox
$outputBox.Location = New-Object System.Drawing.Size(350,50)
$outputBox.Size = New-Object System.Drawing.Size(200,200)
$outputBox.MultiLine = $True
$outputBox.ReadOnly= $True
$Form.Controls.Add($outputBox)
$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()
For some reason, this line of the code is not getting executed:
Set-Location "C:\Windows\System32\inetsrv"; .\appcmd.exe set config "$url.text" -section:system.webServer/security/ipSecurity /+" [ipAddress='$ip.text',allowed='True',subnetMask='$mask.text']" /commit:apphost
attached is the image which shows that script is only setting location to desired and nothing else. $url.text and $ip.text before and after this line is not getting executed as well.
It most certainly executes appcmd.exe, you just don't see the output from the Click event since it's running in its own scope.
Your appcmd.exe most likely fails because you attempt to expand $ip.text inside a double-quoted string. The parser will convert the entire $ip object to a string and concatenate the literal string ".text", resulting in the following appcmd.exe argument:
/+" [ipAddress='System.Windows.Forms.TextBox, Text: .text',allowed='True',subnetMask='System.Windows.Forms.TextBox, Text: .text']"
Enclose $ip.Text and $mask.Text in a subexpression ($()) instead:
.\appcmd.exe set config "$($url.Text)" -section:system.webServer/security/ipSecurity /+" [ipAddress='$($ip.Text)',allowed='True',subnetMask='$($mask.Text)']" /commit:apphost