Lightweight PowerShell Templating Engine




Simple templating engine to expand a given template text containing PowerShell expressions.


The text of the template to do the expansion


Path to template to do the expansion

.PARAMETER Desitination

Destination path to write expansion result.  If not specified, write to output stream.

.PARAMETER PsConfigurationPath                          

Path to file containing PowerShell code. This file could contain variable values to use when evaluating templates


Begin tag for detecting expand expression in template


End tag for detecting expand expression in template


$message=”hello”; .\Expand-Template.ps1 -Text ‘I would like to say [[$message]] to the world’





    [Parameter(Mandatory=$true, ParameterSetName=‘Text’,ValueFromPipeline=$true)]


    [Parameter(Mandatory=$true, ParameterSetName=‘Path’)]




    [string]$BeginTag = ‘[[‘,

    [string]$EndTag = ‘]]’


$BeginTag = [RegEx]::Escape($BeginTag)

$EndTag = [RegEx]::Escape($EndTag)

Write-Verbose ‘Expand-Template’

if ($Path) {

    if (!(Test-Path -Path $path)) { throw “Template-Expand: path `’$path`’ can’t be found”  }

    $Text = Get-Content -Path $path -Raw


if ($PsConfigurationPath) {

    if (!(Test-Path -Path $PsConfigurationPath)) { throw “Template-Expand: psConfigurationPath `’$psConfigurationPath`’ can’t be found” }

    Write-Verbose ” ** Loading PS Configuration file: $PsConfigurationPath

    . $PsConfigurationPath


$pattern = New-Object -Type System.Text.RegularExpressions.Regex `

                      -ArgumentList $BeginTag(.*?)$EndTag,([System.Text.RegularExpressions.RegexOptions]::Singleline)

$matchEvaluatorDelegate =  [System.Text.RegularExpressions.MatchEvaluator] {


           $expression = $match.get_Groups()[1].Value # content between markers

           Write-Verbose ”  ** expanding expression: $expression

           trap { Write-Error “Failed to expand template. Can’t evaluate expression ‘$expression‘. The following error occured: $_; break }

           Invoke-Expression -command $expression | Tee-Object -Variable result

           Write-Verbose ”  ** expanded expression evaluated value:`n$result`n”


$expandedText = $pattern.Replace($text, $matchEvaluatorDelegate)

if (-not $destination){ $expandedText }

else { Set-Content -Path $destination -value $expandedText -encoding $Encoding }


Restart Lenovo Laptop Audio

I have a Lenovo W540 Laptop at work.  Often times, when docking/undocking, the audio stops working or the audio will not play through the headphones or the On Screen Display stops working or the hotkeys don’t do the right thing.  Below is a batch script I assembled that will stop all affected services and re-start them.  It has worked so far, but let me know if you find a case where it does not work.


::Restart audio services and On Screen Display services
net stop AudioSrv
net stop AudioEndpointBuilder
net stop TPHKLOAD
net stop TPHKSVC
net start AudioEndpointBuilder
net start AudioSrv
net start TPHKLOAD
net start TPHKSVC
taskkill /F /FI "IMAGENAME eq Ravcpl*"

Fastest method to get MSMQ message counts

Getting MSMQ message counts can be painfully slow if there are large numbers of messages in a given queue. This PowerShell script is the fastes known way I have found to get the message counts of a queue. The time to get the counts is linear regardless of the number of messages.

Gets all queues' information from the specified computer

Gets all queues' information from the specified computer

Adapted from

Get-MessageQueueInfo.ps1 -MachineName rg-p-blu2 | sort -Property name| ft -Property Name,MessagesInQueue,BytesInQueue -AutoSize

param([string] $MachineName = $env:COMPUTERNAME)
$path = "\\{0}\root\CIMv2" -f $MachineName
$scope = new-object System.Management.ManagementScope ($path)
$QueryString = "SELECT * FROM Win32_PerfFormattedData_msmq_MSMQQueue"
$query = new-object System.Management.ObjectQuery ($queryString)
$searcher = new-object System.Management.ManagementObjectSearcher ($scope, $query)

Kill a process that is listening on a network port

Sometimes, you want to forcibly deploy/install a piece of software that requires a particular service port. This script will find any process that is listening on that port and kill it and if it is a windows service, also disable the service.

param([string]$Port = '80')

$a = netstat -a -n -o

$a -split [environment]::NewLine | foreach {
    $parts = $_.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries) 
    $isMatch = $parts | where {$_ -like "*:$Port*" }
    if($isMatch -and $parts[3] -like 'LISTENING') {
        $proc = Get-Process -Id $parts[4] -ErrorAction SilentlyContinue
        if(-not $proc) {continue}
        Write-Warning "A process was found listening on port $($parts[4])"
        $foundService = (Get-WmiObject Win32_Service -Filter "ProcessId='$($parts[4])'") 
        if($foundService) {
            Write-Host "The process was running as a service, the service will be stopped and disabled ($($foundService.PathName))"

        Write-Host "Killing process $($proc.Name)"
        kill -Id $parts[4] -Force
        $s = Get-Service

Parse output of handle.exe into objects for use with PowerShell

There are times when you need to determine the process that is locking a file.  Using the SysInternals “handle.exe” command line tool, we can search for processes that are using (i.e. locking) a particular file or directory. The code below translates the output of handle.exe into objects that are more friendly for use with PowerShell.

Add-Type -Language CSharp @"
public class Handle{
    public string ProcessName { get;set;}
    public int ProcessId {get;set;}
    public string Type {get;set;}
    public string User {get;set;}
    public string HandleId { get;set;}
    public string Name { get; set;}
    public string AppPoolName {get;set;}

function Get-HandlesAndProcessIds {
<# .Description Converts the text output of the SysInternals tool "handle.exe" into an object array .Example $handles = & handle.exe -a  -u -accepteula "MY_LOCKED_ASSEMBLY.dll" $allHandles = Get-HandlesAndProcessIds -HandleInfo $handles $allHandles --------------------------- ProcessName : dllhost.exe ProcessId   : 6960 Type        : File User        : DOMAIN\user HandleId    : B34 Name        : MY_LOCKED_ASSEMBLY.dll AppPoolName :  #>
    $handle = new-object Handle
    foreach ($line in $handles) {
        if($line -like "*pid:*") {
            $result = $line | Select-String –pattern '^([^ ]*)\s*pid: ([0-9]*)\s*type: ([^ ]*)\s*([^ ]*)\s*(.*?): (.*)'

            $handle.ProcessName =  $result.Matches[0].Groups[1].Value
            $handle.ProcessId = [int]::Parse( $result.Matches[0].Groups[2].Value)
            $handle.Type = $result.Matches[0].Groups[3].Value
            $handle.User = $result.Matches[0].Groups[4].Value
            $handle.HandleId =  $result.Matches[0].Groups[5].Value
            $handle.Name = $result.Matches[0].Groups[6].Value

            if($handle.ProcessName -like "w3wp.exe") {
                $process = Get-AppPoolProcesses | where { $_.ProcessId -eq $handle.ProcessId }
                if($process) {
                    $handle.AppPoolName = $Process.AppPoolName


function Get-AppPoolProcesses {
    Get-WmiObject -NameSpace 'root\WebAdministration' -class 'WorkerProcess' -ComputerName 'LocalHost' |
        select AppPoolName, ProcessId |
            sort -Property AppPoolName


Free Proverb Teleprompter software

I was recently tasked with coming up with a teleprompter solution for my church. One of the requirements was that the software could controlled with a remote control. None of the teleprompter software out there (free or commercial) was able to support custom key bindings. So I decided to create my own. It is pretty full featured, comparable to many of the commercially available ones. It requires the .NET 4.0 framework.

Download Proverb Teleprompter here

Depth of field learnin’s

  1. The higher the F-Stop, the larger the depth of field. See below examples:
  2. As the F-Stop value increases, less light is allowed in. To compensate the shutter speed must be decreased or the ISO must be increased.
  3. With a high F-Stop and low shutter speed, a tripod is a necessity
  4. This works best for slow moving or stationary subjects


Tv (Shutter Speed): 1/20 sec
Av(Aperture Value, F-Stop): 2.8
ISO Speed: 400


Tv (Shutter Speed): 1/10 sec
Av(Aperture Value, F-Stop): 5.6
ISO Speed: 400


Tv (Shutter Speed): 1/6 sec
Av(Aperture Value, F-Stop): 5.6
ISO Speed: 400


Tv (Shutter Speed): 1/3 sec
Av(Aperture Value, F-Stop): 9
ISO Speed: 400


Tv (Shutter Speed): 1/2 sec
Av(Aperture Value, F-Stop): 9
ISO Speed: 400


Tv (Shutter Speed): 1 sec
Av(Aperture Value, F-Stop): 13
ISO Speed: 400


Tv (Shutter Speed): 2 sec
Av(Aperture Value, F-Stop): 18
ISO Speed: 400


Tv (Shutter Speed): 3.2 sec
Av(Aperture Value, F-Stop): 25
ISO Speed: 400


Tv (Shutter Speed): 4 sec
Av(Aperture Value, F-Stop): 25
ISO Speed: 400


Tv (Shutter Speed): 8 sec
Av(Aperture Value, F-Stop): 32
ISO Speed: 400