Coder Social home page Coder Social logo

Comments (10)

mmashwani avatar mmashwani commented on July 29, 2024

The -CustomMessage parameter would have to be added to the config XML file so that you could translate the message into different languages and have the toolkit display the appropriate language based on the user's regional language settings.

I don't have time at the moment for new feature development, so if you want to take a crack at this, then I'll consider it for addition to the toolkit. We're also putting a hold on new feature development untill we have a stable release without new bug reports for a while so that we can start work on the v4 release.

from psappdeploytoolkit.

dersonc avatar dersonc commented on July 29, 2024

I'll try to come up with the necessary code for this.

from psappdeploytoolkit.

dersonc avatar dersonc commented on July 29, 2024

I implemented these on the Main code of the toolkit and the XML file. Here are the changes that I had to make:

Added the following parameters to the XML file:

<DeferPrompt_CountdownMessage>The {0} will automatically continue in:</DeferPrompt_CountdownMessage>
<Prompt_CustomMessage>This is a custom message to display at the Welcome Screen window.</Prompt_CustomMessage>

Added the following to the variable declaration of the Main toolkit:

[string]$configDeferPromptCountdownMessage = $xmlUIMessages.DeferPrompt_CountdownMessage
[string]$configPromptCustomMessage = $xmlUIMessages.Prompt_CustomMessage

Added the following parameters to the Function Show-InstallationWelcome:

## Specify a countdown to display before automatically proceeding with the installation when a deferal is enabled
[Parameter(Mandatory=$false)]
[ValidateNotNullorEmpty()]
[int32]$ForceCountdown = 0,
## Specify whether to display a custom message specified on the XML file
[Parameter(Mandatory=$false)]
[switch]$CustomText = $false,

Replaced part of the code in the Function Show-InstallationWelcome with the following:

