0

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 { }
 }
 }

enter image description here

enter image description here

enter image description here

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
1
  • 1
    Well, every time that A and B are checked, then A will be checked. So your current logic will see both of those if statements as true. You need to rework your logic. Commented Apr 2, 2018 at 14:27

1 Answer 1

1

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)
Sign up to request clarification or add additional context in comments.

4 Comments

Kirill, I updated the code and included the new "full" code. Something is amiss, because now it does not do anything. In powershell ISE, I can see that it runs successfully, but I get no prompt to select a location or the confirmation message. When I uncomment my 2 initial questions about a ticket number and email address, they do show.
I have posted only a part of your code. The part where I made some changes. Try to fit it with your original code.
Fixed it. Put a } in the wrong location...........Anyway, I updated the OP with the error it now gives. It DOES work, but throws this error as well....
Also, the reason why I initially had all of the different IF statements is because of the various admins that would receive the email. If location A and/or B need access, it is one admin. But building C is a different admin, and D is yet another admin. So my goal was to make sure that each admin is emailed for their specific location. If easier, it could be one email with multiple admins included. But either way, I would have to include the specified admin for the location.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.