Example Code Documentation

Mike Wilcock - WebHelp
Example Code Documentation
View with Navigation Tools

The following documentation has been created for the example code contained at www.mikewilcock.com. With the exception of the PowerShell Examples, all of the code presented in this section of the website is written using PHP, HTML and JavaScript and runs on a dedicated and fully managed Intel Xeon web server running CentOS Linux; The database in use is MariaDB version 10.

All example documentation is available in context sensitive HTML Web Help format, a downloadable PDF booklet and Microsoft Compiled HTML Help (.chm) format.

The example code and applications are presented as a guide to demonstrate the kind of projects and work that I have been involved in over the last few years and to demonstrate the functionality of the Upsilon web application framework that I have developed to enable rapid development of cloud based database applications.

© Mike Wilcock, 2025.


Application Framework - Introduction

Application Framework - Introduction
Example Code > Application Framework - Introduction

This section of this documentation is dedicated to the web-based application framework that I have developed over the last few years to facilitate the rapid design and creation of database driven web-based applications.

The application framework has been used to create Upsilon-ERP, the cloud-based ERP solution, and has been written using a combination of PHP, JavaScript and HTML with a back end SQL database of MariaDB.

The framework includes templates for grid and form applications, reporting including an integrated report designer, user security, a menu system with multi document interface and a fully indexed and searchable context sensitive help system.

The framework demo presented here pulls together many of the example applications published to this website displaying code from the Database Applications, Tools & Utilities and Documentation sections of my Example Code.

See Also

Database Applications

Northwind Customers Application
Northwind Customers Report
Northwind Customers Report (Detailed)
Northwind Orders Application
Northwind Orders Report


Database Applications - Introduction

Database Applications - Introduction
Example Code > Database Applications - Introduction

The following section of this documentation contains several example web-based database applications that I have created over the last few years.

I have spent the majority of my over thirty-year career in IT within the software industry, specifically involved in the development of database applications. This started in the early 1990’s developing Dbase III+ applications and then moving on to compiling them using the CA Clipper compiler for DOS. The association with Xbase languages continued throughout the early 2000’s moving from CA Clipper to Alaska Software’s Xbase++ compiler.

These days all of my database programming is web-based using PHP and MariaDB. All examples use the Microsoft Northwind database as sample data and are written in and executed under PHP 7.3.

The backend database in use is MariaDB version 10.


Northwind Customers Application

Northwind Customers Application
Example Code > Database Applications > Northwind Customers Application

The Northwind Customers Application is a simple database application consisting of a grid application designed to display and search tabular data and a form application designed to create, read, update and delete record data.

Application Features

  • Quick Search
  • Advanced Search
  • Export data to multiple formats
  • Form validation
  • Create, Read, Update and Delete

For further help on the grid and form options click the respective tab pages below.

  • Customers DataGrid
  • Customers Form

The Northwind Customers grid allows you to browse, filter and sort the customer accounts that you have created within the Northwind customers module.

TIP: Clicking the pencil icon will launch the form in edit mode for the selected record.

Toolbar

Toolbar Item | Description
 | The Quick Search option can be used to quickly filter the grid. NOTE: Fields searched by the Quick Search option are CustomerID, CompanyName, ContactName, Address, City, Region, PostalCode, Country, Phone and Fax.
 | Add New record.
 | The search button can be used if a more detailed search is required. Using this option the grid can be filtered by any value in any field.
 | The Export button is used to export the grid records to an external, downloadable data file. Supported file formats are MS Excel, CSV, XML and JSON. At time of export there are also options to specify which columns are included in the exported data along with other file type specific options.
 | The Settings button can be used to customise the column layout of the grid by adding or subtracting grid columns. The status of the grid can also be saved so that the required grid status can be loaded again at a later time.
 | Refresh the grid.
 | Calls context sensitive help system.

The Northwind Customers form allows you to edit, save or delete the selected customer record.

Toolbar

Toolbar Item | Description
 | Add new record. NOTE: When in Add mode the form toolbar buttons will be replaced with Add and Cancel buttons. Add will add the new record and Cancel will return the form to Edit mode.
 | Save the form.
 | Delete the current record.
 | Call the context sensitive help system.
 | Return to calling grid.

Mandatory Fields

Field Name | Notes
Customer ID | The Customer ID field Is editable only upon adding new records and must be unique within the Customers option.
See Also
Northwind Customers Report
Northwind Customers Report (Detailed)


Northwind Customers Report

Northwind Customers Report
Example Code > Database Applications > Northwind Customers Report

The Northwind Customers Report is a sample report which lists the Microsoft Northwind database customer table and allows simple filtering by Customer ID.

Once run there are options to search the report, export the report output to a variety of formats and to call the web based report designer which allows customisation of the report.

Application Features

  • Export Report to multiple formats.
  • Report is fully searchable.
  • Built in report designer.
  • Report is rendered in HTML5.
  • Report zoom.
  • Report Parameters
  • Report Viewer Options
Parameter Name | Description
Lower Customer ID | Lower customer ID.
Upper Customer ID | Upper customer ID.

Button Name | Description
 | Call context sensitive help system.
 | Render the report in the Upsilon report viewer.

Toolbar

Toolbar Item | Description
 | Print current report to printer. NOTE: Printing is done via PDF format. Your web browser will require a plug-in to view PDF files.
 | Save the current report to PDF, HTML, MS Word, MS Excel or CSV Data file.
 | Search the current report for a text string.
 | Navigate sequentially through the current report pages or enter a specific page number to jump to.
 | Zoom in or out.
 | Select page view.
 | Back to calling application.
 | Call the Upsilon Report Designer.
See Also
Northwind Customers Application


Northwind Customers Report (Detailed)

Northwind Customers Report (Detailed)
View with Navigation Tools
Example Code > Database Applications > Northwind Customers Report (Detailed)

The Northwind Customers (Detailed) Report is a sample report which lists the Microsoft Northwind database customer table and allows simple filtering by Customer ID.

Once run there are options to search the report, export the report output to a variety of formats and to call the web based report designer which allows customisation of the report.

Application Features

  • Export Report to multiple formats.
  • Report is fully searchable.
  • Built in report designer.
  • Report is rendered in HTML5.
  • Report zoom.
  • Report Parameters
  • Report Viewer Options
Parameter Name | Description
Lower Customer ID | Lower customer ID.
Upper Customer ID | Upper customer ID.

Button Name | Description
 | Call context sensitive help system.
 | Render the report in the Upsilon report viewer.

Toolbar

Toolbar Item | Description
 | Print current report to printer. NOTE: Printing is done via PDF format. Your web browser will require a plug-in to view PDF files.
 | Save the current report to PDF, HTML, MS Word, MS Excel or CSV Data file.
 | Search the current report for a text string.
 | Navigate sequentially through the current report pages or enter a specific page number to jump to.
 | Zoom in or out.
 | Select page view.
 | Back to calling application.
 | Call the Upsilon Report Designer.
See Also
Northwind Customers Application


Northwind Orders Application

Northwind Orders Application
Example Code > Database Applications > Northwind Orders Application

test

The Northwind Orders Application is an example of an order processing application built using the Microsoft Northwind database. The application features a searchable grid as a means of navigating the orders table and a master / detail form to display the order record and associated order items.

Application Features

  • Master / Detail Order Form
  • Customisable HTML5 Order Report Output
  • Quick Search
  • Advanced Search
  • Export data to multiple formats
  • Form validation
  • Create, Read, Update and Delete

For further help on the grid and form options click the respective tab pages below.

  • Orders DataGrid
  • Orders Form

The Northwind Orders grid allows you to browse, filter and sort the customer accounts that you have created within the Northwind orders module.

TIP: Clicking the pencil icon will launch the form in edit mode for the selected record.

Toolbar

Toolbar Item | Description
 | The Quick Search option can be used to quickly filter the grid. NOTE: Fields searched by the Quick Search option are OrderID, CustomerID, ShipName, ShipAddress, ShipCity, ShipRegion, ShipPostalCode and ShipCountry.
 | Add New record.
 | The search button can be used if a more detailed search is required. Using this option the grid can be filtered by any value in any field.
 | The Export button is used to export the grid records to an external, downloadable data file. Supported file formats are MS Excel, CSV, XML and JSON. At time of export there are also options to specify which columns are included in the exported data along with other file type specific options.
 | The Settings button can be used to customise the column layout of the grid by adding or subtracting grid columns. The status of the grid can also be saved so that the required grid status can be loaded again at a later time.
 | Refresh the grid.
 | Calls context sensitive help system.

The Northwind Orders form allows you to edit, save or delete the selected order record and its associated order items.

Toolbar

