Powershell Workstation/Server Audit script update

Following some great comments from Jeffrey Snover and other PowerShell Guru’s on the previous version of my Audit script I have now re-written the script to incompas some of the superior wisdom emparted upon me.

So what does this mean ?

  • I am now using a string to store all the html code as I build it up through the script as blogged by Jeffrey here
  • I am now using $env:computername rather than localhost – Thanks to Jeffrey Hicks, your right it does look better !
  • I am breaking from my switch statements correctly (schoolboy error on my part)
  • I am now using a terminating error where needed
  • I have changed the keyboard map switch statement into a hashtable
  • The code is now over 100 lines shorter and now fits into http://poshcode.org (Cool)

The Bad News

Jeffreys parting comment was:

It would be a lot faster as well.

Again – awesome script!
Jeffrey Snover [MSFT]

Unfortunatly although I will agree with the awesome script part when I ran some tests to see if the script ran faster, which I was convinced it would, mainly due to only writing the content out at the end rather than one line at a time I had some supprising results:

PS C:\Audit> measure-command {& “C:\Audit\OldAudit.ps1”}

Days : 0
Hours : 0
Minutes : 0
Seconds : 14
Milliseconds : 57
Ticks : 140570477
TotalDays : 0.000162697311342593
TotalHours : 0.00390473547222222
TotalMinutes : 0.234284128333333
TotalSeconds : 14.0570477
TotalMilliseconds : 14057.0477

PS C:\Audit> measure-command {& “C:\Audit\Audit.ps1”}

Days : 0
Hours : 0
Minutes : 0
Seconds : 18
Milliseconds : 480
Ticks : 184803922
TotalDays : 0.000213893428240741
TotalHours : 0.00513344227777778
TotalMinutes : 0.308006536666667
TotalSeconds : 18.4803922
TotalMilliseconds : 18480.3922

Can anyone shed any light on this as frankly I’m baffled ?!

Thanks again for all the comments on the script and the new version is below:

A sample of the output can be viewed here (best viewed in Internet Explorer):

