This script will keep the Windows Screen Saver from coming on. The script runs in the System Tray using NotifyIcon, while being controlled by a Timer object, as it toggles the NumLock key.

Toggling the NumLock (or CapsLock) key provide enough interaction to the system to prevent the Screen Saver from enabling. I have tested under Windows XP, 7 and 8 Screen Savers. Also tested on Domain Member workstations running Windows 2008 R2 Functional Level AD Group Policy enabled Screen Savers.

Sending regular keystrokes or jiggling the mouse a few pixels no longer works to prevent the Screen Saver from enabling.

Here is the Script running in the System Tray, showing the MouseOver –

NoSSaver

First I add the .Net Namespaces, hide the Host Console and setup the Main Form. It has almost no properties and gets hidden.

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

# Hide Host Console
Add-Type -Name Window -Namespace Console -MemberDefinition '
    [DllImport("Kernel32.dll")]
    public static extern IntPtr GetConsoleWindow();
    [DllImport("user32.dll")]
    public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
'
function Hide-Console {
    $consolePtr = [Console.Window]::GetConsoleWindow()
    [void][Console.Window]::ShowWindow($consolePtr, 0)
}
hide-console

# Main Form Object
$mainForm = New-Object System.Windows.Forms.form
# Hide Main Form Window
$mainForm.ShowInTaskbar = $false
$mainForm.WindowState   = "minimized"

Next I added a Timer object. It will count down a predefined time and then process an event, calling the sendKeys function. The Timer Interval Delay is in Milliseconds i.e. 60k = 1 minute. The add_Tick set the event, calling the Function. The Timer control is then started.

# Timer Object
$Timer          = New-Object System.Windows.Forms.Timer
$Timer.Interval = 30000 
$Timer.add_Tick({sendKeys}) 
$Timer.start()

I then define the “About” information form. I define the Form, add a Label and a ListBox with Items containing the script description. Lastly an “OK” Button to Close the Form.

# 'About' Window Setup
# About Form Object
$aboutForm      = New-Object system.Windows.Forms.Form
$aboutForm.Size = New-Object System.Drawing.Size(250,220) 
$aboutForm.Font = New-Object System.Drawing.Font("Calibri",12,[System.Drawing.FontStyle]::Regular)
$aboutForm.Icon = $Icon
$aboutForm.Text = " About NoSSaver"
$aboutForm.StartPosition = "CenterScreen"
# About Label Object
$aboutLabel          = New-Object System.Windows.Forms.Label
$aboutLabel.font     = new-object system.drawing.font("Calibri",14,[system.drawing.fontstyle]::bold)
$aboutLabel.Location = New-Object System.Drawing.Size(10,10) 
$aboutLabel.Size     = New-Object System.Drawing.Size(220,20) 
$aboutLabel.Text     = "NoSSaver Script"
# Add About Label to Form
$aboutForm.Controls.Add($aboutLabel) 
# About ListBox Object
$aboutListBox          = New-Object System.Windows.Forms.ListBox 
$aboutListBox.Font     = new-object system.drawing.font("Calibri",11,[system.drawing.fontstyle]::regular)
$aboutListBox.Location = New-Object System.Drawing.Size(16,40) 
$aboutListBox.Size     = New-Object System.Drawing.Size(200,20) 
$aboutListBox.Height   = 100
# Add Info to About ListBox
[void] $aboutListBox.Items.Add("     NoSSaver.ps1")
[void] $aboutListBox.Items.Add("  Prevents the Windows")
[void] $aboutListBox.Items.Add("Screensaver from starting ")
[void] $aboutListBox.Items.Add("  by Wayne Lindimore")
[void] $aboutListBox.Items.Add("adminscache.wordpress.com")
# Add About ListBox to Form
$aboutForm.Controls.Add($aboutListBox) 
# About OK Button Object
$OKButton          = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(70,150)
$OKButton.Size     = New-Object System.Drawing.Size(75,23)
$OKButton.Text     = "OK"
$OKButton.Add_Click({$aboutForm.Close()})
# Add About OK Button to Form
$aboutForm.Controls.Add($OKButton)

NoSSaverContext

NoSSaverAbout1

Next is the NotifyIcon object. First I decode the embedded icon. I encoded the icon with my PowerShell Base64 Encoding of Images script. After encoding the image into a text file with Image2Base64, I insert the text block into the script using a Here-String.

# NotifyIcon Setup
# Decode and Set Icon
[string]$IconB64=@"
AAABAAQAGBgAAAEAIACICQAARgAAACAgAAABACAAqBAAAM4JAAAQEAAAAQAgAGgEAAB2GgAAFhYAAAEA
IAAQCAAA3h4AACgAAAAYAAAAMAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
.
.
.
i/aIjYv2ipGPlAAA//8AAP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///AA+ABgAMAABADAAAwA8AAcAP4A
PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAA///wA
"@

To decode the icon and make it available for use, the string is converted into a MemoryStream. The stream has a backing store of memory instead disk or a network connection, which we’ll need as we have no file to use. A bitmap image is made from the stream. We collect the icons handle using the GetHicon() method from the bitmap image. The icon is created using the FromHandle method. We now have an icon image available for use have been read from the source script file and decoded and created in memory instead of read from a disk file.

$Iconstream = [System.IO.MemoryStream][System.Convert]::FromBase64String($IconB64)
$Iconbmp    = [System.Drawing.Bitmap][System.Drawing.Image]::FromStream($Iconstream)
$Iconhandle = $Iconbmp.GetHicon()
$Icon       = [System.Drawing.Icon]::FromHandle($Iconhandle)

I then define the NotifyIcon and make it visible. Within the NotifyIcon I define a ContextMenu which is visible on a right-click of the icon. I add a MenuItem to it for the Exit option. Lastly I define a click event action to clean up and exit the script.

# NotifyIcon Objects
$NotifyIcon  = New-Object System.Windows.Forms.NotifyIcon
$ContextMenu = New-Object System.Windows.Forms.ContextMenu
$NotifyIcon.ContextMenu = $ContextMenu
$NotifyIcon.Icon = $Icon
$NotifyIcon.Visible = $True
$NotifyIcon.Text = "NoSSaver"
$MenuItem1 = New-Object System.Windows.Forms.MenuItem -ArgumentList "About..."
$MenuItem2 = New-Object System.Windows.Forms.MenuItem -ArgumentList "Exit"
# Add Context MenuItems
[void] $contextMenu.MenuItems.Add($MenuItem1)
[void] $contextMenu.MenuItems.Add($MenuItem2)
# Add 'About' MenuItem
$MenuItem1.add_Click({
    [void] $aboutForm.ShowDialog() 
})
# Add Exit MenuItem
$MenuItem2.add_Click({
	$Timer.stop()
	$NotifyIcon.Visible = $False
	$mainForm.close()
})

The Timer event calls the sendKeys Function which toggles the NumLock key on and off.

Function sendKeys() {           
    $shell = New-Object -com "Wscript.Shell"
    $shell.sendkeys(“{NumLock}{NumLock}”)
    $shell.Dispose
}

If started from a Command file the script will start in the System Tray with the PowerShell host box hidden.

powershell.exe -windowstyle hidden -nologo -command .\NoSleep.ps1

Download the complete script here – NoSSaver.ps1

Advertisements