Toolbar Item | Description
 | Add new record. NOTE: When in Add mode the form toolbar buttons will be replaced with Add and Cancel buttons. Add will add the new record and Cancel will return the form to Edit mode.
 | Save the form.
 | Delete the current record.
 | Call the context sensitive help system.
 | Return to calling grid.

Mandatory Fields

Field Name | Notes
Order ID | The Order ID field is automatically populated upon adding a new order to the orders table.
Customer ID | The Customer ID field Is editable only upon adding new records and must be unique within the Customers option.
See Also
Northwind Orders Report


Northwind Orders Report

Northwind Orders Report
Example Code > Database Applications > Northwind Orders Report

The Northwind Orders Report is a sample report which lists the Microsoft Northwind database orders table and related order details table. The report allows filtering by Order ID.

Once run there are options to search the report, export the report output to a variety of formats and to call the web based report designer which allows customisation of the report.

Application Features

  • Export Report to multiple formats.
  • Report is fully searchable.
  • Built in report designer.
  • Report is rendered in HTML5.
  • Report zoom.
  • Report Parameters
  • Report Viewer Options
Parameter Name | Description
Lower Customer ID | Lower customer ID.
Upper Customer ID | Upper customer ID.

Button Name | Description
 | Call context sensitive help system.
 | Render the report in the Upsilon report viewer.

Toolbar

Toolbar Item | Description
 | Print current report to printer. NOTE: Printing is done via PDF format. Your web browser will require a plug-in to view PDF files.
 | Save the current report to PDF, HTML, MS Word, MS Excel or CSV Data file.
 | Search the current report for a text string.
 | Navigate sequentially through the current report pages or enter a specific page number to jump to.
 | Zoom in or out.
 | Select page view.
 | Back to calling application.
 | Call the Upsilon Report Designer.
See Also
Northwind Orders Application


Tools & Utilities Introduction

Tools & Utilities Introduction
Example Code > Tools & Utilities Introduction

The following section of this documentation contains several example Tools & Utilities applications that I have created.

The examples are designed to serve as an overview of the types of application that can be created using the tools and custom application framework code that I have developed over the last few years.

All examples are written in and executed under PHP 7.3.

See Also
Return Current IP Address
Hexadecimal To IPv4 Conversion Application
Online Postcode Lookup
Distance Conversion
Javascript Client Information
Clock Application
Return IP Address Geolocation Data
Plesk Scheduled Task PHP Script


Return Current IP Address

Return Current IP Address
Example Code > Tools & Utilities > Return Current IP Address

This simple application uses several built in PHP functions to determine and then display the public IP address of the device that is being used to load the web page.

function getUserIP()
Copy Code
// Return current IP address.
function getUserIP
{
    if(!empty($_SERVER['HTTP_CLIENT_IP']))
    {
        //ip from share internet
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    }
    elseif(!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
    {
        //ip pass from proxy
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    }
    else
    {
        $ip = $_SERVER['REMOTE_ADDR'];
    }
}

return($ip);
See Also
Hexadecimal To IPv4 Conversion Application
Return IP Address Geolocation Data


Hexadecimal To IPv4 Conversion Application

Hexadecimal To IPv4 Conversion Application
Example Code > Tools & Utilities > Hexadecimal To IPv4 Conversion Application

This simple application allows the conversion of a user entered hexadecimal encoded value to an IPv4 address. This can be useful when checking webserver logs, as on occasion, hostnames are represented in this way.

The application demonstrates the use of AJAX calls to update the result field without the need to reload the entire page. The application is written in and executes under PHP 7.3.

See Also
Return Current IP Address
Return IP Address Geolocation Data


Online Postcode Lookup

Online Postcode Lookup
Example Code > Tools & Utilities > Online Postcode Lookup

This sample application is written in PHP and returns a postal address, or list of addresses, based upon a user inputted postcode and (optional) house number. If the house number is not specified then a drop down list of available addresses is populated for the entered postcode. There is also an option to view the selected address using Google Maps.

The code uses the getAddress.io web service for postcode lookups. Have fun! :-)

See Also
Return IP Address Geolocation Data


Distance Conversion

Distance Conversion
Example Code > Tools & Utilities > Distance Conversion

This simple application allows the conversion of one distance measurement to another measurement. The application demonstrates the use of AJAX calls to update the result field without the need to reload the entire page.

The application is written in and executes under PHP 7.3.


Javascript Client Information

Javascript Client Information
Example Code > Tools & Utilities > Javascript Client Information

This simple application demonstrates the types of information that it is possible to return via JavaScript code executed within a client browser. The application is by no means complete and is designed to serve as an example of the type(s) of information available to developers at the client end.

  • JavaScript Document Object
  • JavaScript Location Object
  • JavaScript Navigator Object
  • JavaScript Screen Object
  • JavaScript Window Object