21 thoughts on “Powershell Workstation/Server Audit script update

  1. smurteira

    Hi Alan, is there a way to change the even log section of the script so that the message field takes up at least 50% of the space, otherwise it crunches things too much and makes the report way too long. Thanks

  2. Alan Post author

    You would need to adjust it and remove the foreach which puts each server in a sperate file, the custom HTML functions will need to be adjusted to be put in the correct place too. Maybe just add an index page once it has completed which links to each file – that may be easier πŸ˜‰

  3. Hector

    Hi still a great script to use πŸ™‚ tell me how can it be modified to generate a single report for a list of servers rather than one per server?

  4. Virtu-Al

    On Windows 2003 the Win32_Product class isn’t installed by default.
    You can install it with Add/Remove Windows Component. Look for the
    “WMI Windows Installer Provider” component under “Management and
    Monitoring Tools”.

  5. Arnold

    When I run the script I get the following errors:

    Using Audit list: servers.txt
    Collating Detail for ct501
    ..Hotfix Information
    ..Logical Disks
    ..Network Configuration
    ..Local Shares
    ..Regional Options
    ..Event Log Settings
    ..Event Log Errors
    ..Event Log Warnings
    Poging door nul te delen.
    At E:\__USBdrive\Documents\Scripts\QueryInstalledSoftware\Audit.ps1:413 char:65
    + $percFreespace=[math]::round(((($objDisk.FreeSpace /1048576)/( <<<< $objDisk.Size /1048676)) * 100),0)
    ..Installed Software
    Get-WmiObject : Ongeldige klasse
    At E:\__USBdrive\Documents\Scripts\QueryInstalledSoftware\Audit.ps1:507 char:27
    + $colApps = get-wmiobject <<<< -ComputerName $Target Win32_Product | select Name,Version,Vendor,InstallDate

    I have tried it to run on several servers and get always the same results.
    The software section in the htm file is empty.

    Can you help me to find a solution for this?

  6. baz

    Putting in “if ( !$ComputerSystem ){” as seen below will skip computers that are not switched/broken/don’t exsist/etc

    Foreach ($Target in $Targets){
    Write-Output “Collating Detail for $Target”
    $ComputerSystem = Get-WmiObject -computername $Target Win32_ComputerSystem
    if ( !$ComputerSystem ){

  7. Andy

    Wonder if I have been asleep .. saw the original ..
    rediscovered the updated .. ‘blown away’ once again.
    Most elegant, thanx.

  8. Aaron

    I saw that, but it only works for Exchange 2003, we run 2007. I will let you know if i run into any problems.

  9. Virtu-Al

    I have run it with both versions of powershell and all is fine so far, strange !

    Let me know if you need a hand amending it but it should be quite straight forward, someone has already changed it to make it an Exchange audit script which they run on a daily basis here http://www.virtu-al.net/2009/05/07/exchange-audit/

    Again, if you need a help with the amendments let me know.


  10. Aaron

    I tried running it from another machine, and even though it took a long time to run, it didn’t error out, and i LOVE the format. I would love to figure out how to get this to run on a daily basis with the General Details, and the Event Log area (filtered for the last couple of days). This would make daily server checks go much quicker (if they happen at all.) There is another script that someone put together in VBS, that i may take a crack at converting to PowerShell.

    I wonder if the problems i had running it are due to the fact that i have don’t have PowerShell V1 installed, i have V2 CTP3.

    Hope all is well


  11. Aaron

    Same thing happened when i tried to scan another system. Here are the messages thrown this time. THe last one looks similar, but the one before it puzzles me too.

    ..Regional Options
    ..Event Log Settings
    ..Event Log Errors
    Shutting down
    At :line:151 char:33
    + $colLoggedEvents = Get-WmiObject <<<='” + $WmidtQueryDT + “‘”)

    ..Event Log Warnings
    ..Installed Software
    The ‘+=’ operator failed: Exception of type ‘System.OutOfMemoryException’ was thrown..
    At :line:797 char:11
    + $Report+= <<<< ” ”

    Off to build another server for a bit.


  12. Virtu-Al

    Thats a new one ! Have you tried auditing another machine, doing a quick google search it looks like System.OutOfMemoryException is a memory issue with the .net profiler.

  13. Aaron

    This looks like it is shaping up to be a great script. I tried to run it today and i got the following messages. The last couple of lines don’t make sense to me, and i don’t see any files being created. let me know what i should do.

    No list specified, using APERRAULT1973
    Collating Detail for APERRAULT1973
    ..Hotfix Information
    ..Logical Disks
    ..Network Configuration
    ..Local Shares
    ..Regional Options
    ..Event Log Settings
    ..Event Log Errors
    ..Event Log Warnings
    ..Installed Software
    Generic failure
    At :line:507 char:26
    + $colApps = get-wmiobject <<<< -ComputerName $Target Win32_Product | select Name,Version,Vendor,InstallDate

    The ‘+=’ operator failed: Exception of type ‘System.OutOfMemoryException’ was thrown..
    At :line:650 char:13
    + $Report+= <<<< ” $($objService.State)”

  14. Virtu-Al


    Thanks for your comments, I have recently adjusted my own version to use a html output that works in all browsers correctly, it also functionises everything to make it look easier to read, if I get a chance I will make the final changes and upload it soon. Your Exchange script sounds great, I would love to give it a go, please can you email it to me… ajw.renouf at googlemail.com

    Thanks for reading my blog.


  15. Jean


    This is a truly excellent piece of work. I have adapted it to use on Exchange servers, to audit certain Exchange specific items. I can send you a copy if you like. The fact that it uses WMI makes it Exchange 2003 only πŸ™ for now, but I have started work on an Exchange 2007 version.

    There is one small little item though on line 64 the gmwi doesn’t point to the $Target, the line should read:

    $colQuickFixes = Get-WmiObject $Target Win32_QuickFixEngineering

    Once again thanks for an awesome script!


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.