## Prompt the user to close running applications and optionally defer if enabled
        If (-not ($deployModeSilent) -and (-not ($silent))) {
            If ($forceCloseAppsCountdown -gt 0) {
                #  Keep the same variable for countdown to simplify the code:
                $closeAppsCountdown = $forceCloseAppsCountdown
                #  Change this variable to a boolean now to switch the countdown on even with deferral
                [boolean]$forceCloseAppsCountdown = $true
            }
            ElseIf ($forceCountdown -gt 0){
                #  Keep the same variable for countdown to simplify the code:
                $closeAppsCountdown = $forceCountdown
                #  Change this variable to a boolean now to switch the countdown on
                [boolean]$forceCountdown = $true
            }
            Set-Variable -Name 'closeAppsCountdownGlobal' -Value $closeAppsCountdown -Scope 'Script'

            While ((Get-RunningProcesses -ProcessObjects $processObjects -OutVariable 'runningProcesses') -or (($promptResult -ne 'Defer') -and ($promptResult -ne 'Close'))) {
                [string]$runningProcessDescriptions = ($runningProcesses | Where-Object { $_.ProcessDescription } | Select-Object -ExpandProperty 'ProcessDescription' | Select-Object -Unique | Sort-Object) -join ','
                #  Check if we need to prompt the user to defer, to defer and close apps, or not to prompt them at all
                If ($allowDefer) {
                    #  If there is deferral and closing apps is allowed but there are no apps to be closed, break the while loop
                    If ($AllowDeferCloseApps -and (-not $runningProcessDescriptions)) {
                        Break
                    }
                    #  Otherwise, as long as the user has not selected to close the apps or the processes are still running and the user has not selected to continue, prompt user to close running processes with deferral
                    ElseIf (($promptResult -ne 'Close') -or (($runningProcessDescriptions) -and ($promptResult -ne 'Continue'))) {
                        [string]$promptResult = Show-WelcomePrompt -ProcessDescriptions $runningProcessDescriptions -CloseAppsCountdown $closeAppsCountdownGlobal -ForceCloseAppsCountdown $forceCloseAppsCountdown -ForceCountdown $forceCountdown -PersistPrompt $PersistPrompt -AllowDefer -DeferTimes $deferTimes -DeferDeadline $deferDeadlineUniversal -MinimizeWindows $MinimizeWindows -CustomText $CustomText -TopMost $TopMost
                    }
                }
                #  If there is no deferral and processes are running, prompt the user to close running processes with no deferral option
                ElseIf (($runningProcessDescriptions) -or ($forceCountdown)) {
                    [string]$promptResult = Show-WelcomePrompt -ProcessDescriptions $runningProcessDescriptions -CloseAppsCountdown $closeAppsCountdownGlobal -ForceCloseAppsCountdown $forceCloseAppsCountdown -ForceCountdown $forceCountdown -PersistPrompt $PersistPrompt -MinimizeWindows $minimizeWindows -CustomText $CustomText -TopMost $TopMost
                }
                #  If there is no deferral and no processes running, break the while loop

Added the following parameters to the Function Show-WelcomePrompt:

[Parameter(Mandatory=$false)]
[ValidateNotNullorEmpty()]
[boolean]$ForceCountdown,
[Parameter(Mandatory=$false)]
[boolean]$CustomText = $false,

Replaced part of the code in the Function Show-WelcomePrompt:

## If 'force close apps countdown' was specified, enable that feature.
        If ($forceCloseAppsCountdown -eq $true) {
            Write-Log -Message "Close applications countdown has [$closeAppsCountdown] seconds remaining." -Source ${CmdletName}
            $showCountdown = $true
        }
        ## If 'force countdown' was specified, enable that feature.
        If ($forceCountdown -eq $true) {
            Write-Log -Message "Countdown has [$closeAppsCountdown] seconds remaining." -Source ${CmdletName}
            $showCountdown = $true
        }

        [string[]]$processDescriptions = $processDescriptions -split ','
        [Windows.Forms.Application]::EnableVisualStyles()

        $formWelcome = New-Object -TypeName 'System.Windows.Forms.Form'
        $pictureBanner = New-Object -TypeName 'System.Windows.Forms.PictureBox'
        $labelAppName = New-Object -TypeName 'System.Windows.Forms.Label'
        $labelCountdown = New-Object -TypeName 'System.Windows.Forms.Label'
        $labelDefer = New-Object -TypeName 'System.Windows.Forms.Label'
        $listBoxCloseApps = New-Object -TypeName 'System.Windows.Forms.ListBox'
        $buttonContinue = New-Object -TypeName 'System.Windows.Forms.Button'
        $buttonDefer = New-Object -TypeName 'System.Windows.Forms.Button'
        $buttonCloseApps = New-Object -TypeName 'System.Windows.Forms.Button'
        $buttonAbort = New-Object -TypeName 'System.Windows.Forms.Button'
        $formWelcomeWindowState = New-Object -TypeName 'System.Windows.Forms.FormWindowState'
        $flowLayoutPanel = New-Object -TypeName 'System.Windows.Forms.FlowLayoutPanel'
        $panelButtons = New-Object -TypeName 'System.Windows.Forms.Panel'
        $toolTip = New-Object -TypeName 'System.Windows.Forms.ToolTip'

        ## Remove all event handlers from the controls
        [scriptblock]$Form_Cleanup_FormClosed = {
            Try {
                $labelAppName.remove_Click($handler_labelAppName_Click)
                $labelDefer.remove_Click($handler_labelDefer_Click)
                $buttonCloseApps.remove_Click($buttonCloseApps_OnClick)
                $buttonContinue.remove_Click($buttonContinue_OnClick)
                $buttonDefer.remove_Click($buttonDefer_OnClick)
                $buttonAbort.remove_Click($buttonAbort_OnClick)
                $script:welcomeTimer.remove_Tick($timer_Tick)
                $timerPersist.remove_Tick($timerPersist_Tick)
                $formWelcome.remove_Load($Form_StateCorrection_Load)
                $formWelcome.remove_FormClosed($Form_Cleanup_FormClosed)
            }
            Catch { }
        }

        [scriptblock]$Form_StateCorrection_Load = {
            ## Correct the initial state of the form to prevent the .NET maximized form issue
            $formWelcome.WindowState = 'Normal'
            $formWelcome.AutoSize = $true
            $formWelcome.TopMost = $TopMost
            $formWelcome.BringToFront()
            #  Get the start position of the form so we can return the form to this position if PersistPrompt is enabled
            Set-Variable -Name 'formWelcomeStartPosition' -Value $formWelcome.Location -Scope 'Script'

            ## Initialize the countdown timer
            [datetime]$currentTime = Get-Date
            [datetime]$countdownTime = $startTime.AddSeconds($CloseAppsCountdown)
            $script:welcomeTimer.Start()

            ## Set up the form
            [timespan]$remainingTime = $countdownTime.Subtract($currentTime)
            [string]$labelCountdownSeconds = [string]::Format('{0}:{1:d2}:{2:d2}', $remainingTime.Hours, $remainingTime.Minutes, $remainingTime.Seconds)
            If ($forceCountdown -eq $true) {
                If ($deploymentType -ieq 'Install') { $labelCountdown.Text = ($configDeferPromptCountdownMessage -f $configDeploymentTypeInstall) + "`n$labelCountdownSeconds" }
                Else { $labelCountdown.Text = ($configDeferPromptCountdownMessage -f $configDeploymentTypeUninstall) + "`n$labelCountdownSeconds" } 
            }
            Else { $labelCountdown.Text = "$configClosePromptCountdownMessage`n$labelCountdownSeconds" }
        }

        ## Add the timer if it doesn't already exist - this avoids the timer being reset if the continue button is clicked
        If (-not ($script:welcomeTimer)) {
            $script:welcomeTimer = New-Object -TypeName 'System.Windows.Forms.Timer'
        }

        If ($showCountdown) {
            [scriptblock]$timer_Tick = {
                ## Get the time information
                [datetime]$currentTime = Get-Date
                [datetime]$countdownTime = $startTime.AddSeconds($CloseAppsCountdown)
                [timespan]$remainingTime = $countdownTime.Subtract($currentTime)
                Set-Variable -Name 'closeAppsCountdownGlobal' -Value $remainingTime.TotalSeconds -Scope 'Script'

                ## If the countdown is complete, close the application(s) or continue
                If ($countdownTime -lt $currentTime) {
                    If ($forceCountdown -eq $true) {
                        Write-Log -Message 'Countdown timer has elapsed. Force continue.' -Source ${CmdletName}
                        $buttonContinue.PerformClick()
                    }
                    Else {
                        Write-Log -Message 'Close application(s) countdown timer has elapsed. Force closing application(s).' -Source ${CmdletName}
                        $buttonCloseApps.PerformClick()
                    }
                }
                Else {
                    #  Update the form
                    [string]$labelCountdownSeconds = [string]::Format('{0}:{1:d2}:{2:d2}', $remainingTime.Hours, $remainingTime.Minutes, $remainingTime.Seconds)
                    If ($forceCountdown -eq $true) {
                        If ($deploymentType -ieq 'Install') { $labelCountdown.Text = ($configDeferPromptCountdownMessage -f $configDeploymentTypeInstall) + "`n$labelCountdownSeconds" }
                        Else { $labelCountdown.Text = ($configDeferPromptCountdownMessage -f $configDeploymentTypeUninstall) + "`n$labelCountdownSeconds" }
                    }
                    Else { $labelCountdown.Text = "$configClosePromptCountdownMessage`n$labelCountdownSeconds" }
                    [Windows.Forms.Application]::DoEvents()
                }
            }
        }
        Else {
            $script:welcomeTimer.Interval = ($configInstallationUITimeout * 1000)
            [scriptblock]$timer_Tick = { $buttonAbort.PerformClick() }
        }

        $script:welcomeTimer.add_Tick($timer_Tick)

        ## Persistence Timer
        If ($persistWindow) {
            $timerPersist = New-Object -TypeName 'System.Windows.Forms.Timer'
            $timerPersist.Interval = ($configInstallationPersistInterval * 1000)
            [scriptblock]$timerPersist_Tick = { Refresh-InstallationWelcome }
            $timerPersist.add_Tick($timerPersist_Tick)
            $timerPersist.Start()
        }

        ## Form
        $formWelcome.Controls.Add($pictureBanner)
        $formWelcome.Controls.Add($buttonAbort)

        ##----------------------------------------------
        ## Create padding object
        $paddingNone = New-Object -TypeName 'System.Windows.Forms.Padding'
        $paddingNone.Top = 0
        $paddingNone.Bottom = 0
        $paddingNone.Left = 0
        $paddingNone.Right = 0

        ## Generic Label properties
        $labelPadding = '20,0,20,0'

        ## Generic Button properties
        $buttonWidth = 110
        $buttonHeight = 23
        $buttonPadding = 50
        $buttonSize = New-Object -TypeName 'System.Drawing.Size'
        $buttonSize.Width = $buttonWidth
        $buttonSize.Height = $buttonHeight
        $buttonPadding = New-Object -TypeName 'System.Windows.Forms.Padding'
        $buttonPadding.Top = 0
        $buttonPadding.Bottom = 5
        $buttonPadding.Left = 50
        $buttonPadding.Right = 0

        ## Picture Banner
        $pictureBanner.DataBindings.DefaultDataSourceUpdateMode = 0
        $pictureBanner.ImageLocation = $appDeployLogoBanner
        $System_Drawing_Point = New-Object -TypeName 'System.Drawing.Point'
        $System_Drawing_Point.X = 0
        $System_Drawing_Point.Y = 0
        $pictureBanner.Location = $System_Drawing_Point
        $pictureBanner.Name = 'pictureBanner'
        $System_Drawing_Size = New-Object -TypeName 'System.Drawing.Size'
        $System_Drawing_Size.Height = 50
        $System_Drawing_Size.Width = 450
        $pictureBanner.Size = $System_Drawing_Size
        $pictureBanner.SizeMode = 'CenterImage'
        $pictureBanner.Margin = $paddingNone
        $pictureBanner.TabIndex = 0
        $pictureBanner.TabStop = $false

        ## Label App Name
        $labelAppName.DataBindings.DefaultDataSourceUpdateMode = 0
        $labelAppName.Name = 'labelAppName'
        $System_Drawing_Size = New-Object -TypeName 'System.Drawing.Size'
        If (-not $showCloseApps) {
            $System_Drawing_Size.Height = 40
        }
        Else {
            $System_Drawing_Size.Height = 65
        }
        $System_Drawing_Size.Width = 450
        $labelAppName.Size = $System_Drawing_Size
        $System_Drawing_Size.Height = 0
        $labelAppName.MaximumSize = $System_Drawing_Size
        $labelAppName.Margin = '0,15,0,15'
        $labelAppName.Padding = $labelPadding
        $labelAppName.TabIndex = 1

        ## Initial form layout: Close Applications / Allow Deferral
        If ($showCloseApps) {
            $labelAppNameText = $configClosePromptMessage
        }
        ElseIf (($showDefer) -or ($forceCountdown)) {
            $labelAppNameText = "$configDeferPromptWelcomeMessage `n$installTitle"
        }
        If ($CustomText) {
            $labelAppNameText = "$labelAppNameText `n`n$configPromptCustomMessage"
        }
        $labelAppName.Text = $labelAppNameText
        $labelAppName.TextAlign = 'TopCenter'
        $labelAppName.Anchor = 'Top'
        $labelAppName.AutoSize = $true
        $labelAppName.add_Click($handler_labelAppName_Click)

        ## Listbox Close Applications
        $listBoxCloseApps.DataBindings.DefaultDataSourceUpdateMode = 0
        $listBoxCloseApps.FormattingEnabled = $true
        $listBoxCloseApps.HorizontalScrollbar = $true
        $listBoxCloseApps.Name = 'listBoxCloseApps'
        $System_Drawing_Size = New-Object -TypeName 'System.Drawing.Size'
        $System_Drawing_Size.Height = 100
        $System_Drawing_Size.Width = 300
        $listBoxCloseApps.Size = $System_Drawing_Size
        $listBoxCloseApps.Margin = '75,0,0,0'
        $listBoxCloseApps.TabIndex = 3
        $ProcessDescriptions | ForEach-Object { $listboxCloseApps.Items.Add($_) | Out-Null }

        ## Label Defer
        $labelDefer.DataBindings.DefaultDataSourceUpdateMode = 0
        $labelDefer.Name = 'labelDefer'
        $System_Drawing_Size = New-Object -TypeName 'System.Drawing.Size'
        $System_Drawing_Size.Height = 90
        $System_Drawing_Size.Width = 450
        $labelDefer.Size = $System_Drawing_Size
        $System_Drawing_Size.Height = 0
        $labelDefer.MaximumSize = $System_Drawing_Size
        $labelDefer.Margin = $paddingNone
        $labelDefer.Padding = $labelPadding
        $labelDefer.TabIndex = 4
        $deferralText = "$configDeferPromptExpiryMessage`n"

        If ($deferTimes -ge 0) {
            $deferralText = "$deferralText `n$configDeferPromptRemainingDeferrals $([int32]$deferTimes + 1)"
        }
        If ($deferDeadline) {
            $deferralText = "$deferralText `n$configDeferPromptDeadline $deferDeadline"
        }
        If (($deferTimes -lt 0) -and (-not $DeferDeadline)) {
            $deferralText = "$deferralText `n$configDeferPromptNoDeadline"
        }
        $deferralText = "$deferralText `n`n$configDeferPromptWarningMessage"
        $labelDefer.Text = $deferralText
        $labelDefer.TextAlign = 'MiddleCenter'
        $labelDefer.AutoSize = $true
        $labelDefer.add_Click($handler_labelDefer_Click)

        ## Label Countdown
        $labelCountdown.DataBindings.DefaultDataSourceUpdateMode = 0
        $labelCountdown.Name = 'labelCountdown'
        $System_Drawing_Size = New-Object -TypeName 'System.Drawing.Size'
        $System_Drawing_Size.Height = 40
        $System_Drawing_Size.Width = 450
        $labelCountdown.Size = $System_Drawing_Size
        $System_Drawing_Size.Height = 0
        $labelCountdown.MaximumSize = $System_Drawing_Size
        $labelCountdown.Margin = $paddingNone
        $labelCountdown.Padding = $labelPadding
        $labelCountdown.TabIndex = 4
        $labelCountdown.Font = 'Microsoft Sans Serif, 9pt, style=Bold'
        $labelCountdown.Text = '00:00:00'
        $labelCountdown.TextAlign = 'MiddleCenter'
        $labelCountdown.AutoSize = $true
        $labelCountdown.add_Click($handler_labelDefer_Click)

        ## Panel Flow Layout
        $System_Drawing_Point = New-Object -TypeName 'System.Drawing.Point'
        $System_Drawing_Point.X = 0
        $System_Drawing_Point.Y = 50
        $flowLayoutPanel.Location = $System_Drawing_Point
        $flowLayoutPanel.AutoSize = $true
        $flowLayoutPanel.Anchor = 'Top'
        $flowLayoutPanel.FlowDirection = 'TopDown'
        $flowLayoutPanel.WrapContents = $true
        $flowLayoutPanel.Controls.Add($labelAppName)
        If ($showCloseApps) { $flowLayoutPanel.Controls.Add($listBoxCloseApps) }
        If ($showDefer) {
            $flowLayoutPanel.Controls.Add($labelDefer)
        }
        If ($showCountdown) {
            $flowLayoutPanel.Controls.Add($labelCountdown)
        }

        ## Button Close For Me
        $buttonCloseApps.DataBindings.DefaultDataSourceUpdateMode = 0
        $buttonCloseApps.Location = '15,0'
        $buttonCloseApps.Name = 'buttonCloseApps'
        $buttonCloseApps.Size = $buttonSize
        $buttonCloseApps.TabIndex = 5
        $buttonCloseApps.Text = $configClosePromptButtonClose
        $buttonCloseApps.DialogResult = 'Yes'
        $buttonCloseApps.AutoSize = $true
        $buttonCloseApps.UseVisualStyleBackColor = $true
        $buttonCloseApps.add_Click($buttonCloseApps_OnClick)

        ## Button Defer
        $buttonDefer.DataBindings.DefaultDataSourceUpdateMode = 0
        If (-not $showCloseApps) {
            $buttonDefer.Location = '15,0'
        }
        Else {
            $buttonDefer.Location = '170,0'
        }
        $buttonDefer.Name = 'buttonDefer'
        $buttonDefer.Size = $buttonSize
        $buttonDefer.TabIndex = 6
        $buttonDefer.Text = $configClosePromptButtonDefer
        $buttonDefer.DialogResult = 'No'
        $buttonDefer.AutoSize = $true
        $buttonDefer.UseVisualStyleBackColor = $true
        $buttonDefer.add_Click($buttonDefer_OnClick)

        ## Button Continue
        $buttonContinue.DataBindings.DefaultDataSourceUpdateMode = 0
        $buttonContinue.Location = '325,0'
        $buttonContinue.Name = 'buttonContinue'
        $buttonContinue.Size = $buttonSize
        $buttonContinue.TabIndex = 7
        $buttonContinue.Text = $configClosePromptButtonContinue
        $buttonContinue.DialogResult = 'OK'
        $buttonContinue.AutoSize = $true
        $buttonContinue.UseVisualStyleBackColor = $true
        $buttonContinue.add_Click($buttonContinue_OnClick)
        If ($showCloseApps) {
            #  Add tooltip to Continue button
            $toolTip.BackColor = [Drawing.Color]::LightGoldenrodYellow
            $toolTip.IsBalloon = $false
            $toolTip.InitialDelay = 100
            $toolTip.ReshowDelay = 100
            $toolTip.SetToolTip($buttonContinue, $configClosePromptButtonContinueTooltip)
        }

from psappdeploytoolkit.

dersonc avatar dersonc commented on July 29, 2024

In my tests using the code above everything worked as expected. I used the following command line for testing:

Show-InstallationWelcome -AllowDefer -ForceCountdown 3600 -DeferTimes 2 -DeferDays 7 -PersistPrompt -TopMost 0 -CustomText

from psappdeploytoolkit.

dersonc avatar dersonc commented on July 29, 2024

This is how this code looks with deferrals left:
deferralsleft_countdown_custommessage

This is how this code looks when there are no deferrals left:
nodeferralsleft_countdown_custommessage

from psappdeploytoolkit.

dersonc avatar dersonc commented on July 29, 2024

@mmashwani I wonder if you are considering the inclusion of this feature for the next release?

from psappdeploytoolkit.

mmashwani avatar mmashwani commented on July 29, 2024

Yes, I will add this to the next release.

from psappdeploytoolkit.

dersonc avatar dersonc commented on July 29, 2024

@mmashwani Thank you so much!

from psappdeploytoolkit.

mmashwani avatar mmashwani commented on July 29, 2024

I have included this in the latest beta. Please test and let me know if it's working as expected. The text for one of the new XML config options still needs to be translated into different languages before we release a final version.

from psappdeploytoolkit.

dersonc avatar dersonc commented on July 29, 2024

I tested a few scenarios and everything is working fine, thanks a lot!

I can help with the Brazilian Portuguese translation:

<WelcomePrompt_CountdownMessage>A {0} vai continuar automaticamente em:</WelcomePrompt_CountdownMessage>

My team suggested improvements to the languages of the two texts below, it might also be valuable for the Toolkit:

<DeferPrompt_ExpiryMessage>You can choose to defer the installation until the deferral deadline:</DeferPrompt_ExpiryMessage>
<DeferPrompt_WarningMessage>Once the deadline has passed, you will no longer have the option to defer.</DeferPrompt_WarningMessage>

Another suggestion: wouldn't be better to always use {0} when we have the install or uninstall text on the XML file and replace it with the appropriate information during runtime just like the code that was included?

from psappdeploytoolkit.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.