Tag Archives: windows

Get the Windows Install Date of a remote computer with PowerShell

A quick script that came up in response to a situation where I wanted to know the date a workstation on the network was last built without visiting the machine or interrupting the currently logged on user. PowerShell to the rescue!

The WMI property “InstallDate” comes into play here.

(Get-WmiObject Win32_OperatingSystem).InstallDate

Returns a date: “20180717202039.000000+060” for my workstation. The Get-WmiObject cmdlet can again be leveraged to make this into a more usable PowerShell DateTime object:

(Get-WmiObject Win32_OperatingSystem).ConvertToDateTime( (Get-WmiObject Win32_OperatingSystem).InstallDate )

Which returns 17 July 2018 20:20:39.

Get-WmiObject can also be used on a remote computer, this example would return the date that the computer called WS12000 was built.

(Get-WmiObject win32_OperatingSystem –ComputerName “WS12000”).InstallDate

I’ve taken this work and expanded it into a PowerShell function (available on GitHub). This function “Get-BuildDate” takes one or more computer names and returns a table of build dates and, because it’s handy, the number of days that have passed since that date.

Some example usage would be:

Return the installation date of workstation 40200:

Get-BuildDate  -ComputerNames "WS40200"

Computer BuildDate           DaysSinceLastBuild
-------- ---------           ------------------
WS40200  17/07/2018 20:20:39                 55

Return the installation date of workstations WS40200 and WS46000:

Get-BuildDate ("WS40200","WS46000")

or alternatively using pipeline input:

("WS40200","WS46000") | Get-BuildDate

Finally, return a table of the last build dates for the sequentially numbered computers called WS12300, WS12301, WS12302…. right through to WS12399:

$Computers=((12300..12399) | ForEach-Object{ "WS$_"}) | Get-BuildDate

The script (and any future refinements) is available here: https://github.com/isjwuk/powershell-general/blob/master/Get-BuildDate.ps1

PowerShell Snippet – Find Windows 2008 VMs before EOL

Support for Windows Server 2008 and 2008 R2 ends in January 2020– just two years from the date of this post. Four years ago I put up a script to find XP and 2003 VMs, and I’ve modified this to search a vSphere environment for powered on VMs running Server 2008 as a Guest OS:

Get-VM |
 Where {$_.PowerState -eq "PoweredOn" -and
 ($_.Guest -like "*Server 2008*")} |
 get-VMGuest |
 select VmName, OSFullName

VmName    OSFullName
------    ----------
MyVM1     Microsoft Windows Server 2008 R2 (64-bit)
MyVM2     Microsoft Windows Server 2008 R2 (64-bit)
MyVM3     Microsoft Windows Server 2008 (64-bit)
MyVM4     Microsoft Windows Server 2008 R2 (64-bit)

Checking Encryption Status of Remote Windows Computers

Using the manage-bde command you can check the Bitlocker encryption status on both the local Windows computer but also remote devices on the local area network. For example, to check the encryption status of the C: drive on the computer “WS12345” the following command could be used

manage-bde -status -computername WS12345 C:

and the results might look something like this:

BitLocker Drive Encryption: Configuration Tool version 10.0.14393
Copyright (C) 2013 Microsoft Corporation. All rights reserved.

Computer Name: WS12345

Volume C: [OSDisk]
[OS Volume]

Size:                 237.99 GB
BitLocker Version:    2.0
Conversion Status:    Fully Encrypted
Percentage Encrypted: 100.0%
Encryption Method:    AES 256 with Diffuser
Protection Status:    Protection On
Lock Status:          Unlocked
Identification Field: None
Key Protectors:
    Numerical Password
    TPM

Expanding on this we could wrap some PowerShell around the command and read in a list of hostnames from a text file and report on the encryption status of each.

Firstly we need to format the output of manage-bde to only show us the value of the “Conversion Status” field- PowerShell’s string manupulation can come in handy here- we can locate the “Conversion Status” line, check that it is present (if the computer is not on the network, or access is denied the manage-bde command will not return a status), and then trim back the line so we only have the value of the field. For example:

#Check the Encryption Status of the C: drive, filter to the Conversion Status line
$EncryptionStatus=(manage-bde -status -computername "$hostname" C: | where {$_ -match 'Conversion Status'})
#Check a status was returned.
if ($EncryptionStatus)
{
  #Status was returned, tidy up the formatting
  $EncryptionStatus=$EncryptionStatus.Split(":")[1].trim()
}
else
{
  #Status was not returned. Explain why in the output
  $EncryptionStatus="Not Found On Network (or access denied)"
}

Once this is working, it’s just a case of reading in the text file using the get-content cmdlet and outputting a result. The full code (Get-EncryptionStatus.ps1) I used is available for downloading and/or improving on GitHub here- https://github.com/isjwuk/get-encryptionstatus

Microsoft Future Decoded Banner

Microsoft Future Decoded 2015

November 2015 saw the return of Microsoft’s Future Decoded event to the ExCel Center in London. I didn’t make it last year (it was a week after TechEd Europe and I was all Microsofted out!) so I’ve been looking forward to the Tech Day of this event since the registration notice back in May. This is my summary of the day. Continue reading

Using PowerShell to check a folder copied

I’ve had a number of times over the years where I’ve needed to guarantee to someone that their data is unchanged as a result of an IT action- when we’ve migrated servers, replaced disks etc. The detailed, in depth, article by Jeff Hicks over at Petri.com “Hashing it Out in PowerShell: Using Get-FileHash” showed me that a file-hash comparison was possible in Windows without a third party piece of software.

So, inspired by that, here’s a short bit of PowerShell script to check two folders are the same- the folder had been previously copied with a ROBOCOPY /MIR command. The script makes two lists of hashes, one for each folder, and compares the two.

$SourceHash = Get-ChildItem -recurse X:\Folder\ | Get-FileHash
$TargetHash = Get-ChildItem -recurse Y:\Folder\ | Get-FileHash
Compare-Object $SourceHash.Hash $TargetHash.Hash

Or if you want to squish it to one line

Compare-Object (Get-ChildItem -recurse X:\Folder\ | Get-FileHash).Hash (Get-ChildItem -recurse Y:\Folder\ | Get-FileHash).Hash

If the two folders are the same (i.e. the Robocopy worked as it should) then no output is displayed. To check it’s working, adding -includeequal to the end of the Compare-Object line will also output a line for identical files. For example

Compare-Object (Get-ChildItem -recurse X:\Folder\ | Get-FileHash).Hash (Get-ChildItem -recurse Y:\Folder\ | Get-FileHash).Hash -includeequal

This should hopefully be a quick and simple solution for others, check out Jeff Hicks’ article or type get-help get-filehash in a PowerShell window for more in-depth information.