Finding Rarely Used Computers On Your Network

I support a number of hospitals.  Many of these have very large facilities, where the placement of computers was originally done by a space planner or others trying to make an educated guess about how and where people would be working.  Frequently we find that there are computers which are unused or only rarely used.  Efficient use of the machines requires that you identify these systems and reallocate them to be used where they are needed most.

There are a lot of ways to try to get at this information, for example, working with the information collected by SCCM, but you may not be collecting what is needed.  I wanted to create a multi-threaded script which collected the list of users from AD, pinged the list, then recorded the most recent logon which was not done by the local administrator account.

Get-UnusedComputers.ps1 uses Get-WMIObject to find the local path of each of the user profiles. Because the “lastwritten” attribute is updated when you log on, I sort the files by that date to determine the most recent logon. The results are exported to your desktop in a CSV file.

Script Text

How to Create Single SCCM Bootable Media for both X32 and X64

My friend, Nick Miller, has gone to work with another company, and is involved in a Windows 7 image standardization project.  He recently told me that he had figured out how to have a single bootable USB WinPE disk to create both 32 bit and 64 bit OS images.  Nick is a smart guy, and he had not found instructions for this anywhere else on the web.  I suggested that he be my first Guest Blogger.

For a long time I have wanted to have a single USB bootable media that will install every Windows OS known to man. This has always eluded me because of the differences between architectures. Recently it bothered me to the point of fixing it.

If you have found this article, you probably already know how to build a WINPE 32 bit bootable media, and I will not bore you with the details. Start by creating a directory for the Windows 7 (32 bit) files. Create another directory for the Windows 7 (64 bit) file. For each OS architecture, create a Unattend.xml and place it inside the corresponding directory. It is important to note that both versions must be identical. For example, if you plan on deploying Windows 7 Professional (64 bit) you will need to start the Windows 7 Professional (32 bit) install process.

Here is where it gets mind numbing. Create a new unattend.xml called SpecialUnattend.xml (link has example file) with the WinPE phase of the x86, and the other 6 phases of the x64. Place this in the Windows 7 (64 bit) directory. Be sure to add the “Microsoft-Windows-Setup\Installimage\OSImage\InstallFrom\Path” in the Unattend.xml to point to the Windows 7 (64 bit) wim. IE. “D:\W764\Sources\Install.wim”. And last but not least, at the bottom of the Unattend.xml file (edited with notepad) make sure that the wim is correctly located when booted to the WinPE OS.

To execute, run the following example. “D:\W732\Sources\Setup.exe /InstallFrom:D:\W764\Sources\Install.wim /unattend:D:\W764\SpecialUnattend.xml”
Do not forget that the target drive will need to be wiped with diskpart.
For more information, feel free to reach out to me at NCSHREK on Hotmail.

Thanks Nick.  I know that other SCCM admins will find this to be very helpful.

Get Oldest Windows Event

Get-OldestEvent.ps1 is a PowerShell advanced function which returns the oldest event from a Windows computer event log, and will help you determine the rollover time for an event log by also returning the age of the record as a time span with the time created. Optionally you can return the entire oldest record with the age as an added member. Age is calculated from the time the script collects the information.  You must, of course, have admin rights to query remote event logs. Running locally requires that PowerShell be run elevated. Because it is an advanced function, it must first be loaded with “dot sourcing”.

Example: Get the time created and age for the oldest event in the Security log of this computer.

Example: Get the time created and age for the oldest event in the Application log of this computer.
Get-OldestEvent -eLog Application

Example: Get the oldest event from the Security log on MyServerName, plus Age of event.
Get-OldestEvent -ComputerName MyServerName -eLog security -ReturnAll

Script Text

Passwords for Password Resets

I discovered that my script to generate passwords, RandomPW.vbs, isn’t popular with users because the passwords are random.  I have an even more complicated but unposted PowerShell version with the same issue.

I wanted to create something that was easier for the help desk and users.  Get-TempPW.ps1 is my answer to those objections.  This script is pretty well commented, so I won’t go into details about the code here.   What the script does is get a randomly selected word from the web, capitalizes a random letter within the word, then appends numbers and special characters to the end.  You can set the minimum word length and the number of numbers and special characters with variables within the code.  The default is and eight character word plus a number and special character.  The order of the numbers and special characters are randomized. An example password is “hypeRimmunization4&”.

Script Text


Get the Parent OU for an AD Object

I have mentioned before that the Charlotte PowerShell User group was frequented by Scripting Guy Ed Wilson, and his wife Teresa. I’m sad to say that they have moved away, but am happy that Brian Wilhite has been running the meetings since.  I mentioned to Brian that I had a cool way to get the parent container of an Active Directory object using ADSI:

The string method is, of course faster. But If the parent object isn’t an OU, try the first method. It always works.

Get IE Zone Information

Like most large enterprises, we use a group policies to manage Internet Explorer settings.  We manage the security settings, and we enforce which sites are in Trusted Sites and the other internet zones.  The user cannot change the list, or even view the list.  This creates a problem for troubleshooting when a  user has opened a ticket reporting that the website needs to be added to trusted sites.  IT staff wants to know whether the site is already in the proper zone, and whether the GPO applied properly.

Get-IEZones.ps1 is a PowerShell script which will let you view the IE zone information from the local or a remote computer.  The script uses the WMI accelerator instead of a registry cmdlet to read this data from the registry.   Out-GridView displays the results which can be copied to your clipboard.

Script Text

A Really Recursive Group Enumeration

Get-GroupHierarchy.ps1 gets a fully recursive listing of group membership.  The script is based on a script by the same name posted at  I made a large number of changes to the original code.  This script takes the SamAccountName of a group, such as Domain\MyGroupName, and then gives you all the members of the group.  If a group is a member, it indents and gets the list of members of that group.  Loops throw a warning.

It writes out a text log to your desktop.  I used this code as the basis of a script which I used to fix a problem with a group used in SharePoint which had buried sub groups which were not mail enabled distribution groups.  I’ll post that soon.

A tip of the hat to faithful reader, Bill P.  He was really surprised when I called