QuickTip: Add VMware PowerCLI to PowerShell Console

Although officially the PowerCLI cmdlets are only supported by VMware when running the PowerCLI console it is possible to add the majority of the PowerCLI cmdlets by manually adding the VMware.VimAutomation.Core snapin in your current console:

Add-PSSnapin -Name VMware.VimAutomation.Core

This is particularly useful when running PowerCLI script from the task scheduler as the scripts can just be executed using PowerShell.

As suggested in the comments it is also possible to add all registered VMware PSSnapin’s by runing the following code:

Get-PSSnapin -Registered |
Where-Object {$_.Name -like 'vmware*'} | ForEach-Object {
    Add-PSSnapin -Name $_.Name

Get-ExtensionAttribute – Script in TechNet Script Gallery

Previously I blogged about listing extended file and folder attributes using the Shell.Application object in PowerShell in my List length and bitrate for mp3 files using Shell.Application article. As a result of that post I decided to write a function, Get-ExtensionAttribute, to properly and consistently be able to list extension attributes even when the locale or version of windows is different.

For this purpose I have created a dynamic parameter -ExtensionAttribute which retrieves all extension attributes available on the system it is run which can be selected and displayed. The function takes path names from either pipeline or as a single path or collection of paths.

Get-ExtensionAttribute -FullName C:\Music -ExtensionAttribute Size,Length,Bitrate

Retrieves the Size,Length,Bitrate and FullName of the contents of the C:\Music folder, non recursively

Get-ExtensionAttribute -FullName C:\Music\Song2.mp3,C:\Music\Song.mp3 -ExtensionAttribute Size,Length,Bitrate

Retrieves the Size,Length,Bitrate and FullName of Song.mp3 and Song2.mp3 in the C:\Music folder

Get-ChildItem -Recurse C:\Video | Get-ExtensionAttribute -ExtensionAttribute Size,Length,Bitrate,Totalbitrate

Uses the Get-ChildItem cmdlet to provide input to the Get-ExtensionAttribute function and retrieves selected attributes for the C:\Videos folder recursively

Get-ChildItem -Recurse C:\Music | Select-Object FullName,Length,@{Name = 'Bitrate' ; Expression = { Get-ExtensionAttribute -FullName $_.FullName -ExtensionAttribute Bitrate | Select-Object -ExpandProperty Bitrate } }

Combines the output from Get-ChildItem with the Get-ExtensionAttribute function, selecting the FullName and Length properties from Get-ChildItem with the ExtensionAttribute Bitrate

The complete function is available in the TechNet Script Library. To view this script or to participate in the discussions about this script either comment here or in the TechNet Script Library.

TechNet Script Library
My entries in TechNet Script Gallery

Active Directory Friday: Create new OU

PowerShell can be used to create any number of objects in Active Directory. Today I will demonstrate how to create an organizational unit using both the ActiveDirectory module as well as the [adsi] alternative.

Creating an OU using the New-ADOrganizationalUnit is quite straight forward:

New-ADOrganizationalUnit -Name Departments -Path "ou=Resources,DC=jaapbrasser,DC=com'

Using the [adsi] accelerator to create an OU requires some additional steps. First the parent object has to be selected, in this example the Resources OU in the jaapbrasser.com domain. The next step is create a new object, an organizationalunit in this case, finally the changes are committed to Active Directory by using the SetInfo() method.

$TargetOU = [adsi]'LDAP://ou=Resources,DC=jaapbrasser,DC=com'
$NewOU = $TargetOU.Create('organizationalUnit','ou=Departments')

That is all there is to it, creating an Organizational Unit in Active Directory is quite easy, with or without the ActiveDirectory module.

Update to my TechNet scripts

I upload some of my scripts into the TechNet Script Gallery and there are some lively discussions going on in the questions and answers sections of the scripts. I received feedback and based on that I have improved and updated some of my scripts.

The first script I would like to highlight is the Get-RemoteProgram script that has been built as a replacement for the Win32_Product WMI class. The Win32_Product class is useful but there are some downsides to this, have a look at this article for more information. This prompted me to write an alternative function for this purpose. This function generates a list by querying the registry and returning the installed programs of a local or remote computer. In the latest version of this script. There was an issue with some scenarios when running this script on a 32 bit machine which have been resolved in the latest version.

Get-RemoteProgram -ComputerName Server01 -Property DisplayVersion,VersionMajor 
Will gather the list of programs from Server01 and attempts to retrieve the displayversion and versionmajor subkeys from the registry for each installed program 
'server01','server02' | Get-RemoteProgram -Property Uninstallstring 
Will retrieve the installed programs on server01/02 that are passed on to the function through the pipeline and also retrieves the uninstall string for each program

The second script that received an update is the Get-ScheduledTask the status of the tasks was listed in integers instead of ‘Running’,’Disabled’ or ‘Ready’. This has been updated and there were also scenarios in which the script would list the same task twice which has also been patched.

.\Get-ScheduledTask.ps1 -Computername mycomputer1

This command query mycomputer1 and display a formatted list of all scheduled tasks on  that computer

Another script that I have updated is the Get-OrphanHomeFolder, this script takes a folder path as input and checks if the the folder has a corresponding samaccountname in Active Directory and if that is the case if the account is enabled or disabled. A request came in to also display the enabled users in order to get a full overview. Because of this I added the DisplayAll parameter to the script.

.PARAMETER DisplayAll 
This switch parameters will force the script to also display enabled active directory  accounts, can be used in combination with -FolderSize parameter. 

.\Get-OrphanHomeFolder.ps1 -HomeFolderPath \\Server01\Home -FolderSize -DisplayAll 
Will list all the folders in the \\Server01\Home path. For each of these folders it    will query AD using the foldername, regardless of the AD results folder size will be returned 

The last script I updated is the Compare-ADuserAddGroupGUI this script compares the group membership between two users. The goal of this script is to grant the destination user all the missing memberships when compared to the source user. Any missing memberships will be added by this script and and any additional memberships will be removed. The ComputerName parameter has been added to this script in order to specify which domain controller will be queried for the comparison.

.\Compare-ADuserAddGroupGUI.ps1 testuserabc123 testuserabc456

This command will add&remove from groups testuserabc456 to match groups that testuserabc123 is a member of the user is prompted by user interface to confirm these changes.


Will use GUI to prompt for confirmation 

For a complete list of all my script feel free to browse to my submissions in the TechNet Script Gallery.

TechNet Script Gallery
My entries in TechNet Script Gallery
Get-RemoteProgram Get-ScheduledTask
Get-OrphanHomeFolder Compare-ADuserAddGroupGUI

Quicktip: Get-PSDrive does not filter provider with Where-Object

When attempting to filter the results of Get-PSDrive you might notice that filtering by using Where-Object for the Provider property does not work as expected. For example the following code will not yield the expected results and will in fact not return any drives:

Get-PSDRive | Where-Object {$_.Provider -eq 'FileSystem'}

So let’s have a look at the reason for this, if we take a look at the Provider property of the output and what it contains:

PS C:\Users\JaapBrasser (Get-PSDrive).Provider.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
PS C:\Users\JaapBrasser (Get-PSDrive).Provider | Get-Member -MemberType Property
 TypeName: System.Management.Automation.ProviderInfo
Name MemberType Definition
---- ---------- ----------
Capabilities Property System.Management.Automation.Provider.ProviderCapabil...
Description Property string Description {get;set;}
Drives Property System.Collections.ObjectModel.Collection[System.Management...
HelpFile Property string HelpFile {get;}
Home Property string Home {get;set;}
ImplementingType Property type ImplementingType {get;}
Module Property psmoduleinfo Module {get;}
ModuleName Property string ModuleName {get;}
Name Property string Name {get;}
PSSnapIn Property System.Management.Automation.PSSnapInInfo PSSnapIn {get;}

So in order to correctly use Where-Object here, the comparison should be made to Provider.Name property instead, here is what the successful Where-Object filter script looks like:

Get-PSDRive | Where-Object {$_.Provider.Name -eq 'FileSystem'}

An easier and more correct form of only listing the FileSystem drives on your system would be by using the -PSProvider parameter of the Get-PSDrive cmdlet. By using this we can avoid using the pipeline and simplify the code even further:

Get-PSDRive -PSProvider FileSystem