We’re automating so much these days, post-Covid. It’s how we survived, and thrived, as the small IT shop we are.

Automation scripting is a cornerstone of effective IT systems management. Whether you’re applying bulk config changes, querying status or config values across your environment, or simply experimenting with new cmdlets, proper logging ensures that you have a clear record of what happene and when it happened. Logging is learning. Logging is life. 😉

One challenge my team experienced was seeing what their scripts were doing. I was surprised at how none of my colleages’ scripts were creating any logging data. So I threw this together a primer to help them out, and decided to also post this info here.

PowerShell makes it straightforward to keep track of your work by leveraging built-in transcript capabilities and custom logging functions. In this post I will briefly review how to use PowerShell’s Start-Transcript feature to capture entire console sessions, and then we’ll explore a custom WriteLog function to document scripted processes more granularly. Here we go!

Why Log?

Before diving into code, it’s worth understanding the importance of logging. Logging provides:
• Traceability: Know exactly which commands were executed and when.
• Accountability: Provide an audit trail for compliance and troubleshooting.
• Debugging Aid: Easily identify what went wrong when a script doesn’t behave as expected.
• Documenting Changes: Keep a historical record of environment modifications for reference.

Especially in enterprise environments, maintaining robust logs can save countless hours of guesswork and improve your operational integrity.

Primer on Start-Transcript

PowerShell’s built-in Start-Transcript and Stop-Transcript cmdlets offer a simple way to record everything that happens in the console. When you run Start-Transcript, PowerShell begins capturing all input and output during your session. When you’re done, Stop-Transcript finalizes the logging and saves the output to the file you specified.

Example:

1
2
3
4
5
6
# Start transcript with a specified output file
Start-Transcript -Path "C:\Logs\MyPSSession.log"

\# ... run various commands here ...

Stop-Transcript

Once stopped, you have a neat record of every command entered and response returned during that session. This approach is perfect for one-off sessions or documenting the execution of a large script that you run interactively.

However, when creating highly automated, unattended scripts, you may want more structured control over what gets logged. That’s where a custom logging function can be invaluable.

1
2
3
4
5
6
7
8
9
Function WriteLog($LogString) {
    ##########################################################################
    ## Writes a timestamped entry to a log file defined by $LogFile variable
    ##########################################################################

    $Stamp = (Get-Date).ToString("yyyy/MM/dd HH:mm:ss")
    $LogMessage = "$Stamp $LogString"
    Add-Content $LogFile -Value $LogMessage
}

How It Works:

  1. Timestamping: The function prefixes each message with a date/time stamp for clear sequencing.
  2. Custom Messages: You have fine control over what gets logged. You can log progress, error messages, or summary statements at key points.
  3. Predefined Log File Variable: By setting $LogFile before you call WriteLog, you control the output location without modifying the function itself each time.

Example Usage:

1
2
3
4
5
6
# Define where you want your log
$LogFile = "C:\Logs\MyScriptActions.log"

WriteLog "Starting configuration tasks..."
\# Run some complex script actions here
WriteLog "Configuration tasks completed successfully."

When you inspect MyScriptActions.log, you’ll see entries like:

1
2
2024/12/09 09:15:00 Starting configuration tasks...
2024/12/09 09:16:10 Configuration tasks completed successfully. 

This selective approach to logging is particularly useful in automation scripts, where every executed step can be logged methodically.

Best Practices for Logging in Your Scripts

  1. Use Consistent, Centralized Logs:
    Keep logs in a known, consistent directory structure. Consider naming logs by date or by the script that generated them for quick reference.
  2. Log Important Steps and Results:
    Don’t flood your logs with every tiny detail—log the big steps, decision points, errors, and completion states. Your logs should tell a story of what your script did, not overwhelm you with noise.
  3. Secure Your Logs:
    Logs can contain sensitive information. Ensure that the directories storing them have appropriate file system permissions. In some cases, consider encrypting or obfuscating sensitive data.
  4. Periodically Review and Rotate Logs:
    Large logs become unmanageable. Consider archiving old logs and rotating them monthly or after a certain size threshold.

Putting It All Together

A robust logging approach might look like this:

1. Begin Transcript for Full Visibility:
Use Start-Transcript at the start of an interactive session or a run-once script to capture a full record.
2. Use WriteLog in Your Script Logic:
Throughout your script, insert calls to WriteLog to highlight key steps, confirm registry values read, and record errors or decisions.
3. Stop Transcript at the End (If Applicable):
When the script is done, run Stop-Transcript to finalize your console-based logging.

By combining these techniques, you get both broad-stroke session logging and fine-grained, contextual logging of critical actions. Whether you’re troubleshooting an issue or proving compliance with your organization’s policies, these logs become invaluable assets.

Effective logging is a fundamental practice for anyone running scripts in a production environment. With PowerShell’s native transcript tools and the flexible WriteLog function I share above, you can create robust and meaningful logs that help you maintain control, compliance, and peace of mind in your automated operations. Have fun building transparent, well-documented workflows in PowerShell!