Better way to validate when not using a function ValidateSet - powershell

I'm looking for a better way to validate a "response" from a user for my script. I know you can use a function to validate this but I want it to be more interactive.
$DPString = #"
Enter users department.
Valid choices are;
"Accounts","Claims","Broker Services","Underwriting","Compliance","HR","IT","Developmet","Legal" and "Legal Underwriting"
"#
$Department = Read-Host "$DPString"
do
{
Switch ($Department)
{
Accounts { $DepBool = $true }
Claims { $DepBool = $true }
"Broker Services" { $DepBool = $true }
Underwriting { $DepBool = $true }
Compliance { $DepBool = $true }
"Legal Underwriting" { $DepBool = $true }
Legal { $DepBool = $true }
HR { $DepBool = $true }
IT { $DepBool = $true }
Development { $DepBool = $true }
Default { $DepBool = $false }
}
if ($DepBool -eq $true)
{
$DepLoop = $false
}
else {
$Department = Read-Host "Please enter a valid Department"
$DepLoop = $true
}
}
while ($DepLoop)

It's not clear in what context the user is being prompted for input, but I would favour a list of valid parameters being passed in on the command line. I would make them mutually exclusive using Parameter Sets.
However, if this is a part of a larger script which prompts for input part way through, then it might be appropriate to prompt for input using the windows API for displaying an input box. Here's a link which describes this approach in more detail Creating a Custom Input Box.
Although it feels wrong to display UI from powershell, I understand that there are times when this is desirable, using the link above here's an implementation of a ListBox, you simply pass it a string array and it returns the selected value:
<#
.SYNOPSIS
Displays a Windows List Control and returns the selected item
.EXAMPLE
Get-ListBoxChoice -Title "Select Environment" -Prompt "Choose an environment" -Options #("Option 1","Option 2")
This command displays a list box containing two options.
.NOTES
There are two command buttons OK and Cancel, selecting OK will return the selected option, whilst
Cancel will return nothing.
.RELATED LINKS
http://technet.microsoft.com/en-us/library/ff730941.aspx
#>
Function Get-ListBoxChoice
{
[cmdletbinding()]
param
(
[Parameter(Mandatory=$true)]
[string] $Title,
[Parameter(Mandatory=$true)]
[string] $Prompt,
[Parameter(Mandatory=$true)]
[string[]] $Options
)
Write-Verbose "Get-ListBoxChoice"
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$uiForm = New-Object System.Windows.Forms.Form
$uiForm.Text = $Title
$uiForm.FormBorderStyle = 'Fixed3D'
$uiForm.MaximizeBox = $false
$uiForm.Size = New-Object System.Drawing.Size(300,240)
$uiForm.StartPosition = "CenterScreen"
$uiForm.KeyPreview = $True
$uiForm.Add_KeyDown({if ($_.KeyCode -eq "Enter")
{$chosenValue=$objListBox.SelectedItem;$uiForm.Close()}})
$uiForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")
{$uiForm.Close()}})
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(75,160)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.Add_Click({$chosenValue=$objListBox.SelectedItem;$uiForm.Close()})
$uiForm.Controls.Add($OKButton)
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(150,160)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"
$CancelButton.Add_Click({$uiForm.Close()})
$uiForm.Controls.Add($CancelButton)
$uiLabel = New-Object System.Windows.Forms.Label
$uiLabel.Location = New-Object System.Drawing.Size(10,20)
$uiLabel.Size = New-Object System.Drawing.Size(280,20)
$uiLabel.Text = $Prompt
$uiForm.Controls.Add($uiLabel)
$objListBox = New-Object System.Windows.Forms.ListBox
$objListBox.Location = New-Object System.Drawing.Size(10,40)
$objListBox.Size = New-Object System.Drawing.Size(260,20)
$objListBox.Height = 120
$Options | % {
[void] $objListBox.Items.Add($_)
}
$uiForm.Controls.Add($objListBox)
$uiForm.Topmost = $True
$uiForm.Add_Shown({$uiForm.Activate()})
[void] $uiForm.ShowDialog()
$chosenValue
}