document.activeElement | Returns the currently focused element in the document.
document.anchors | Returns a collection of all <a> elements in the document that have a name attribute.
document.applets | Returns a collection of all <applet> elements in the document.
document.baseURI | Returns the absolute base URI of a document.
document.cookie | Returns all name/value pairs of cookies in the document.
document.characterSet | Returns the character encoding for the document.
document.doctype | Returns the Document Type Declaration associated with the document.
document.documentURI | Sets or returns the location of the document.
document.domain | Returns the domain name of the server that loaded the document.
document.readyState | Returns the (loading) status of the document.
document.referrer | Returns the URL of the document that loaded the current document.
document.title | Sets or returns the title of the document.
document.URL | Returns the full URL of the HTML document.
location.hash | Sets or returns the anchor part (#) of a URL.
location.host | Sets or returns the hostname and port number of a URL.
location.hostname | Sets or returns the hostname of a URL.
location.href | Sets or returns the entire URL.
location.origin | Returns the protocol, hostname and port number of a URL.
location.pathname | Sets or returns the path name of a URL.
location.port | Sets or returns the port number of a URL.
location.protocol | Sets or returns the protocol of a URL.
location.search | Sets or returns the querystring part of a URL.
navigator.appCodeName | Returns the code name of the browser.
navigator.appName | Returns the name of the browser.
navigator.appVersion | Returns the version information of the browser.
navigator.cookieEnabled | Determines whether cookies are enabled in the browser.
navigator.geolocation | Returns a Geolocation object that can be used to locate the user's position.
navigator.language | Returns the language of the browser.
navigator.onLine | Determines whether the browser is online.
navigator.platform | Returns for which platform the browser is compiled.
navigator.product | Returns the engine name of the browser.
navigator.userAgent | Returns the user-agent header sent by the browser to the server.
navigator.javaEnabled | Specifies whether or not the browser has Java enabled.
navigator.taintEnabled | deprecated.
screen.availHeight | Returns the height of the screen (excluding the Windows Taskbar).
screen.availWidth | Returns the width of the screen (excluding the Windows Taskbar).
screen.colorDepth | Returns the bit depth of the color palette for displaying images.
screen.height | Returns the total height of the screen.
screen.pixelDepth | Returns the color resolution (in bits per pixel) of the screen.
screen.width | Returns the total width of the screen.
window.closed | Returns a Boolean value indicating whether a window has been closed or not.
window.defaultStatus | Sets or returns the default text in the statusbar of a window.
window.frameElement | Returns the <iframe> element in which the current window is inserted.
window.frames | Returns all <iframe> elements in the current window.
window.innerHeight | Returns the height of the window's content area (viewport) including scrollbars.
window.innerWidth | Returns the width of a window's content area (viewport) including scrollbars.
window.length | Returns the number of <iframe> elements in the current window.
window.name | Sets or returns the name of a window.
window.opener | Returns a reference to the window that created the window.
window.outerHeight | Returns the height of the browser window, including toolbars/scrollbars.
window.outerWidth | Returns the width of the browser window, including toolbars/scrollbars.
window.pageXOffset | Returns the pixels the current document has been scrolled (horizontally) from the upper left corner of the window.
window.pageYOffset | Returns the pixels the current document has been scrolled (vertically) from the upper left corner of the window.
window.screenLeft | Returns the horizontal coordinate of the window relative to the screen.
window.screenTop | Returns the vertical coordinate of the window relative to the screen.
window.screenX | Returns the horizontal coordinate of the window relative to the screen.
window.screenY | Returns the vertical coordinate of the window relative to the screen.
window.status | Sets or returns the text in the statusbar of a window.
See Also
Clock Application


Clock Application

Clock Application
Example Code > Tools & Utilities > Clock Application

This simple clock application displays the current, client side date and time in UK format. The application uses the JavaScript setTimeOut() method to refresh the date and time fields every half second.

See Also
Javascript Client Information


Return IP Address Geolocation Data

Return IP Address Geolocation Data
Example Code > Tools & Utilities > Return IP Address Geolocation Data

This sample application returns geolocation data based upon the users public IP address. The application uses the IP Geolocation API from ipinfodb.com to retreive the geolocation information. The application returns the following fields:

  • statusCode
  • statusMessage
  • ipAddress
  • countryCode
  • countryName
  • regionName
  • cityName
  • zipCode
  • latitude
  • longitude
  • timeZone

In addition the application also integrates with Google Maps to display a location map based upon the longitude and latitude contained in the geolocation data.

See Also
Return Current IP Address
Hexadecimal To IPv4 Conversion Application
Online Postcode Lookup


Plesk Scheduled Task PHP Script

Plesk Scheduled Task PHP Script
Example Code > Tools & Utilities > Plesk Scheduled Task PHP Script

The following Plesk Scheduled Task PHP script can be used to run SQL stored in an external text file via the Plesk Scheduled Tasks option for a specified domain hosted on your Plesk server.

The script accepts an argument which is the name of the SQL script text file to execute. Arguments are passed to the PHP binary in Plesk via the $argv array. An interesting note is that the first element in this array is always the PHP script name. The script makes the assumption that it is being run from a folder called mw which is in the root of the domain and outside of the public httpdocs folder, but this can be changed to whatever you like.

Plesk scheduled task PHP script presented here is useful if you want to run batch data processing jobs on your web server at a pre-defined interval.

Plesk Scheduled Task PHP Script
Copy Code
#----------------------------------------------------------------------------#
# Program Copyright    : Mike Wilcock.
# Program Name         : sql_file_import.php
#----------------------------------------------------------------------------#
# Program Created      : 3rd February 2024.
# Program Code Type    : PHP.
# Program Author       : Michael Wilcock.
# Program Version      : 1.10
#----------------------------------------------------------------------------#
# Purpose              : Execute a SQL script stored in an external file from PHP.
#----------------------------------------------------------------------------#
# Notes                : Script to execute is passed into PHP as a parameter
#                        named sql_file.
#
#                        Plesk passes arguments to the PHP binary as the array:
#                        $argv, the first element of which is always the script name.
#----------------------------------------------------------------------------#

$db_host = "localhost";
$db_database = "<your_db>";
$db_user = "<your_username>";
$db_password = "<your_password>";

// Check that a parameter has been provided.
if(isset($argv[1]))
{
    // It has so store it in memory.
    $sql_file = "mw/" . $argv[1];
}
// No parameter passed so terminate script.
else
{
    echo "Parameter sql_file not passed";

    // Exit here.
    return;
}

// Parameter passed but file does not exist.
if(!file_exists("$sql_file"))
{
    echo "Parameter sql_file is not valid";

    // Exit here.
    return;
}

// If we get here we are good to go!

// Create new PDO database connection.
$db = new PDO("mysql:host=$db_host;dbname=$db_database", $db_user, $db_password);

// Enable PDO error output.  This gives us a clue when things go wrong!
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// Load our script into memory.
$query = file_get_contents($sql_file);

// Prepare SQL statement.
$stmt = $db->prepare($query);

// Execute SQL code.
if($stmt->execute())
{
    echo $sql_file . " Executed Successfully :-)";
}
// Problem!
else
{
    echo $sql_file . " Failed with errors! :-0";
}
See Also
Hexadecimal To IPv4 Conversion Application
Return IP Address Geolocation Data


Powershell Scripts - Introduction

Powershell Scripts - Introduction
Example Code > Powershell Scripts - Introduction

The following section of this documentation contains example PowerShell scripts that I have created. All of the scripts presented here have been tested using PowerShell running on Windows 10 or 11.

PowerShell scripting is relatively new to me, but it is something that I have found increasingly useful for the automation of both simple and complex tasks in Windows Server and Windows Desktop environments.

See Also
PowerShell Printer Driver Installation
PowerShell Device Report
PowerShell Automated Reboot
PowerShell Reposition The Windows Taskbar
PowerShell Toast Notifications


PowerShell Printer Driver Installation

PowerShell Printer Driver Installation
Example Code > PowerShell Scripts > PowerShell Printer Driver Installation

The following PowerShell script performs an automated Windows printer driver installation. If the driver and / or port already exist they will be deleted and re-installed / re-created respectively. The .ps1 code is presented below; I have also provided a link to the HP driver installation files. The code has been tested and works on Windows 10/11. The HP Universal Printer Driver has been used here as an example, but the code has been written so that it may be easily modified for other makes and models of printer. Knock yourself out! ;-)

  • Automated Printer Driver Installation
#----------------------------------------------------------------------------#
# Program Copyright    : Mike Wilcock.
# Program Name         : printer_driver_install.ps1.
#----------------------------------------------------------------------------#
# Program Created      : 19th July 2021.
# Program Code Type    : PowerShell Script (version 5.1.19041.1023).
# Program Author       : Michael Wilcock.
# Program Version      : 1.00
#----------------------------------------------------------------------------#
# Printer Driver       : HP Universal Printing PCL 6.
#----------------------------------------------------------------------------#
# Purpose              : Automated printer driver installation.
#----------------------------------------------------------------------------#

