Reputation: 496
I have a long script that provides a user with prompts: enter a ticket number (commented out for now), enter an email address (also commented) and select from a series of 4 checkboxes. The idea is that a new person can get access to any combo of 4 different locations. 2 locations are handled by 1 admin, and the other 2 by a single admin (IE, A & B are handled by admin A, C is handled by admin B, and D by C). Therefore, I wrote a long script that includes a snippet of code for each location combination without duplication. So, you could select A, AB, AC, AD, ABC, ABD, ect.
If I include code to just send an email when A, B, C OR D is chosen, everything works great. When I include code to, say, select A & B, the script does not work right.
An example: I select to include access to building A. The email gets sent saying user needs access to A. Another example: I select to include access to building B. The emails gets sent saying user needs access to B. Final example with the issue: I select to include access to buildings A and B. I get a prompt to include access to A and a prompt to include access to A and B, but I get 2 emails to include access to A. I should get 1 prompt and 1 email both stating access to A and B.
For brevity, I have clipped a lot of the code to remove all combinations besides the code for A, and A & B. If you need me to include more, please let me know.
# initialize the script
if ($startupvariables) { try {Remove-Variable -Name startupvariables -Scope Global -ErrorAction SilentlyContinue } catch { } }
New-Variable -force -name startupVariables -value ( Get-Variable | ForEach-Object { $_.Name } )
# make sure the cmd window is not closed
Write-Output "Don't close this window!"
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
$Separator = ".", "@"
# advise what the script does
Add-Type -AssemblyName PresentationCore,PresentationFramework
$ButtonType = [System.Windows.MessageBoxButton]::OKCancel
$MessageIcon = [System.Windows.MessageBoxImage]::Warning
$MessageTitle = "Building Access - US Corp Locations"
$MessageBody = "This script sends the building admins for the US corporate locations an email advising them that a user needs access to their location.`n`nTo use it, enter the below information:`n`n`n`tSCTask Ticket Number`n`n`tUser's Email Address`n`n`tBuilding Access Requested`n`n`nIf this is the script you want to use, click OK.`nIf not, click Cancel."
$Result = [System.Windows.MessageBox]::Show($MessageBody,$MessageTitle,$ButtonType,$MessageIcon)
if ($Result -eq "Cancel")
{
Exit-PSSession
}
else
{
# get the ticket number
###################
# $Ticket = [Microsoft.VisualBasic.Interaction]::InputBox("Enter the SCTask ticket number" , "Ticket Number")
$Ticket = 1234567890
###################
# get the user id via the email address
###################
# $UserID = [Microsoft.VisualBasic.Interaction]::InputBox("Enter the user's email address" , "User Email Address")
$UserID = "xxxxxxxxxxx.com"
###################
$User = $UserID.split($Separator)
$Firstname = $User[0].substring(0,1).toupper()+$User[0].substring(1).tolower()
$Lastname = $User[1].substring(0,1).toupper()+$User[1].substring(1).tolower()
$User = $Firstname, $Lastname
# get the local username
$Username = [System.Environment]::UserName
# provide checkboxes for locations requested
function Location_Access{
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$Form = New-Object System.Windows.Forms.Form
$Form.width = 415
$Form.height = 235
$Form.Text = ”Select Building Locations"
$Font = New-Object System.Drawing.Font("Verdana",11)
$Form.Font = $Font
$MyGroupBox = New-Object System.Windows.Forms.GroupBox
$MyGroupBox.Location = '5,5'
$MyGroupBox.size = '385,135'
$Checkbox1 = New-Object System.Windows.Forms.Checkbox
$Checkbox1.Location = '20,20'
$Checkbox1.size = '360,25'
$Checkbox1.Checked = $false
$Checkbox1.Text = "World Headquarters (Maumee, OH)"
$CB1 = "World Headquarters"
$Checkbox2 = New-Object System.Windows.Forms.Checkbox
$Checkbox2.Location = '20,45'
$Checkbox2.size = '360,25'
$Checkbox2.Checked = $false
$Checkbox2.Text = "Maumee Technology Center (Maumee, OH)"
$CB2 = "Maumee Technology Center"
$Checkbox3 = New-Object System.Windows.Forms.Checkbox
$Checkbox3.Location = '20,70'
$Checkbox3.size = '360,25'
$Checkbox3.Checked = $false
$Checkbox3.Text = "Global IT Center/Longbow (Maumee, OH)"
$CB3 = "Global IT Center/Longbow"
$Checkbox4 = New-Object System.Windows.Forms.Checkbox
$Checkbox4.Location = '20,95'
$Checkbox4.size = '360,25'
$Checkbox4.Checked = $false
$Checkbox4.Text = "Novi (Novi, MI)"
$CB4 = "Novi"
$OKButton = new-object System.Windows.Forms.Button
$OKButton.Location = '10,150'
$OKButton.Size = '90,35'
$OKButton.Text = 'OK'
$OKButton.DialogResult=[System.Windows.Forms.DialogResult]::OK
$CancelButton = new-object System.Windows.Forms.Button
$CancelButton.Location = '110,150'
$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(@($Checkbox1,$Checkbox2,$Checkbox3,$Checkbox4))
$form.AcceptButton = $OKButton
$form.CancelButton = $CancelButton
$form.Add_Shown({$form.Activate()})
$dialogResult = $form.ShowDialog()
if ($DialogResult -eq "OK")
{
# if WHQ is selected
if ($Checkbox1.Checked)
{
$subject = "Ticket $Ticket - $User's Building Access Request"
$body = @"
<html>
<body style="font-family:calibri">
Team,<br>
<br>
<br>
Per ticket $Ticket, $User is requesting building access to:<br>
<br>
<br>
<b><u>$CB1</b></u><br>
<br>
<br>
<br>
Thank You,<br>
<br>
IT Service Desk<br>
<br>
------------------------------------------------------------------ <br>
IT Service Desk Operation Information <br>
------------------------------------------------------------------ <br>
Hours of Operation : 24 hours a day<br>
xxxxxxxxxxxxxxxx
</body>
</html>
"@
}
# create confirmation message
$ButtonType = [System.Windows.MessageBoxButton]::YesNo
$MessageIcon = [System.Windows.MessageBoxImage]::Warning
$MessageTitle = "Corporate Building Access Request"
$MessageBody = "The information you have entered is show below:`n`n`nTicket Number: $Ticket`n`nUser's Email Address: $UserID`n`nAccess To: $CB1`n`n`nIf you would like to send the email, click Yes.`nOtherwise, click No."
$Result = [System.Windows.MessageBox]::Show($MessageBody,$MessageTitle,$ButtonType,$MessageIcon)
if ($Result -eq "No")
{
Exit-PSSession
}
else
# send email
{
Send-MailMessage -To "<[email protected]>" -from "<[email protected]>" -Subject $subject -SmtpServer "mailrelay.xxxx.com" -BodyAsHtml -body $body
}
# if WHQ & MTC is selected
elseif ($Checkbox1.Checked -And $Checkbox2.Checked)
{
$subject = "Ticket $Ticket - $User's Building Access Request"
$body = @"
<html>
<body style="font-family:calibri">
Team,<br>
<br>
<br>
Per ticket $Ticket, $User is requesting building access to:<br>
<br>
<br>
<b><u>$CB1 & $CB2</b></u><br>
<br>
<br>
<br>
Thank You,<br>
<br>
IT Service Desk<br>
<br>
------------------------------------------------------------------ <br>
IT Service Desk Operation Information <br>
------------------------------------------------------------------ <br>
Hours of Operation : 24 hours a day<br>
xxxxxxxxx
</body>
</html>
"@
}
# create confirmation message
$ButtonType = [System.Windows.MessageBoxButton]::YesNo
$MessageIcon = [System.Windows.MessageBoxImage]::Warning
$MessageTitle = "Corporate Building Access Request"
$MessageBody = "The information you have entered is show below:`n`n`nTicket Number: $Ticket`n`nUser's Email Address: $UserID`n`nAccess To: $CB1 & $CB2`n`n`nIf you would like to send the email, click Yes.`nOtherwise, click No."
$Result = [System.Windows.MessageBox]::Show($MessageBody,$MessageTitle,$ButtonType,$MessageIcon)
if ($Result -eq "No")
{
Exit-PSSession
}
else
# send email
{
Send-MailMessage -To "<[email protected]>" -from "<[email protected]>" -Subject $subject -SmtpServer "mailrelay.xxxx.com" -BodyAsHtml -body $body
}
}
elseif ($DialogResult -eq "Cancel")
{
break
}
}
Location_Access
}
Function Clean-Memory {
Get-Variable |
Where-Object { $startupVariables -notcontains $_.Name } |
ForEach-Object {
try { Remove-Variable -Name "$($_.Name)" -Force -Scope "global" -ErrorAction SilentlyContinue -WarningAction SilentlyContinue}
catch { }
}
}
I should not get that middle prompt, only the second one where it prompts for both locations selected. Included with each prompt is an email for the building access. However, I get 2 emails both for access to the first building, and neither mentioning the second building.
I know this is odd, and probably seems convoluted. Please let me know what other info you might need. I can include the full code if needed; just wanted to cut out as much extras as possible.
Update: error when running script
You cannot call a method on a null-valued expression.
At line:109 char:42
+ $MyGroupBox.Controls | % {if($_.Checked){[Void]$TextTotal.AppendLine($_.Text);[V ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At line:142 char:154
+ ... `nAccess To: $($TextTotal.ToString())`n`n`nIf you would like to send the email, ...
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Upvotes: 0
Views: 2499
Reputation: 3236
I think you need to build up final message according to elements checked. Add this piece of code right after form showdialog call ($dialogResult = $form.ShowDialog())
$CheckedBoxes = New-Object System.Text.StringBuilder
$CheckedBoxesForEmail = New-Object System.Text.StringBuilder
$MyGroupBox.Controls | % {if($_.Checked){[Void]$TextTotal.AppendLine($_.Text);[Void]$CheckedBoxesForEmail.AppendLine('<b><u>{0}</b></u><br>' -f $_.Text)}}
Then just throw away all those needless IF statements for every checkbox. I have changed variable $CB1 to this $($CheckedBoxesForEmail.ToString()) and this $($TextTotal.ToString()). Those will carry all the text you want.
$CheckedBoxes = New-Object System.Text.StringBuilder
$CheckedBoxesForEmail = New-Object System.Text.StringBuilder
$MyGroupBox.Controls | % {if($_.Checked){[Void]$TextTotal.AppendLine($_.Text);[Void]$CheckedBoxesForEmail.AppendLine('<b><u>{0}</b></u><br>' -f $_.Text)}}
if ($DialogResult -eq "OK")
{
$subject = "Ticket $Ticket - $User's Building Access Request"
$body = @"
<html>
<body style="font-family:calibri">
Team,<br>
<br>
<br>
Per ticket $Ticket, $User is requesting building access to:<br>
<br>
<br>$($CheckedBoxesForEmail.ToString())<br>
<br>
<br>
Thank You,<br>
<br>
IT Service Desk<br>
<br>
------------------------------------------------------------------ <br>
IT Service Desk Operation Information <br>
------------------------------------------------------------------ <br>
Hours of Operation : 24 hours a day<br>
xxxxxxxxxxxxxxxx
</body>
</html>
"@
}
# create confirmation message
$ButtonType = [System.Windows.MessageBoxButton]::YesNo
$MessageIcon = [System.Windows.MessageBoxImage]::Warning
$MessageTitle = "Corporate Building Access Request"
$MessageBody = "The information you have entered is show below:`n`n`nTicket Number: $Ticket`n`nUser's Email Address: $UserID`n`nAccess To: $($TextTotal.ToString())`n`n`nIf you would like to send the email, click Yes.`nOtherwise, click No."
$Result = [System.Windows.MessageBox]::Show($MessageBody,$MessageTitle,$ButtonType,$MessageIcon)
Upvotes: 1