2

I have a PowerShell script with a function to pull LAPS information when someone enters a computer name. What I'd like is to clear the output after 60 seconds so someone doesn't accidentally leave a password on their screen.

Seems as though no matter where the sleep is in the function (or even after) the script is paused for the 60 seconds, then displays the information and it never clears.

The part of the script that waits and clears:

Start-Sleep -s 60
$WPFOutputbox.Clear()

(look for my #TRIED HERE comments below)

function GETLAPS {
    Param ($computername = $WPFComputer.Text)

    try {
        $LAPSComputer = Get-AdmPwdPassword -ComputerName $computername |
                        Select-Object -ExpandProperty computername
        $LAPSDistinguished = Get-AdmPwdPassword -ComputerName $computername |
                             Select-Object -ExpandProperty distinguishedname
        $LAPSPassword = Get-AdmPwdPassword -ComputerName $computername |
                        Select-Object -ExpandProperty Password
        $LAPSExpire = Get-AdmPwdPassword -ComputerName $computername |
                      Select-Object -ExpandProperty Expirationtimestamp
    } catch {
        $ErrorMessage = $_.Exception.Message
    }
    if ($ErrorMessage -eq $null) {
        $WPFOutputBox.Foreground = "Blue"
        $WPFOutputBox.Text = "Local Admin Information for: $LAPSComputer

    Current: $LAPSPassword

    Exipiration: $LAPSExpire

    SCREEN WILL CLEAR AFTER 60 SECONDS"
        #TRIED HERE
    } else {
        $WPFOutputBox.Foreground = "Red"
        $WPFOutputBox.Text = $ErrorMessage
    }
    #TRIED HERE
}

Instead the script will wait 60 seconds to show information, and never clear the screen.

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
Derryn
  • 31
  • 4
  • $WpFOutputBox.Text = "" ? – Sage Pourpre Jan 03 '19 at 19:18
  • It's a WPF window that shows the output in a more Helpdesk friendly manner. It runs off powershell though. – Derryn Jan 03 '19 at 19:22
  • Instead of Clear(), try setting the text to an empty string. $WpFOutputBox.Text = "" – Sage Pourpre Jan 03 '19 at 20:58
  • It's not the clear that's the major issue, it's the waiting 60 seconds before displaying the information. I can clear the screen with other commands just fine. – Derryn Jan 03 '19 at 21:05
  • I'd say, that you'd need to define a piece of C#/.Net code, and then use something like [System.Threading.Tasks.Task]::Run(delegate) to start it in background. Or make your own auto-closing dialog window in C#, use Add-Type to load this DLL. Or, run the whole output task a a job at the local host. – Max Jan 03 '19 at 21:35
  • I would suggest an other runspace that handles the sleep and invokes a dispatcher to clear the Textbox. But that is a lot of work for a little effect if the runspace isn't used for other things. On the other hand a second runspace is always handy. – T-Me Jan 04 '19 at 09:51

2 Answers2

2

Unless you create a separate thread, I would strongly advise against using the Start-Sleep cmdlet in Windows Forms or Windows Presentation Foundation as it will obviously stall the User Interface.

Instead, I would recommend to use a (Windows.Forms.Timer) event.

For this, I wrote a small function to delay a command:

Delay-Command

Function Delay-Command([ScriptBlock]$Command, [Int]$Interval = 100, [String]$Id = "$Command") {
    If ($Timers -isnot "HashTable") {$Global:Timers = @{}}
    $Timer = $Timers[$Id]
    If (!$Timer) {
        $Timer = New-Object Windows.Forms.Timer
        $Timer.Add_Tick({$This.Stop()})
        $Timer.Add_Tick($Command)
        $Global:Timers[$Id] = $Timer
    }
    $Timer.Stop()
    $Timer.Interval = $Interval
    If ($Interval -gt 0) {$Timer.Start()}
}; Set-Alias Delay Delay-Command

Example

Delay {$WpFOutputBox.Text = ''} 60000

Parameters

-Command
The command to be delayed.

-Interval
The time to wait before executing the command.
If -Interval is set to 0 or less, the command (with the related Id) will be reset.
The default is 100 (a minor time lapse to give other events the possibility to kick off).

-Id
The Id of the delayed command. Multiple commands which different Id's can be executed simultaneously. If the same Id is used for a command that is not yet executed, the interval timer will be reset (or canceled when set to 0).
The default Id in the command string.

mklement0
  • 382,024
  • 64
  • 607
  • 775
iRon
  • 20,463
  • 10
  • 53
  • 79
-1

Call the function, sleep 60 seconds, then clear it. Do not put your sleep inside the function, put it where you call the function. Something like:

$WPFGetLAPSButton.add_click({
    GETLAPS
    # If no error, wait 60 seconds and clear the text box
    If($WPFOutputBox.Foreground -eq "Blue"){
        Start-Sleep 60
        $WPFOutputBox.Text = ''
    }
})

Pretty sure that'll do what you're looking for.

TheMadTechnician
  • 34,906
  • 3
  • 42
  • 56