If they're running at least V3, you can use Out-Gridview:
$Departments = #(
[PSCustomObject]#{Name = 'Accounts';Description = 'Accounting Department'}
[PSCustomObject]#{Name = 'Claims';Description = 'Claims Department'}
[PSCustomObject]#{Name = 'Broker';Description = 'Broker Services'}
)
$GridParams = #{
Title = "Select a department, and press 'OK', or 'Cancel' to quit."
OutPutMode = 'Single'
}
$Department = $Departments | Out-Gridview #GridParams
If ($Department)
{ #Do stuff }

Related

Prevent Powershell GUI from closing

I want to prevent my Powershell Form from closing after a submit button is pressed. After the function "search_PC" there is no more code and the form closes. I want to still be able to write stuff in there after the function is finished. I have already tried the pause function and while($true) loops. I would be very happy about an answer.
Import-Module ActiveDirectory
# Assembly for GUI
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
# Create Form
$objForm = New-Object System.Windows.Forms.Form
$objForm.Size = New-Object System.Drawing.Size(400,500)
$objForm.Backcolor="white"
$objForm.StartPosition = "CenterScreen"
$objForm.Text = "Example Software"
$objForm.Icon="C:\Users\...\icon.ico"
# Label
$objLabel1 = New-Object System.Windows.Forms.Label
$objLabel1.Location = New-Object System.Drawing.Size(80,30)
$objLabel1.Size = New-Object System.Drawing.Size(60,20)
$objLabel1.Text = "UserID:"
$objForm.Controls.Add($objLabel1)
# Textbox
$objTextBox1 = New-Object System.Windows.Forms.TextBox
$objTextBox1.Location = New-Object System.Drawing.Size(160,28)
$objTextBox1.Size = New-Object System.Drawing.Size(100,20)
$objForm.Controls.Add($objTextBox1)
# Label
$objLabel2 = New-Object System.Windows.Forms.Label
$objLabel2.Location = New-Object System.Drawing.Size(80,72)
$objLabel2.Size = New-Object System.Drawing.Size(80,20)
$objLabel2.Text = "PC-Name:"
$objForm.Controls.Add($objLabel2)
# Textbox
$objTextBox2 = New-Object System.Windows.Forms.TextBox
$objTextBox2.Location = New-Object System.Drawing.Size(160,70)
$objTextBox2.Size = New-Object System.Drawing.Size(100,20)
$objForm.Controls.Add($objTextBox2)
# Button for closing
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(100,220)
$CancelButton.Size = New-Object System.Drawing.Size(163,25)
$CancelButton.Text = "Exit"
$CancelButton.Name = "Exit"
$CancelButton.DialogResult = "Cancel"
$CancelButton.Add_Click({$objForm.Close()})
$objForm.Controls.Add($CancelButton)
# Checkbox
$objTypeCheckbox1 = New-Object System.Windows.Forms.Checkbox
$objTypeCheckbox1.Location = New-Object System.Drawing.Size(80,120)
$objTypeCheckbox1.Size = New-Object System.Drawing.Size(500,20)
$objTypeCheckbox1.Text = "Internal Session Support"
$objTypeCheckbox1.TabIndex = 1
$objTypeCheckbox1.Add_Click({$objTypeCheckbox2.Checked = $false})
$objForm.Controls.Add($objTypeCheckbox1)
# Checkbox
$objTypeCheckbox2 = New-Object System.Windows.Forms.Checkbox
$objTypeCheckbox2.Location = New-Object System.Drawing.Size(80,140)
$objTypeCheckbox2.Size = New-Object System.Drawing.Size(500,20)
$objTypeCheckbox2.Text = "Session Support Internal & external"
$objTypeCheckbox2.TabIndex = 2
$objTypeCheckbox2.Add_Click({$objTypeCheckbox1.Checked = $false})
$objForm.Controls.Add($objTypeCheckbox2)
# Button fo checking the User Input
$SubmitButton = New-Object System.Windows.Forms.Button
$SubmitButton.Location = New-Object System.Drawing.Size(100,190)
$SubmitButton.Size = New-Object System.Drawing.Size(163,25)
$SubmitButton.Text = "Submit"
$SubmitButton.Name = "Submit"
$SubmitButton.DialogResult = "OK"
$objForm.AcceptButton = $SubmitButton
$SubmitButton.Add_Click({
$User = $objTextBox1.Text
$PC = $objTextBox2.Text
# Check if all User Inputs are filled out
if ( !($User.trim()) -or !($PC.trim()) ) {
[void] [Windows.Forms.MessageBox]::Show("Please fill out every value!", "Error", [Windows.Forms.MessageBoxButtons]::ok, [Windows.Forms.MessageBoxIcon]::Warning)}
if($objTypeCheckbox1.checked -eq $true) {$Software = "Internal"}
elseif($objTypeCheckbox2.checked -eq $true) {$Software = "Internal&External"}
else {[void] [Windows.Forms.MessageBox]::Show("Please fill out every value!", "Error", [Windows.Forms.MessageBoxButtons]::ok, [Windows.Forms.MessageBoxIcon]::Warning)}
search_user
})
$objForm.Controls.Add($SubmitButton)
$statusBar1 = New-Object System.Windows.Forms.StatusBar
$objForm.controls.add($statusBar1)
function createFile
{
$Date = Get-Date -Format d.M.yyyy
$Time = (Get-Date).ToString(„HH:mm:ss“)
$Time2 = (Get-Date).ToString(„HH-mm-ss“)
$Date2 = Get-Date -Format yyyy-M-d;
$FileName = $Time2 + " " + $Date2
$wrapper = New-Object PSObject -Property #{ 1 = $Date; 2 = $Time; 3 = $User; 4 = $PC; 5 = $Software }
Export-Csv -InputObject $wrapper -Path C:\Users\...\$FileName.csv -NoTypeInformation
[void] [Windows.Forms.MessageBox]::Show("Successful!")
}
function search_user
{
if (#(Get-ADUser -Filter {SamAccountName -eq $User}).Count -eq 0) {
$objTextBox1.BackColor = "Red";
$statusBar1.Text = "Couldn't find user!"
$objForm.Dispose()
}
else{$objTextBox1.BackColor = "Green"
search_PC}
}
function search_PC
{
$Client = $PC
if (#(Get-ADComputer -Filter {DNSHostName -eq $Client}).Count -eq 0) {
$objTextBox2.BackColor = "Red";
$statusBar1.Text = "Couldn't find PC!"
$objForm.Dispose()
}
else{$objTextBox2.BackColor = "Green"
createFile}
}
$objForm.ShowDialog() #Showing Form and elements
Screenshot of the form:
This line is your problem:
$SubmitButton.DialogResult = "OK"
It should be:
$SubmitButton.DialogResult = [System.Windows.Forms.DialogResult]::None
Or just be removed.
DialogResult

Powershell password GUI (easy)

I'm looking for a simple script for a password-check in a Powershell GUI.
I have tried different types of codes but sometimes it can't read the textbox and sometimes it can't register the clicks.
So I have two buttons and a textbox.
If I have the right password and press enter I want it to do something.
If I have the wrong password I can try again.
But I have no idea how to do this with buttons in a GUI.
So I wonder I anyone has done something similar?
Heres what I have now about the "if" statment:
if ($Result = [System.Windows.Forms.DialogResult]::OK) {
$OKButton.Add_Click( { $OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK })
$OKButton.Add_Enter( { $OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK })
$CancelButton.Add_Click( { $CancelButton.Add_Click( { $CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel }) })
if (([string]::IsNullOrEmpty($MaskedTextBox)) -or ([string]::IsNullOrEmpty($Pword))) {
write-host "Passwords can not be NULL or empty"
}
else {
if ($MaskedTextBox -cne $PWord) {
write-host "Fel"
}
else {
($MaskedTextBox -eq $PWord)
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\USBSTOR\" -Name "start" -Value 3
write-host "Rätt"
}
}
}
This should do the trick:
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$password = "Test"
$script:isMatch = $false
[System.Windows.Forms.Application]::EnableVisualStyles()
$form = New-Object System.Windows.Forms.Form
$form.Visible = $false
[void]$form.SuspendLayout()
$form.Text = 'Password Window'
$form.ClientSize = New-Object System.Drawing.Size(160,120)
$form.StartPosition = 'CenterScreen'
$form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedSingle
$CTRL_label1 = New-Object System.Windows.Forms.Label
$CTRL_label1.Location = New-Object System.Drawing.Point(10,10)
$CTRL_label1.Size = New-Object System.Drawing.Size(280,20)
$CTRL_label1.Text = 'Please enter password:'
$CTRL_label1.Name = 'Label1'
[void]$form.Controls.Add($CTRL_label1)
$CTRL_password = New-Object System.Windows.Forms.TextBox
$CTRL_password.Location = New-Object System.Drawing.Point(10,30)
$CTRL_password.PasswordChar = '*'
$CTRL_password.Size = New-Object System.Drawing.Size(140,20)
$CTRL_password.MaxLength = 20
$CTRL_password.Name = 'Password'
[void]$form.Controls.Add($CTRL_password)
$CTRL_label2 = New-Object System.Windows.Forms.Label
$CTRL_label2.Location = New-Object System.Drawing.Point(10,60)
$CTRL_label2.Size = New-Object System.Drawing.Size(280,20)
$CTRL_label2.ForeColor = [System.Drawing.Color]::Red
$CTRL_label2.Text = ''
$CTRL_label2.Name = 'Label2'
[void]$form.Controls.Add($CTRL_label2)
$CTRL_Button = New-Object System.Windows.Forms.Button
$CTRL_Button.Location = New-Object System.Drawing.Point(10,90)
$CTRL_Button.Size = New-Object System.Drawing.Size(140,23)
$CTRL_Button.Text = 'OK'
$CTRL_Button.Name = 'OK'
$CTRL_Button.Add_Click( {
if ( $CTRL_password.Text.Trim() -ceq $password ) {
$script:isMatch = $true
[void]$form.Close()
[void]$form.Dispose()
}
else {
$CTRL_label2.Text = 'wrong password!'
}
} )
[void]$form.Controls.Add($CTRL_Button)
[void]$form.ResumeLayout()
$userInput = $form.ShowDialog()
if( $script:isMatch ) {
# do anything => passwort is ok!
"OK!"
}

i want to create a GUI powershell script which should perform the following operation,

i want to create a GUI powershell script which should perform the following operation, if i give a name it should search in a specific list (may be in AD or in a database list) and if it found the exact name there then the name should be copied and the same name should be used to provide permission to a folder which is available in a path i mentioned.
mY CODE
function selectShare{
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
####################################################################
$Form = New-Object System.Windows.Forms.Form #
#
$Form.width = 300 # Main Window Section
$Form.height = 200 #
$Form.Text = ”File Sharing” #
#######################################################################################
#below section function of "Select an item button"
$Button = new-object System.Windows.Forms.Button
$Button.Location = new-object System.Drawing.Size(100,100)
$Button.Size = new-object System.Drawing.Size(105,25)
$Button.Text = "New Folder"
$Button.Add_Click({New-Item “h:\shan" –type directory
NET SHARE shan = h:\shan /GRANT:everyone`,FULL})
###################
################### button section
$Button1 = new-object System.Windows.Forms.Button
$Button1.Location = new-object System.Drawing.Size(100,50)
$Button1.Size = new-object System.Drawing.Size(105,25)
$Button1.Text = "Existing Folder"
$Button1.Add_Click(
{
function Find-Folders
{
[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
[System.Windows.Forms.Application]::EnableVisualStyles()
$FolderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog
$browse = New-Object System.Windows.Forms.FolderBrowserDialog
$browse.SelectedPath = "C:\"
$browse.ShowNewFolderButton = $true
$browse.Description = "Select a Folder"
$loop = $true
while($loop)
{
if ($browse.ShowDialog() -eq "OK")
{
$loop = $false
$FolderBrowser.SelectedPath
#Insert your script here
} else
{
$res = [System.Windows.Forms.MessageBox]::Show("You clicked Cancel. Would you like to try again or exit?", "Select a location", [System.Windows.Forms.MessageBoxButtons]::RetryCancel)
if($res -eq "Cancel")
{
#Ends script
return
}
}
}
$browse.SelectedPath
$browse.Dispose()
} Find-Folders})
$form.Controls.Add($Button)
$form.Controls.Add($Button1)
$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()
return $script:choice
}
$share = selectShare
write-host $share

Powershell - Function within IfElse not providing results

I have the below snippet of code that is supposed to give the user (myself) a YesNo box. If I select Yes, it assigns a value to a variable ($Category). If I select No, it is supposed to start the IncOrRitm function, which I then select from two radio buttons. Each button has a variable assigned to it, with a value to for that variable. If No was selected, the value for the variable assigned to whichever radio button I select should be assigned to the $Category variable.
The logic is this:
Correct category?
Yes -> $Category = Yes
No -> What should ticket have been?
Incident -> $Category = Incident
RITM -> $Category = RITM
However, only the "Yes" part of this code works. I am not sure if I am missing something, or if the function is nested incorrectly, or what....
# is the ticket correctly listed as an incident/ritm
Add-Type -AssemblyName PresentationCore,PresentationFramework
$ButtonType = [System.Windows.MessageBoxButton]::YesNo
$MessageTitle = "Incident or RITM"
$MessageBody = "Was the category correctly selected?"
$IncOrRITM = [System.Windows.MessageBox]::Show($MessageBody,$MessageTitle,$ButtonType)
if ($IncOrRITM -eq "Yes")
{
$Category = "Correct"
}
elseif ($IncOrRITM -eq "No")
{
function IncOrRITM{
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$Form = New-Object System.Windows.Forms.Form
$Form.width = 300
$Form.height = 170
$Form.Text = ”What Should The Ticket Have Been?"
$Font = New-Object System.Drawing.Font("Verdana",11)
$Form.Font = $Font
$MyGroupBox = New-Object System.Windows.Forms.GroupBox
$MyGroupBox.Location = '5,5'
$MyGroupBox.size = '275,65'
$RadioButton1 = New-Object System.Windows.Forms.RadioButton
$RadioButton1.Location = '20,20'
$RadioButton1.size = '90,30'
$RadioButton1.Checked = $false
$RadioButton1.Text = "Incident"
$RB1 = "Incorrect - Should be an Incident"
$RadioButton2 = New-Object System.Windows.Forms.RadioButton
$RadioButton2.Location = '150,20'
$RadioButton2.size = '90,30'
$RadioButton2.Checked = $false
$RadioButton2.Text = "RITM"
$RB2 = "Incorrect - Should be an RITM"
$OKButton = new-object System.Windows.Forms.Button
$OKButton.Location = '10,90'
$OKButton.Size = '90,35'
$OKButton.Text = 'OK'
$OKButton.DialogResult=[System.Windows.Forms.DialogResult]::OK
$CancelButton = new-object System.Windows.Forms.Button
$CancelButton.Location = '180,90'
$CancelButton.Size = '90,35'
$CancelButton.Text = "Cancel"
$CancelButton.Add_Click({$objForm.Close()})
$CancelButton.DialogResult=[System.Windows.Forms.DialogResult]::Cancel
$form.Controls.AddRange(#($MyGroupBox,$OKButton,$CancelButton))
$MyGroupBox.Controls.AddRange(#($Radiobutton1,$RadioButton2))
$form.AcceptButton = $OKButton
$form.CancelButton = $CancelButton
$form.Add_Shown({$form.Activate()})
$dialogResult = $form.ShowDialog()
if ($DialogResult -eq "OK")
{
if ($RadioButton1.Checked){$Category = $RB1}
if ($RadioButton2.Checked){$Category = $RB2}
}
elseif ($DialogResult -eq "Cancel")
{
break
}
}
IncOrRITM
}
Within the IncOrRITM function, $Catalog becomes a local variable once you assign to it. You don't return its value, so it is lost.
You can see a detailed explanation of variable scope in this answer on another question.
You should return the value you want from the function, then assign $Category to its call:
function IncOrRITM {
# Other code
if ($DialogResult -eq "OK")
{
if ($RadioButton1.Checked){ $RB1 }
if ($RadioButton2.Checked){ $RB2 }
}
elseif ($DialogResult -eq "Cancel")
{
break
}
}
$Category = IncOrRITM
Adding $global: to the variable fixes it.

grey out a textbox until enabled by checkbox

I'm creating a script and I want the user to mark certain checkboxes to enable txtboxes.
When the user presses the chexbox, the textbox next to it will be enabled. If they don't, then they cannot insert text into it.
Right now it doesn't work, has someone an idea how to change it?
Thanks for your help!
Here is the part of my script with the checkbox and the textbox:
#creating the whole form
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "Ofir`s script"
$objForm.Size = New-Object System.Drawing.Size(480,240)
$objForm.StartPosition = "CenterScreen"
#This creates the TextBox1
$objTextBox1 = New-Object System.Windows.Forms.TextBox
$objTextBox1.Location = New-Object System.Drawing.Size(300,40)
$objTextBox1.Size = New-Object System.Drawing.Size(140,150)
$objTextBox1.TabIndex = 3
$objTextBox1.text = Dsp.z
$objForm.Controls.Add($objTextBox1)
#This creates a checkbox for textbox1
$objDsp2Checkbox = New-Object System.Windows.Forms.Checkbox
$objDsp2Checkbox.Location = New-Object System.Drawing.Size(280,40)
$objDsp2Checkbox.Size = New-Object System.Drawing.Size(150,20)
$objDsp2Checkbox.TabIndex = 0
$objForm.Controls.Add($objDsp2Checkbox)
#changing the file name
if ($objDsp2Checkbox.Checked -eq $true)
{
$objTextBox1.Enabled = $true
}
elseif ($objDsp2Checkbox.Checked -eq $false)
{
$objTextBox1.Enabled = $false
}
#makes the form appear on top of the screen
$objForm.Topmost = $True
$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()
You need to assign the bit of code that enables/disables the text box to an event handler on the checkbox object. Most likely the Click event.
$objDsp2Checkbox_OnClick = {
if ($objDsp2Checkbox.Checked -eq $true)
{
$objTextBox1.Enabled = $true
}
elseif ($objDsp2Checkbox.Checked -eq $false)
{
$objTextBox1.Enabled = $false
}
}
$objDsp2Checkbox.Add_Click($objDsp2Checkbox_OnClick)
http://social.technet.microsoft.com/wiki/contents/articles/25911.how-to-add-a-powershell-gui-event-handler-part-1.aspx
https://msdn.microsoft.com/en-us/library/system.windows.forms.textbox(v=vs.110).aspx