# Define printer name, port and ip/hostname strings as memvars.
$cPrn_driver_name = "HP Universal Printing PCL 6"
$cHost_or_ip = "HP Universal Printing PCL 6"
$cPort_name = ("auto_" + $cHost_or_ip)
$cDriver_path_local = ("C:\HP Universal Print Driver\pcl6-x64-7.0.1.24923\")
$cInf_file = ("C:\Windows\System32\DriverStore\FileRepository\" + "hpcu255u.inf_amd64_883dd40f467c5d42\hpcu255u.inf")

clear screen
write-host "Printer Name             : " $cPrn_driver_name
write-host "Port Name                : " $cPort_name
write-host "Hostname / IP Address    : " $cHost_or_ip
write-host "Driver Path (Local)      : " $cDriver_path_local
write-host "Printer Driver .inf File : " $cInf_file
write-host ""

# Promt user?
$user_conf = read-host ("Install Printer Driver For Printer: " + $cHost_or_ip + " To: " + $env:computername + " - [Y/N]")

# User bailed! :-(
if($user_conf -ne "Y")
{
    clear screen
    Write-Host "Printer driver installation cancelled by user."
    break
}
clear screen

# Query printer.
Get-Printer -Name $cHost_or_ip -erroraction 'silentlycontinue' | Out-Null

# Printer exists on this machine so remove it.
if($?)
{
    # Delete the printer.
    write-host "Deleting Printer       :" $cHost_or_ip
    Remove-Printer -Name $cHost_or_ip #-ErrorAction:SilentlyContinue
}

# Query printer port.
Get-PrinterPort -Name $cPort_name -erroraction 'silentlycontinue' | Out-Null

# Printer port exists on this machine so remove it.
if($?)
{
    # Delete the printer port.
    write-host "Deleting Printer Port  :" $cPort_name
    Remove-PrinterPort -Name $cPort_name #-ErrorAction:SilentlyContinue
}

# Query printer driver.
Get-PrinterDriver -Name $cPrn_driver_name -erroraction 'silentlycontinue' | Out-Null

# Printer driver exists on this machine so remove it.
if($?)
{
    # Delete the printer driver.
    write-host "Deleting Printer Driver:" $cPrn_driver_name
    Remove-PrinterDriver -Name $cPrn_driver_name #-ErrorAction:SilentlyContinue
}

# Copy drivers to the Windows driver store.
write-host ""
write-host "Copying Drivers To The Windows Driver Store - Please Wait."
write-host ""

pnputil.exe /a ($cDriver_path_local + "hpcu255u.inf") | Out-Null

# There was a problem so terminate the script.
if($lastExitCode -ne 0)
{
    Write-Host "There was a problem copying the driver files to the Windows driver store."

    # Gracefully exit. :-)
    Break
}

# Add printer driver.
write-host "Adding Printer Driver - Please Wait."
Add-PrinterDriver -Name $cPrn_driver_name -InfPath $cInf_file

if($?)
{
    write-host "Printer Driver Added Successfully."
    write-host ""
}

# Add printer port.
write-host "Adding Printer Port - Please Wait."
Add-PrinterPort -Name $cPort_name -PrinterHostAddress $cHost_or_ip

if($?)
{
    write-host "Printer Port Added Successfully."
    write-host ""
}

# Add printer.
write-host "Adding Printer - Please Wait."
Add-Printer -DriverName $cPrn_driver_name -Name $cPrn_driver_name -PortName $cPort_name

if($?)
{
    write-host "Printer Added Successfully."
    write-host ""
}

# Rename printer.
Rename-Printer -Name $cPrn_driver_name -NewName $cHost_or_ip

# Test page promt.
$user_conf = read-host ("Print Test Page To : " + $cHost_or_ip + " - [Y/N]")

# Print test page.
if($user_conf -eq "Y")
{
    Get-CimInstance Win32_Printer -Filter "name LIKE '$cHost_or_ip'" | Invoke-CimMethod -MethodName PrintTestPage | Out-Null

    write-host ""
    write-host "Test Page Sent To Printer."
}

# Foshizzle! :-)
write-host ""
write-host "Script Completed Successfully."
See Also
PowerShell Device Report
PowerShell Automated Reboot
PowerShell Reposition The Windows Taskbar
PowerShell Toast Notifications


PowerShell Device Report

PowerShell Device Report
Example Code > PowerShell Scripts > PowerShell Device Report

The following PowerShell script generates a PowerShell device report which lists various details of the machine on which it is executed. These details include information such as installed drives, printers, RAM and software. The code also allows you to optionally export the device report as an .xml file.

The .ps1 code is presented below; The code has been tested and works on Windows 10/11.

  • PowerShell Device Report
#----------------------------------------------------------------------------#
# Program Copyright    : Mike Wilcock.
# Program Name         : device-report.ps1.
#----------------------------------------------------------------------------#
# Program Created      : 3rd July 2021.
# Program Code Type    : PowerShell Script (version 5.1.19041.1023).
# Author               : Michael Wilcock, IT Technician.
# Version              : 1.01
#----------------------------------------------------------------------------#
# Purpose              : Generate a device report and optionally export to xml.
#----------------------------------------------------------------------------#

clear screen

# Promt user?
$user_conf = read-host "Run Device Report - [Y/N]"

# User bailed! :-(
if($user_conf -ne "Y")
{
    clear screen
    break
}

clear screen

write-host "Getting Computer Information - Please Wait."

# Get computer infomation object.
$oCompInf = Get-ComputerInfo

write-host "Getting Disk Information - Please Wait."

# Get physical disk information object
$oPhyDisks = Get-PhysicalDisk

write-host "Getting Printer Information - Please Wait."

# Get installed printers object.
$oPrinters = Get-Printer

write-host "Getting Installed Software Information - Please Wait."

# Get installed software object.
$oInstalledCode = Get-WmiObject -Class Win32_Product | Sort-Object Name, Version

#----------------------------------------------------------------------------#
# Machine overview.
#----------------------------------------------------------------------------#

# Store required data in memory.
$cHostname = ($oCompInf).CsDNSHostName
$cManufacturer = ($oCompInf).CsManufacturer
$cModel = ($oCompInf).CsModel
$cDomain = ($oCompInf).CsDomain
$nTotMem = ($oCompInf).OsTotalVisibleMemorySize / (1024 * 1024) # kilobytes to gigabytes conversion.
$nInstMem = ($oCompInf).CsPhyicallyInstalledMemory / (1024 * 1024) # kilobytes to gigabytes conversion.
$cProdName = ($oCompInf).WindowsProductName
$cWinVer = ($oCompInf).WindowsVersion
$cOSVer = ($oCompInf).OsVersion
$cOSArch = ($oCompInf).OsArchitecture
$cOSInstDate = ($oCompInf).OsInstallDate
$cOSBootDev = ($oCompInf).OsBootDevice
$cBIOSMan = ($oCompInf).BiosManufacturer
$cBIOSName = ($oCompInf).BiosName
$cBIOSVer = ($oCompInf).BiosVersion
$cBIOSDate = ($oCompInf).BiosReleaseDate
$lMemWarning = $false
$lDriveWarning = $false
$cNl = "`r`n"

# Device installed memory is <= 4GB!
if($nInstMem -le 4)
{
    $lMemWarning = $true
}

clear screen

write-host "---------------------------------------------------------"
write-host "Device Report"
write-host "---------------------------------------------------------"
write-host ""
write-host "---------------------------------------------------------"
write-host "MACHINE OVERVIEW"
write-host "---------------------------------------------------------"
write-host ""
write-host "Host Name             : " $cHostname
write-host "Domain                : " $cDomain
write-host ""
write-host "Device Manufacturer   : " $cManufacturer
write-host "Device Model          : " $cModel
write-host "Visible Memory        : " $nTotMem "GB"

# RAM needs upgrading.
if($lMemWarning)
{
    write-host "Installed Memory      : " $nInstMem "GB - WARNING!"
}
# Ok.
else
{
    write-host "Installed Memory      : " $nInstMem "GB"
}

write-host "Windows Product Name  : " $cProdName
write-host "Windows Version       : " $cWinVer
write-host "OS Version            : " $cOSVer
write-host "OS Architecture       : " $cOsArch
write-host "OS Install Date       : " $cOSInstDate
write-host "OS Boot Device        : " $cOSBootDev
write-host ""
write-host "BIOS Manufacturer     : " $cBIOSMan
write-host "BIOS Name             : " $cBIOSName
write-host "BIOS Version          : " $cBIOSVer
write-host "BIOS Release Date     : " $cBIOSDate

#----------------------------------------------------------------------------#
# Installed disk drives.
#----------------------------------------------------------------------------#

write-host ""
write-host "---------------------------------------------------------"
write-host "INSTALLED DRIVES"
write-host "---------------------------------------------------------"
write-host ""
write-host " ID Type Name                                           Size Message"
write-host "--- ---- ------------------------------- ------------------- --------"

# Loop through each installed disk drive.
ForEach ($n in $oPhyDisks)
{
    $dID = [string]($n).DeviceId
    $dType = [string]($n).MediaType
    $dAllocSize = [string]($n).AllocatedSize
    $dFName = [string]($n).FriendlyName

    # Device is a Hard Drive.
    if($dType -eq "HDD")
    {
        $dMessage = "WARNING!"

        # update boolean variable.
        $lDriveWarning = $true
    }
    # SSD.
    else
    {
        $dMessage = "Ok"
    }

    # Output to console.
    write-host $dID.PadLeft(3, " ") $dType.PadRight(4, " ") $dFName.PadRight(30, " ") $dAllocSize.PadLeft(20, " ") $dMessage
}

#----------------------------------------------------------------------------#
# Installed printers.
#----------------------------------------------------------------------------#

write-host ""
write-host "---------------------------------------------------------"
write-host "INSTALLED PRINTERS"
write-host "---------------------------------------------------------"
write-host ""
write-host "Name                           Type       Driver Name                   "
write-host "------------------------------ ---------- ------------------------------"

# Loop through each installed printer.
ForEach ($n in $oPrinters)
{
    $pName = [string]($n).Name
    $pDriverName = [string]($n).DriverName
    $pType = [string]($n).Type
    $pPort = [string]($n).PortName

    # Output to console.
    write-host $pName.PadRight(30, " ") $pType.PadRight(10, " ") $pDriverName
}

#----------------------------------------------------------------------------#
# Installed software.
#----------------------------------------------------------------------------#

write-host ""
write-host "---------------------------------------------------------"
write-host "INSTALLED SOFTWARE"
write-host "---------------------------------------------------------"
write-host ""
write-host "Name                                          Vendor                         Version              Install Date"
write-host "--------------------------------------------- ------------------------------ -------------------- ------------"

# Loop through each installed application.
ForEach ($n in $oInstalledCode)
{
    $sName = [string]($n).Name
    $sVendor = [string]($n).Vendor
    $sVersion = [string]($n).Version
    $sInstDate = [string]($n).InstallDate

    # Output to console.
    write-host "$sName $(" " * 45)".Substring(0,45) "$sVendor $(" " * 30)".Substring(0,30) "$sVersion $(" " * 20)".Substring(0,20) $sInstDate
}

write-host ""
write-host "---------------------------------------------------------"
write-host "Script Completed Successfully"
write-host "---------------------------------------------------------"
write-host ""

# Installed memory <= 4GB!
if($lMemWarning)
{
    write-host "WARNING - Device Has 4GB Of Memory Or Less."
}

# At least 1 HDD Installed!
if($lDriveWarning)
{
    write-host "WARNING - Device Has At Least One HDD Installed."
}

# Line Space.  Keep things tidy!
if($lMemWarning -Or $lDriveWarning)
{
    write-host ""
}

# Promt user?
$user_conf = read-host "Output Device Report As An XML File? - [Y/N]"

# Generate xml document.
if($user_conf -eq "Y")
{
    $cDateTime = Get-Date -Format "dd-MM-yyyy-HH-mm-ss"

    # Initialise XML string.
    $cOutFile = '<?xml-stylesheet type="text/xsl" href="stylesheet.xsl"?>'

    # Start append.
    $cOutFile += ("<" + $cHostname + ">" + $cNl)
    $cOutFile += ("    <device_overview>" + $cNl)
    $cOutFile += ("        <hostname>" + $cHostname + "</hostname>" + $cNl)
    $cOutFile += ("        <domain>" + $cDomain + "</domain>" + $cNl)
    $cOutFile += ("        <device_manufacturer>" + $cManufacturer + "</device_manufacturer>" + $cNl)
    $cOutFile += ("        <device_model>" + $cModel + "</device_model>" + $cNl)
    $cOutFile += ("        <visible_memory>" + $nTotMem + "</visible_memory>" + $cNl)
    $cOutFile += ("        <installed_memory>" + $nInstMem + "</installed_memory>" + $cNl)
    $cOutFile += ("        <windows_product_name>" + $cProdname + "</windows_product_name>" + $cNl)
    $cOutFile += ("        <windows_version>" + $cWinVer + "</windows_version>" + $cNl)
    $cOutFile += ("        <os_version>" + $cOSVer + "</os_version>" + $cNl)
    $cOutFile += ("        <os_architecture>" + $cOSArch + "</os_architecture>" + $cNl)
    $cOutFile += ("        <os_install_date>" + $cOSInstDate + "</os_install_date>" + $cNl)
    $cOutFile += ("        <os_boot_device>" + $cOSBootDev + "</os_boot_device>" + $cNl)
    $cOutFile += ("        <bios_manufacturer>" + $cBIOSMan + "</bios_manufacturer>" + $cNl)
    $cOutFile += ("        <bios_name>" + $cBIOSNAme + "</bios_name>" + $cNl)
    $cOutFile += ("        <bios_version>" + $cBIOSVer + "</bios_version>" + $cNl)
    $cOutFile += ("        <bios_release_date>" + $cBIOSDate + "</bios_release_date>" + $cNl)
    $cOutFile += ("    </device_overview>" + $cNl)

    # Installed disk drives.
    $cOutFile += ("    <installed_drives>" + $cNl)

    # Loop counter.
    $nCount = 0

    # Loop through each installed disk drive.
    ForEach ($n in $oPhyDisks)
    {
        $dID = [string]($n).DeviceId
        $dType = [string]($n).MediaType
        $dAllocSize = [string]($n).AllocatedSize
        $dFName = [string]($n).FriendlyName

        # Device is a Hard Drive.
        if($dType -eq "HDD")
        {
            $dMessage = "WARNING!"
        }
        # SSD.
        else
        {
            $dMessage = "Ok"
        }

        $cOutFile += ("        <drive" + $nCount + ">" + $cNl)
        $cOutFile += ("            <drive_id>" + $dID + "</drive_id>" + $cNl)
        $cOutFile += ("            <drive_type>" + $dType + "</drive_type>" + $cNl)
        $cOutFile += ("            <drive_size>" + $dAllocSize + "</drive_size>" + $cNl)
        $cOutFile += ("            <drive_name>" + $dFName + "</drive_name>" + $cNl)
        $cOutFile += ("        </drive" + $nCount + ">" + $cNl)

        # Increment loop counter.
        $nCount++
    }

    $cOutFile += ("    </installed_drives>" + $cNl)

    # Installed printers.
    $cOutFile += ("    <installed_printers>" + $cNl)

    # Loop counter.
    $nCount = 0

    # Loop through each installed printer.
    ForEach ($n in $oPrinters)
    {
        $pName = [string]($n).Name
        $pDriverName = [string]($n).DriverName
        $pType = [string]($n).Type
        $pPort = [string]($n).PortName

        # XML does not like the & sign.  This is an extremely "industrial" way of getting around this problem.
        $pName = $pName.Replace("&", "&amp;")
        $pDriverName = $pDriverName.Replace("&", "&amp;")

        $cOutFile += ("        <printer" + $nCount + ">" + $cNl)
        $cOutFile += ("            <printer_name>" + $pName + "</printer_name>" + $cNl)
        $cOutFile += ("            <printer_driver_name>" + $pDriverName + "</printer_driver_name>" + $cNl)
        $cOutFile += ("            <printer_type>" + $pType + "</printer_type>" + $cNl)
        $cOutFile += ("            <printer_port>" + $pPort + "</printer_port>" + $cNl)
        $cOutFile += ("        </printer" + $nCount + ">" + $cNl)

        # Increment loop counter.
        $nCount++
    }

    $cOutFile += ("    </installed_printers>" + $cNl)

    # Installed software.
    $cOutFile += ("    <installed_software>" + $cNl)

    # Loop counter.
    $nCount = 0

    # Loop through each installed application.
    ForEach ($n in $oInstalledCode)
    {
        $sName = [string]($n).Name
        $sVendor = [string]($n).Vendor
        $sVersion = [string]($n).Version
        $sInstDate = [string]($n).InstallDate

        # XML does not like the & sign.  This is an extremely "industrial" way of getting around this problem.
        $sName = $sName.Replace("&", "&amp;")
        $sVendor = $sVendor.Replace("&", "&amp;")

        $cOutFile += ("        <application" + $nCount + ">" + $cNl)
        $cOutFile += ("            <application_name>" + $sName + "</application_name>" + $cNl)
        $cOutFile += ("            <application_vendor>" + $sVendor + "</application_vendor>" + $cNl)
        $cOutFile += ("            <application_version>" + $sVersion + "</application_version>" + $cNl)
        $cOutFile += ("            <application_install_date>" + $sInstDate + "</application_install_date>" + $cNl)
        $cOutFile += ("        </application" + $nCount + ">" + $cNl)

        # Increment loop counter.
        $nCount++
    }

    $cOutFile += ("    </installed_software>" + $cNl)

    # EOF :-).
    $cOutFile += ("</" + $cHostname + ">")

    # Write XML data to disk.
    Set-Content -Path ($PSScriptRoot + "\" + $cHostname + " - " + $cDateTime + ".xml") -Value $cOutFile
}
See Also
PowerShell Printer Driver Installation
PowerShell Automated Reboot
PowerShell Reposition The Windows Taskbar
PowerShell Toast Notifications


PowerShell Automated Reboot

PowerShell Automated Reboot
Example Code > PowerShell Scripts > PowerShell Automated Reboot

The following PowerShell script creates a dialog window which performs an automated device reboot after a pre-specified timeout period. The dialog window has buttons for Cancel and Reboot Now. If the users selects Cancel the script terminates with immediate effect. Should the user select Reboot Now the device will reboot immediately. If no action is taken by the user the code contains a countdown timer object which will countdown and then reboot the device automatically once the timeout period has been met.

The two important variables are $nTimeout which contains the timeout period in seconds and $debug_mode which can be set to $true when testing so that no actual reboot takes place.

The routine is designed to be called as a Windows scheduled task and can be used to automatically reboot workstations at a specified day and time. This is useful for devices that are left on permanently and can often go for weeks or even months without a shutdown or restart.

The .ps1 code is presented below; The code has been tested and works on Windows 10/11.

  • PowerShell Automated Reboot
#----------------------------------------------------------------------------#
# Program Copyright    : Mike Wilcock.
# Program Name         : device_reboot.ps1.
#----------------------------------------------------------------------------#
# Program Created      : 23rd May 2023.
# Program Code Type    : PowerShell Script (version 5.1.22621.436).
# Author               : Michael Wilcock, IT Technician.
#----------------------------------------------------------------------------#
# Version              : 2.10
#----------------------------------------------------------------------------#
# Purpose              : Reboot PC with user confirmation dialog box and timeout.
#----------------------------------------------------------------------------#

# Timeout in seconds.
$nTimeout = 30

# If set to true the reboot will not happen.  Set to false for production.
$debug_mode = $true

# Countdown timer.  Variable MUST be global in scope.
$global:nCountdown = $nTimeout

#----------------------------------------------------------------------------#
# Elegantly perform reboot.
#----------------------------------------------------------------------------#
# Notes: Function is called by the timer object and the reboot button click event.
#
#        If memvar $debug_mode is $true perform a simulated reboot
#----------------------------------------------------------------------------#

function close_and_reboot()
{
    # Simulate reboot for testing.
    if($debug_mode -eq $true)
    {
        Restart-Computer -whatIf
    }
    # Production.
    else
    {
        Restart-Computer
    }

    # Close dialog window.
    $oDlg.Close()
}

#----------------------------------------------------------------------------#
# Update countdown timer label.
#----------------------------------------------------------------------------#
# Notes: Function is called every second by the timer object.  Uses globaly
#        scoped variable to store the seconds left until reboot happens.
#----------------------------------------------------------------------------#

function updCountdown()
{
    # Decrement countdown timer global variable.
    $global:nCountdown--

    # Update countdown label.
    $lbl_countdown.text = "Time To Restart: " + $global:nCountdown
}

#----------------------------------------------------------------------------#
# Main code.  Create dialog window, timer object and form components.
#----------------------------------------------------------------------------#

# Load windows forms class.
Add-Type -assembly System.Windows.Forms

$cMessage = "Device: " + $env:computername + " Requires A Reboot`n`nPlease select Cancel to delay the restart until further notice.`n`nIf no selection is made the device will restart after $nTimeout seconds!"
$cTitle = "[" + $env:computername + "] - " + "Automatic Device Restart"
$CenterScreen = [System.Windows.Forms.FormStartPosition]::CenterScreen;

# Button row in pixels.
$nBtnRow = 170

# Create our dialog window.
$oDlg = New-Object System.Windows.Forms.Form
$oDlg.Text = $cTitle
$oDlg.Width = 475
$oDlg.Height = 235
$oDlg.FormBorderStyle = 'Fixed3D'
$oDlg.MaximizeBox = $false
$oDlg.MinimizeBox = $false
$oDlg.StartPosition = $CenterScreen;
$oDlg.AutoSize = $true

# Create a timer.
$timer_reboot = New-Object System.Windows.Forms.Timer
$timer_reboot.Interval = $nTimeout * 1000

# Set up the event handler for the timer.
$timer_reboot.Add_Tick({close_and_reboot})

# Panel object.
$panel = New-Object System.Windows.Forms.Panel
$panel.Left = 0
$panel.Top = 0
$panel.Width = $oDlg.Width
$panel.Height = 61
$panel.BackColor = '255, 255, 255'
$panel.Dock = "top"

# Add panel to our form.
$oDlg.Controls.Add($panel)

# Add an image to the form using Base64.
$base64ImageString = "iVBORw0KGgoAAAANSUhEUgAAAGQAAAA9CAIAAADUAVs8AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAA6hSURBVHhe7VoHWFRXFh6YYYZehl6GIr0oSlFQFAsW1kIs0f0s0U1cLJvEmKiJ62ZXY9cY1xJi1Kj51MQaC5bEAoIIgoACSh0FpMMwQx1GhrL/zH0zjAjq7LeSMTv/Nx+cc9699937v3POPa9odHZ20tR4PWhS/9V4DajJUgJqspSAmiwloCZLCajJUgJqspSAytVZiYW1pXUtlPI7YbSbuZkei1IUoHJkvXfs3tF7TynlzUNDQ/K3GwdXFg8L97SiFAWoNFmhLubvDrQlMnAjv/p8Zjml0GiRQ50G2BhBwAJWRz+cOcjOz86YHNp7+3FuVSORB9oaLwx2JHL8Y96p+6UgaLA9e5yHRZCjqY2RtjaD3vSsray+pVggPJBY+LCi4a0ka9c0349DXYgMcHlNrut/I7KmhsbdT0cF2ptATi7mD90Zm7R81GAHNlQsiPOvK1i8tCHtb8Od984YSORPfsn4PrFwz3Tf+YMdtOg95OtFJ9P3Jxb2RpZKJ3h/joQLOTjGuo5sXSIbaDO8rQyJDCfSZ2n1l3oZkFPVUNkoIjIw0sWckmi01KeC1WHuC4Od5Ey1tnUIW9vbOyQe0yJujy2oIfYeobpkGbAYvrbU+glYDM0wdwsie1ka6DLpRMae4GNtqKNFqY8qG8jiAYamBg4RuV4kflLbDKaIitCbezTFfu1Vy39cMl8TPWJ33L+uZHNrmsjRHqG6ZLlbGuizGESWZ4opPjZECJRGHMGDsrpgxy41pVhASTSaqR6rn5kekfOqGuGP1obaRAV3J9NLqxpFYE0gFN9+zNsek//ylKS6ZI2ShY+4veNUeimRsakb62hB8JUFHa+5Nbuy0UemAm0dHYPsjMkv3MuSKYu41BIBSCEyYGukczFy6CjXriB9JVSXLC9Z+FQ1PtsdzyWyHpMR5MjGdg8iiOUxrwmu4c+hVGDnVN/0lWPI7/DsAMoKByytr2l6lvCER+k0GrJ4zIcjUj4bPdG7h3T+IlSXLLLTARll9WklAlBG1Ij+NnAubxmV8VyeuT7Lw8KAqC9BylM+/k4/dPd6XhWxEOBElyKHLR/pSum9Q0XJ4hjruJrpExnh86yt42Z+NVFBVoC9iWJwDXYwke9u2O92xXHJ77uEJ9jsiL2yQfSE1wwBzjUuKiF0d9zpB6Vtsn0A2DrFR77V9gYVJWugnTGTQc0NnoW/P6YUExUZeuYgDpGRzh6U1pHSlOCHu0UopshvdxxXPkhOVWNTaxuRAVSnMw8ne226BhKJBXSHOJsRuTeoKFnyogF03C+V7G53sO3LVvuXIQ5EKK8Xoewe5kQtEhUDClQiAwMUKo/M8voXq++CmqZb3K7CSl5w9AYVJUteSZYIWsh9NZgCX8RI15Te0cHpyuvBpoclFbCCFnERXxJrBH4KWR95fbSr+baI/qhdUaCh/rIy0J7tzwlzowo3RHp6SR2Re4MqkoXy0tOSyt+ZFfXyzHIhq+vGkCCrvN7eRBc/oqKUVywOgh1NiYARHlU0TPS2XjnaLfPzsLotUxq2RRSvCz/+3mAzferpAlJYXjV1O9kbVJEsLN7SgFpDpjRhEeAeuP35WIopqEbCkmf3R5VdjVHuO8vKUST1Ir5wko81UdEe10O+RbS2d3x/58lHZx4Q9SWgr127lhJVA+cyy/lCMSIFeR2/k/dL5Y+3sCrcP2PZ5FBaSd1PaSWoLRGJVOP0MmQ20pity3Q21Uecwh79sAIZHRFdWCusaxEj4vC3ol6EEU6kl3x2Luvg3SKRbN8E5gTYu5pToa2I//fnWT3irXlEg/t+xST9uwBZnyPLg4pQObJUGSpaOqgm3kqy6urqampqOjq6UnLfoI/IQrAnJSXt2bPnq6++On/+vFhMVUOwy+XXR0xMjIeHx6+//krp/zs8e0bdrveIviALjOzYsSMiIuLQoUPXr19fsmRJeno67EKhcPz48Xv37iXNfnccPnx4zJgxL7l4fUFWU1PTwYMHhwwZkpiYePv27cLCQh8fH8yJz+enpaU1S0FaIrLKysoePnxYX99VXhJUVFTk5ORgKEqXAb6A7sRDwT4s6Jubm9vS8tzLR0Quhi0vL5dvaGhPzouIxlHImZmZRUVFEHrlC53fNEQikaurq5OT08WLFylTZ+f+/futra3ZbLapqSmE2tpaTHrq1Kl2dnaWlpYwLl26tL0dFXsnDi1YsMDKysrCwgL2/Pz8s2fPouPly5fRZcSIEWFhYTwe7/Tp0+i7b98+X19fHHVxcUG0ontbW9vmzZuh2tjYwD527NiCggLYY2Njcd5NmzZhYjNnzvTy8sJ50QDGDRs2SKb4AvqCLAAejnkAEydO5HK5sDQ0NJw6dQqW1atXP3jwAI6wbNkyc3PzY8eOCQQCLA+HELzwtVWrVkHeuHEjaIJj4soTss6cOTNnzhxQk5eXhwHJaMOHD8doKSkpzs7Onp6e8JELFy6A4hUrVlRWVqI7TgF+0R5koT1I/Pbbb+Pj4zHIhAkTbG1t0Rf+JZn0C+gjsoBbt26BKcwPPpKVlQVLdnY21K1bt0KGE8H7MN3W1laoCCisNiQkBHGHXD5u3DjiZQSErICAAEdHRwQXMRKyjhw5QtTPP/8cHOHCREZGmpmZIYSJfdGiRVAR7ISs9evXEzswd+5ckEUm0CP6rnQIDQ2Njo5es2YNZnP06FHKKgNCFQRpaGhoaUneR7BYLB0dHQjgCD7IZDI1NbtPNTAwsLGxMTU1ldKlMDKinmHp6UnuosE1qTBAnNQssWPZSJdEBd1EeB30BVmYLq4/BHDh7e0NwdhY8qSJ8EJ2a1CD3IHrj2CBiriA4O7ubmBgYG9vj8hCmMCuWFuFS4H4ysjIoEw02tWrV/EXvCckJOAs8BQ3Nzf0woCwI/cnJyfDjnNJm0umRASATpe8ecRlI2oPIA72RoHsi6wZHByMQgErx1ZIkgJJ/BwOZ/HixchTWAYiFGwiUpBKcAhximZ37txBagdmz56NlHTv3j15gsfikZgRp/AUEoZ+fn5wYZwLsYY0h+4Y2d/fHyO///77w4YNQxY/cOAA7CQMkSIhE0RFRcEyefLk48ePU6bn0RePaHR1dbEkQ0NDuNL06dO3bduGjQl2BoOBjQxxgUuK5YGgSZMmoTEoQL2zfft2pC00A5szZszA4rEJgCwkMsggHRTAcYKCgrAJIkgRkpcuXULdi3FwroULF86fPx9n1NbWnjdvHlgAoRhw3bp1U6ZMIbPCJRw6dChGk8ySRkMSRLTC1zACnJoYnwNF2tsP4llwN0p/A+i7BP8HwB/nEQ2yOOIXQUe20TcB9fMsJdA9DIWt7c9kT6PJezqRuF3cLrGAVfmbO0GLOKeyoUXcTlSgraMTR8mPMimPwtrm3fFcxRfF3RDH5aU+7fpI5uXAWuRTesmYr4/uZM06kmy6+iL5sCDg65iUp4IdsQUwQhWK28xWX8qparyQVT54R8zKC1kRBxKlnSRIKqzVX3lhbFTCuKiE7MoGyqokKhtEX8fkv+jse+If/5RWAqGY3/zKF1ZyfHnlkd/2m5hV8Dexf78kKfReibMZZbviqI9QXgT1AZQivKwM113Njpo5iNJfwJXsygCOyc/zB1O6DEY6WgnLQjWlZd7dIv75rHJNDdqSEGc7I5098dxZfhxzfebOWwVzAxweVTYIhK1PBUJeU+s/J3gy6Zon0kvuPRV4WlLfd9x+wovOqtCia346yjWzvP7HlGJ9Fp1jrGOmzyKvsG7mV19+VIkzLgt1MdbRwrDoey23eoSz2TsDqG+4drwzAN2d1l2N+XAEl9d8LrO8iN881t0SF3vlGDfExaHkos9GueG8v2SUsfWYY9wsvkt4whe29jPTm+xNvTdTRA+74QfBTpezKx9LP6MgSCzkRxxMhH+R13aRQ51wvqBvYjMUXuoBHZ2dkSfSF/6cdr+0btoPSR6WBmxd5pAdMaK29i038kBNe0fn5ut5cJ/YguoV5zMZmpon75dEJTy+WVC9/FzGIDvjc7LXqHQNjT/7c6oaRV9EZ1kbajMlLwH1zfVZFx9W3MirvpZbNfvHlJGu5sV8Yfi+BITYlut5x1JLzPSZM48kN4h6yAP3y+qWnr7fKGqraxFvuJaLLnwIv+WKOzoWHE8FO0EObIwP9nE6G9kHb93QA1m4UJ+MdFn/Ww6lS788WDPOY8VoN6L6c0yK1oY7meqO3BOnODNwMdufMy/QPrmYjws1P9Bh+UhXNEgrobKMYt4I6Wf20QjndwfacWua47k8qOj4RZikFMRKcKk3XstFxOVVN4F0J7aeq5k+BNI3qYgf6mI+xcd6bbgnBq9vEWPgpSH9cDpdJr2sl8/ova0Mv5zg6SD7VEYe7B8EOa66kHU9v9qRretmrm9nrNPtW1Y5eiALWBjslFRUi0kQVY9JH2zPDrQ3wQWHCseBZdUYd+T+BlHXczJEDa42loGVI1XD58Eag66B0+uxGHHcGuQ1+Zgs2fctgKu5PmIBgYmRoZbXtxxMKto/y2+yjw35QhKNa4WtEkkKLAkj85qfIVqtDHW0tSRDkffSmGFn11eVz4EuTRAYCjRlldffzK8hX4J8EOwY93Hov2MLkI7RpLa560Td0J0sb+mXrAYsxpbJ/bFIhoaGk6merZGkcsFsJHxpamCiA7be+OuJ9J3TfNGGdIQPB8ouiI+14YaJ3n/6/s6K81m7pvk6sPU2TvSOSnhy9N7TcC8rjNDPVM9GOiYEK0PWnADOeA/L4bviwJenpSHHRHf6QNvJ+++0tnU4mEocAU6HwEdCcTbVszBgzfKzWzDEIWRX3JHk4iNzAlgMOnIocpmWpiacgiRNAj0mI9CejTsYe2MdexPJGTFP5Kl5mIpAGOTIFrd1LjqZjs1qSUg/eBZOlF/duDq6593gv6yzJH06cctOtF6BZq9q0gVMRHFApfoqi5cP3ttRdVGqBHrOWWr0CDVZSkBNlhJQk6UE1GQpATVZSkBNlhJQk/XaoNH+A1L+dFlhjf9fAAAAAElFTkSuQmCC"
$imageBytes = [Convert]::FromBase64String($base64ImageString)
$ms = New-Object IO.MemoryStream($imageBytes, 0, $imageBytes.Length)
$ms.Write($imageBytes, 0, $imageBytes.Length);
$nhs_logo = [System.Drawing.Image]::FromStream($ms, $true)

# picturebox object.
$pictureBox = new-object Windows.Forms.PictureBox
$pictureBox.Width =  $nhs_logo.Size.Width;
$pictureBox.Height =  $nhs_logo.Size.Height;
$pictureBox.Location = New-Object System.Drawing.Size(360,0)
$pictureBox.Image = $nhs_logo;

# Add picturebox to our form.
$oDlg.Controls.Add($pictureBox)

# User message label.
$lbl_message = New-Object System.Windows.Forms.Label
$lbl_message.Text = $cMessage
$lbl_message.Location  = New-Object System.Drawing.Point(10,80)
$lbl_message.AutoSize = $true

# Add label to our form.
$oDlg.Controls.Add($lbl_message)

# Countdown timer label.
$lbl_countdown = New-Object System.Windows.Forms.Label
$lbl_countdown.Text = "Time To Restart: " + $nCountdown
$lbl_countdown.Location  = New-Object System.Drawing.Point(10, $nBtnRow)
$lbl_countdown.ForeColor = "red"
$lbl_countdown.AutoSize = $true

# Add label to our form.
$oDlg.Controls.Add($lbl_countdown)

# Create a timer.
$timer_countdown = New-Object System.Windows.Forms.Timer
$timer_countdown.Interval = 1000

# Set up the event handler for the timer.
$timer_countdown.Add_Tick({updCountdown})

# Reboot button.
$btn_reboot = New-Object System.Windows.Forms.Button
$btn_reboot.Location = New-Object System.Drawing.Size(355, $nBtnRow)
$btn_reboot.Size = New-Object System.Drawing.Size(100, 23)
$btn_reboot.Text = "REBOOT NOW"

# Add button to our form.
$oDlg.Controls.Add($btn_reboot)

# Capture click event.
$btn_reboot.Add_Click({close_and_reboot})

# Cancel button.
$btn_cancel = New-Object System.Windows.Forms.Button
$btn_cancel.Location = New-Object System.Drawing.Size(255, $nBtnRow)
$btn_cancel.Size = New-Object System.Drawing.Size(100, 23)
$btn_cancel.Text = "Cancel"
$oDlg.Controls.Add($btn_cancel)

# Add button to our form.
$btn_cancel.Add_Click({$oDlg.Close()})

# IMPORTANT. Order items for correct display.
$oDlg.Controls.SetChildIndex($panel, 1)

# Start both timers.
$timer_reboot.Start()
$timer_countdown.Start()

# Let's do this thing!
$oDlg.ShowDialog()

# Dispose (stop) the timer. Doing this here instead of in the tick
# event handler ensures that the timer is stopped even when the form
# was closed by the user.
$timer_reboot.Dispose()
$timer_countdown.Dispose()

# Dispose the form and its controls. Skip, if you want to redisplay the form later.
$oDlg.Dispose()
See Also
PowerShell Printer Driver Installation
PowerShell Device Report
PowerShell Reposition The Windows Taskbar
PowerShell Toast Notifications


PowerShell Reposition The Windows Taskbar

PowerShell Reposition The Windows Taskbar
Example Code > PowerShell Scripts > PowerShell Reposition The Windows Taskbar

The following PowerShell script changes the StuckRects3 registry entry in the Windows Registry in order to reposition the Windows Taskbar. The StuckRects3 registry entry can be found under the following current user registry key:

HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\StuckRects3

Once the registry entry has been changed the code stops the explorer process (which Windows will then automatically restart) and the taskbar is repositioned. Valid values for the StuckRects3 registry entry are 0, 1, 2 and 3 which correspond to left, top, right and bottom respectively.

Please note that this code works perfectly on Windows 10, however does not seem to work when run under Windows 11 22H2. Once I have figured out a way to do reposition the taskbar under Windows 11 I will update the code accordingly.

  • PowerShell Reposition The Windows Taskbar
#----------------------------------------------------------------------------#
# Program Copyright    : Mike Wilcock.
# Program Name         : tb_move.ps1.
#----------------------------------------------------------------------------#
# Program Created      : 27th April 2022.
# Program Code Type    : PowerShell Script (version 5.1.19041.1023).
# Author               : Michael Wilcock, IT Technician.
#----------------------------------------------------------------------------#
# Version              : 1.00
#----------------------------------------------------------------------------#
# Purpose              : Reposition the Windows task bar either top[1], left[0], bottom[3] or right[2].
#----------------------------------------------------------------------------#

clear screen

# Prompt user.
$tb_pos = read-host "Please enter task bar position - Top[1], Left[0], Bottom[3] or Right[2]"

# Very simple validation.
if($tb_pos -eq 0 -or $tb_pos -eq 1 -or $tb_pos -eq 2 -or $tb_pos -eq 3)
{
    # Task bar position registry key.
    $RegistryPath =  'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\StuckRects3'

    # Retreive existing registry value.
    $NewValue = Get-ItemProperty -Path $RegistryPath

    # Set new registry value.
    $NewValue.Settings[12] = $tb_pos

    # Update registry value.
    Set-ItemProperty -Path $RegistryPath -Name "Settings" -Value $NewValue.Settings

    # Stop explorer process.  Will automatically restart.
    Stop-Process -Name "Explorer"
}
# User can't read.
else
{
    clear screen.

    write-host "Invalid input entered - Valid values are: Top[1], Left[0], Bottom[3] or Right[2]"
}
See Also
PowerShell Printer Driver Installation
PowerShell Device Report
PowerShell Automated Reboot
PowerShell Toast Notifications


PowerShell Toast Notifications

PowerShell Toast Notifications
Example Code > PowerShell Scripts > PowerShell Toast Notifications

The following example PowerShell script was created to demonstrate the usage of Toast Notifications using Windows PowerShell. Toast Notifications can be useful to inform users that an event is about to take place on their Windows device.

The code stores its configuration in an associated xml config file called mw_toast.xml which resides in the same folder as the calling script. This can be used to customise any messages and change selected behaviour of the notification that is presented to the user.

The logo and hero images are hard coded as Base64 strings and then written to the device temp folder at runtime. This was done as Windows Toast notifications seem to require any images to reside on disk rather than in memory.

The .ps1 code is presented below along with the XML config file; The code has been tested and works on Windows 10/11.

  • PowerShell Toast Notifications
#----------------------------------------------------------------------------#
# Program Copyright    : Mike Wilcock, 2024.
# Program Name         : mw_toast.ps1.
#----------------------------------------------------------------------------#
# Program Created      : 22nd October 2023.
# Program Code Type    : PowerShell Script (version 5.1.22621.436).
# Author               : Michael Wilcock, IT Technician.
#----------------------------------------------------------------------------#
# Version              : 1.51
#----------------------------------------------------------------------------#
# Purpose              : Display a Toast notification to the user.
#----------------------------------------------------------------------------#
# Notes                : Reads configuration from associated mw_toast.xml file
#                        which resides in the same folder as the script.
#----------------------------------------------------------------------------#

#Current Directory
$CurrentDir = split-path -parent $MyInvocation.MyCommand.Definition

# Read our custom xml config file from disk.
[XML]$xmlfile = Get-Content ($CurrentDir + "/mw_toast.xml")

# Store our xml data in memory for readability.
$toastType = $xmlfile.mw_toast.toast_type
$toastSnooze = $xmlfile.mw_toast.toast_snooze
$toastTitle = $xmlfile.mw_toast.toast_title
$toastText = $xmlfile.mw_toast.toast_text
$toastSentBy = $xmlfile.mw_toast.toast_sentby
$toastGroupTextTitle = $xmlfile.mw_toast.toast_grouptext_title
$toastGroupTextBody = $xmlfile.mw_toast.toast_grouptext_body
$toastGroupTextFooter = $xmlfile.mw_toast.toast_grouptext_footer

# Import logo using Base64. - System maintenance logo
$base64AppLogoString = "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"

# Store the logo image file in the users temp folder.
$toastAppLogo = "$env:TEMP\toastAppLogo.png"
[byte[]]$Bytes = [convert]::FromBase64String($Base64AppLogoString)
[System.IO.File]::WriteAllBytes($toastAppLogo,$Bytes)

# Import hero image using Base64.
$base64HeroImageString = "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"

# Store the hero image file in the users temp folder.
$toastHeroImage = "$env:TEMP\toastHeroImage.png"
[byte[]]$Bytes = [convert]::FromBase64String($Base64HeroImageString)
[System.IO.File]::WriteAllBytes($toastHeroImage,$Bytes)

# Load required namespaces.
$null = [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime]
$null = [Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime]

# Display snooze options.
if($toastSnooze -eq 1)
{
    $snoozeXML = @"
    <input id='snoozeTime' type='selection' defaultInput='15'>
        <selection id='1' content='1 minute'/>
        <selection id='15' content='15 minutes'/>
        <selection id='60' content='1 hour'/>
        <selection id='240' content='4 hours'/>
        <selection id='1440' content='1 day'/>
    </input>

    <action activationType='system' arguments='snooze' hint-inputId='snoozeTime' content=''/>

    <action activationType='system' arguments='dismiss' content=''/>
"@
}
# Do not display snooze options.
else
{
    $snoozeXML = ""
}

# In memory XML document.
$NotificationTemplate = [xml]@"
<toast scenario="$toastType">
    <visual>
        <binding template="ToastGeneric">
            <image placement="appLogoOverride" src="$toastAppLogo"/>
            <image placement="hero" src="$toastHeroImage"/>
            <text id="1">$toastTitle</text>
            <text id="2">$toastText</text>
            <text placement="attribution">$toastSentBy</text>
            <group>
                <subgroup>
                    <text hint-style="subtitle" hint-wrap="true" >$toastGroupTextTitle</text>
                </subgroup>
            </group>
            <group>
                <subgroup>
                    <text hint-style="body" hint-wrap="true" >$toastGroupTextBody</text>
                </subgroup>
            </group>
            <group>
                <subgroup>
                    <text hint-style="body" hint-wrap="true" >$toastGroupTextFooter</text>
                </subgroup>
            </group>
        </binding>
    </visual>
    <actions>
    $snoozeXML
    </actions>
</toast>
"@

#retrieve the appid
$AppID = (Get-StartApps | Where Name -like "Windows PowerShell ISE" | Select -First 1 -ExpandProperty AppID)

# Create required XML.
$NotificationXML = [Windows.Data.XML.DOM.XMLDocument]::New()

# Read our in memory XML document.
$NotificationXML.LoadXml($NotificationTemplate.OuterXml)

# Create notification object.
$Toast = [Windows.UI.Notifications.ToastNotification]::new($NotificationXML)

# Assign the appropriate app id.
$ToastNotifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($AppID)

# Display notification to the user.
$ToastNotifier.Show($Toast)

  • XML Config File
<?xml version="1.0" encoding="utf-8"?>
<mw_toast>
    <!-- alarm, reminder, incomingcall, default. -->
    <!-- Check the Microsoft documentation for a description of toast type behaviour. -->
    <toast_type>reminder</toast_type>

    <!-- 1 displays snooze buttons, anything else disables them -->
    <toast_snooze>1</toast_snooze>

    <!-- Notification title -->
    <toast_title>Essential System Maintenance</toast_title>

    <!-- Notification message to user -->
    <toast_text>31/11/2023 - 5am - 7am</toast_text>

    <!-- Sent by text -->
    <toast_sentby>from: https://www.mikewilcock.com</toast_sentby>

    <!-- Notification 1st grouptext title -->
    <toast_grouptext_title>Scheduled Maintenance - 31/11/2023 at 5am</toast_grouptext_title>

    <!-- Notification 1st grouptext text -->
    <toast_grouptext_text>Scheduled maintenance will be undertaken on our Exchange server on 31/11/2023 at 5am.</toast_grouptext_text>

    <!-- Notification 1st grouptext body -->
    <toast_grouptext_body>Scheduled maintenance will be undertaken on our Exchange server on 31/11/2023 at 5am.  This maintenance is scheduled to last for two hours and during this time our email systems will be unavailable to all users.</toast_grouptext_body>

    <!-- Notification 1st grouptext footer -->
    <toast_grouptext_footer>We apologise in advance for any inconvenience that this may cause.</toast_grouptext_footer>
</mw_toast>
See Also
PowerShell Printer Driver Installation
PowerShell Device Report
PowerShell Automated Reboot
PowerShell Reposition The Windows Taskbar


Report Viewer Options

Report Viewer Options

Toolbar

Toolbar Item | Description
 | Print current report to printer. NOTE: Printing is done via PDF format. Your web browser will require a plug-in to view PDF files.
 | Save the current report to PDF, HTML, MS Word, MS Excel or CSV Data file.
 | Search the current report for a text string.
 | Navigate sequentially through the current report pages or enter a specific page number to jump to.
 | Zoom in or out.
 | Select page view.
 | Back to calling application.
 | Call the Upsilon Report Designer.