No breakfast cereals or comic tigers were harmed in the writing of this Blog post.
I have a love for Powershell, it makes my life as a SQL Server tech so much easier when I have to either treat my instances as a herd cattle, rather than separate bovine entities, or have them interact with other technologies as part of a larger task... ie... play with the other farm animals if you will.
Enough of the animal metaphors.
We write Powershell, we run powershell, we swear when our powershell does not do what we would like it to. To this end, we need to log the output somewhere, particularly when our scripts are not going to be run interactively so outputting to the screen becomes pointless.
You may have something like this, a little function to pass information to a file.
Function LogOutput([String]$Message, [string]$LogFile)
{
Add-Content -Path $LogFile $Message
}
LogOutput $(Get-date) C:\Temp\MyLogfile.txt
LogOutput "We need to know about this happening" C:\Temp\MyLogfile.txt
LogOutput "And this!" C:\Temp\MyLogfile.txt
We log, and we log hard.... but hang on, this has a few drawbacks.
What if we have non string types that we want to see, and or logged?
What if we have script that run interactively as well as to a file. The above gives us no output to screen.
Yes, you could use Write-Host, or Write-Verbose in your scripts as well as the above function, but this doesn't cover everything. It's also rather easy to bloat your scripts with logging what's going on, rather than just the code for what's going on.
Transcripts are our friend.
Transcripts in powershell have been around for a while now, and they can make life considerably easier.
To start a transcript log:
Start-Transcript -Path "Path to your log file" -IncludeInvocationHeader
The IncludeInvocationHeader switch just adds some useful info in the log file at the beginning.
And to Stop the transcript
Stop-Transcript
Its that easy.
Par Example
Here's Example with a little bit of error handling in. I like to use a Finally block to ensure my transcript is stopped last.
try {
$Logpath="C:\temp\Logs"
$LogName="TestingTranscripts"
Start-Transcript -Path "$Logpath\$LogName-$(Get-Date -format dd-MM-yyyy- hhmm).log" -IncludeInvocationHeader
Write-Host $(Get-date)
Write-Host "We need to know about this happening"
Write-Host "And this!"
}
catch {$exception = $_.Exception.Message
write-host "Failed transcript Test: $exception" -ForegroundColor Red
}
finally {
Stop-Transcript
}
And our transcript log file.
**********************
Windows PowerShell transcript start
Start time: 20240328173854
Username: LAPTOP3\roded
RunAs User: LAPTOP3\roded
Configuration Name:
Machine: LAPTOP3 (Microsoft Windows NT 10.0.22631.0)
Host Application: C:\Windows\system32\WindowsPowerShell\v1.0\PowerShell_ISE.exe
Process ID: 129684
PSVersion: 5.1.22621.2506
PSEdition: Desktop
PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.22621.2506
BuildVersion: 10.0.22621.2506
CLRVersion: 4.0.30319.42000
WSManStackVersion: 3.0
PSRemotingProtocolVersion: 2.3
SerializationVersion: 1.1.0.1
**********************
Transcript started, output file is C:\temp\Logs\TestingTranscripts-28-03-2024-0538.log
28/03/2024 17:38:54
We need to know about this happening
And this!
**********************
Windows PowerShell transcript end
End time: 20240328173854
**********************
Something other than writing Text...
Lets run a cmdlet to generate some output. In this case, get Get-service to grab the running services on my local client. Contrived example I know.
try {
$Logpath="C:\temp\Logs"
$LogName="TestingTranscripts"
Start-Transcript -Path "$Logpath\$LogName-$(Get-Date -format dd-MM-yyyy-hhmm).log" -IncludeInvocationHeader
Write-Host $(Get-date)
Write-Host "We need to know about this happening"
Write-Host "And this!"
Write-Host "Better do some work... what services are running on my client?"
get-service | Where {$_.Status -eq 'Running'}
}
catch {
$exception = $_.Exception.Message
write-host "Failed transcript Test: $exception" -ForegroundColor Red
}
finally {
Stop-Transcript
}
And this is in our transcript too... (truncated deliberately.)
**********************
Windows PowerShell transcript start
Start time: 20240328172444
Username: XXXXXX\rod
RunAs User: XXXXXX\rod
Configuration Name:
Machine: LAPTOP3 (Microsoft Windows NT 10.0.22631.0)
Host Application: C:\Windows\system32\WindowsPowerShell\v1.0\PowerShell_ISE.exe
Process ID: 129684
PSVersion: 5.1.22621.2506
PSEdition: Desktop
PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.22621.2506
BuildVersion: 10.0.22621.2506
CLRVersion: 4.0.30319.42000
WSManStackVersion: 3.0
PSRemotingProtocolVersion: 2.3
SerializationVersion: 1.1.0.1
**********************
Transcript started, output file is C:\temp\Logs\TestingTranscripts-28-03-2024-0524.log
28/03/2024 17:24:44
We need to know about this happening
And this!
Better do some work... what services are running on my client?
Status Name DisplayName
------ ---- -----------
Running ACCSvc ACC Service
Running AcerARTAIMMXDri... AAADSvc
Running AcerARTAIMMXSer... ARTAimmxService
Running AcerCCAgentSvis Acer Care Center
Running AcerDeviceEnabl... Acer Device Enabling Sevice V2
All from a couple of lines of wrapper code, it allows both logging to a file AND to the screen at the same time. Function output is capture, user input (should you have it), and errors.
Errors you say?
Yes, lets throw a dummy error in, by calling ImnotaFunction, which is a made up function I haven't written...just to produce an error. #Anarchy
Write-Host "Better do some work... what services are running on my client?"
ImnotaFunction
get-service | Where {$_.Status -eq 'Running'} | ft
Transcript file contents, minus the header.
**********************
Transcript started, output file is C:\temp\Logs\TestingTranscripts-28-03-2024-0552.log
28/03/2024 17:52:03
We need to know about this happening
And this!
Better do some work... what services are running on my client?
Failed transcript Test: The term 'ImnotaFunction' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
**********************
Windows PowerShell transcript end
End time: 20240328175203
**********************
Easy life.
Thanks for reading.
Rod.log
Nice 👌
splendid stuff Rodski from the Mr. Blobby Fan Club (Stourbridge).