PowerShell for Windows Admins

February 24, 2017  4:25 AM


Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Wanted one nice kind PowerShell community member to buy the last lonely ticket for the 2017 PowerShell and DevOps Summit.

That’s right we have one place left. And its definitely the last. if you want it – better hurry.

February 16, 2017  2:24 PM

Get-ADUser doesn’t display all properties

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Active Directory, Powershell

Microsoft’s Active Directory cmdlets have some issues. One of the ones that catches everyone when they start using them is that Get-ADUser doesn’t display all properties.

A default call to Get-ADUser displays a subset of the available properties of the user object:

DistinguishedName : CN=FOX Fred,OU=UserAccounts,DC=Manticore,DC=org
Enabled           : True
GivenName         :
Name              : FOX Fred
ObjectClass       : user
ObjectGUID        : db5a3975-980d-4749-b9c0-48aff9217b2a
SamAccountName    : foxfred
SID               : S-1-5-21-759617655-3516038109-1479587680-1314
Surname           :
UserPrincipalName : FredFox@manticore.org

Even if the properties are empty – such as Givenname and Surname – the property name is displayed. So, how do you get the properties that aren’t part of the default list?

There’s the brute force approach:

PS> Get-ADUser -Identity foxfred -Properties *

AccountExpirationDate                :
accountExpires                       : 9223372036854775807
AccountLockoutTime                   :
AccountNotDelegated                  : False
AllowReversiblePasswordEncryption    : False
AuthenticationPolicy                 : {}
AuthenticationPolicySilo             : {}
BadLogonCount                        : 0
badPasswordTime                      : 0
badPwdCount                          : 0
CannotChangePassword                 : False
CanonicalName                        : Manticore.org/UserAccounts/FOX Fred
Certificates                         : {}
City                                 :
CN                                   : FOX Fred
codePage                             : 0
Company                              :
CompoundIdentitySupported            : {}
Country                              :
countryCode                          : 0
Created                              : 17/11/2016 14:07:13
createTimeStamp                      : 17/11/2016 14:07:13
Deleted                              :
Department                           :
Description                          :
DisplayName                          :
DistinguishedName                    : CN=FOX Fred,OU=UserAccounts,DC=Manticore,DC=org
Division                             :
DoesNotRequirePreAuth                : False
dSCorePropagationData                : {01/01/1601 00:00:00}
EmailAddress                         :
EmployeeID                           :
EmployeeNumber                       :
Enabled                              : True
Fax                                  :
GivenName                            :
HomeDirectory                        :
HomedirRequired                      : False
HomeDrive                            :
HomePage                             :
HomePhone                            :
Initials                             :
instanceType                         : 4
isDeleted                            :
KerberosEncryptionType               : {}
LastBadPasswordAttempt               :
LastKnownParent                      :
lastLogoff                           : 0
lastLogon                            : 0
LastLogonDate                        :
LockedOut                            : False
logonCount                           : 0
LogonWorkstations                    :
Manager                              :
MemberOf                             : {}
MNSLogonAccount                      : False
MobilePhone                          :
Modified                             : 18/11/2016 11:03:02
modifyTimeStamp                      : 18/11/2016 11:03:02
msDS-User-Account-Control-Computed   : 8388608
Name                                 : FOX Fred
nTSecurityDescriptor                 : System.DirectoryServices.ActiveDirectorySecurity
ObjectCategory                       : CN=Person,CN=Schema,CN=Configuration,DC=Manticore,DC=org
ObjectClass                          : user
ObjectGUID                           : db5a3975-980d-4749-b9c0-48aff9217b2a
objectSid                            : S-1-5-21-759617655-3516038109-1479587680-1314
Office                               :
OfficePhone                          :
Organization                         :
OtherName                            :
PasswordExpired                      : True
PasswordLastSet                      : 17/11/2016 14:07:13
PasswordNeverExpires                 : False
PasswordNotRequired                  : False
POBox                                :
PostalCode                           :
PrimaryGroup                         : CN=Domain Users,CN=Users,DC=Manticore,DC=org
primaryGroupID                       : 513
PrincipalsAllowedToDelegateToAccount : {}
ProfilePath                          :
ProtectedFromAccidentalDeletion      : False
pwdLastSet                           : 131238652330182673
SamAccountName                       : foxfred
sAMAccountType                       : 805306368
ScriptPath                           :
sDRightsEffective                    : 15
ServicePrincipalNames                : {}
SID                                  : S-1-5-21-759617655-3516038109-1479587680-1314
SIDHistory                           : {}
SmartcardLogonRequired               : False
State                                :
StreetAddress                        :
Surname                              :
Title                                :
TrustedForDelegation                 : False
TrustedToAuthForDelegation           : False
UseDESKeyOnly                        : False
userAccountControl                   : 512
userCertificate                      : {}
UserPrincipalName                    : FredFox@manticore.org
uSNChanged                           : 78123
uSNCreated                           : 62259
whenChanged                          : 18/11/2016 11:03:02
whenCreated                          : 17/11/2016 14:07:13

Using –properties * returns ALL of the properties of a user. That’s OK if you’re looking at one, or a few users, but becomes a very expensive operation if you’re looking at thousands of user objects.

A more elegant approach is to specify the properties you want:

PS> Get-ADUser -Identity foxfred -Properties EmailAddress, LockedOut, ProtectedFromAccidentalDeletion, whenCreated

DistinguishedName               : CN=FOX Fred,OU=UserAccounts,DC=Manticore,DC=org
EmailAddress                    :
Enabled                         : True
GivenName                       :
LockedOut                       : False
Name                            : FOX Fred
ObjectClass                     : user
ObjectGUID                      : db5a3975-980d-4749-b9c0-48aff9217b2a
ProtectedFromAccidentalDeletion : False
SamAccountName                  : foxfred
SID                             : S-1-5-21-759617655-3516038109-1479587680-1314
Surname                         :
UserPrincipalName               : FredFox@manticore.org
whenCreated                     : 17/11/2016 14:07:13

You get the properties you specified and the default properties.

So, while Get-ADUser doesn’t display all properties you can overcome this by using the –properties parameter with a * for all properties or a list of the properties you want in addition to the defaults.

February 11, 2017  8:57 AM

Filtering of Objects and Properties

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Saw a post on the forum today that suggests people are still confused about how to perform filtering of objects and properties in PowerShell.

As with so much in PowerShell explanations are always better with examples.

Let’s start with the physical disks in a computer:

PS> Get-PhysicalDisk

FriendlyName               SerialNumber    CanPool OperationalStatus HealthStatus Usage            Size
------------               ------------    ------- ----------------- ------------ -----            ----
Toshiba USB 2.0 Ext. HDD   WD-WCAMR3209671 False   OK                Healthy      Auto-Select 298.09 GB
ST916082 1A                DEF10E8D9B36    False   OK                Healthy      Auto-Select 149.05 GB
Samsung SSD 840 PRO Series S1AXNSAF329511V False   OK                Healthy      Auto-Select 476.94 GB

If you want to objects that match a specific criteria – for instance disk is larger than 300GB:

PS> Get-PhysicalDisk | Where-Object Size -gt 300GB

FriendlyName               SerialNumber    CanPool OperationalStatus HealthStatus Usage            Size
------------               ------------    ------- ----------------- ------------ -----            ----
Samsung SSD 840 PRO Series S1AXNSAF329511V False   OK                Healthy      Auto-Select 476.94 GB

Where-Object is your friend.

What you’re actually doing – though very few people actually write it like this – is

Get-PhysicalDisk | Where-Object -Property Size -GT -Value 300GB

The help file for Where-Object lists the possible operators.

You can also show the original style syntax

Get-PhysicalDisk | Where-Object -FilterScript {$_.Size -gt 300GB}

Normal usage is to not write the –FilterScript parameter so it becomes

Get-PhysicalDisk | Where-Object {$_.Size -gt 300GB}

$_ represents the object currently on the pipeline. If you need to use multiply conditions in your filter you’ll need to use the older style syntax.

So far you’ve seen how reduce the number of objects on the pipeline. Where-Object filters out those that don’t match the given criteria.

If you want to reduce the number of properties that the objects on the pipeline possess you’ll need to use Select-Object

PS> Get-PhysicalDisk | Select-Object -Property FriendlyName, HealthStatus, Size

FriendlyName               HealthStatus         Size
------------               ------------         ----
Toshiba USB 2.0 Ext. HDD   Healthy      320072933376
ST916082 1A                Healthy      160041885696
Samsung SSD 840 PRO Series Healthy      512110190592

More commonly written as

Get-PhysicalDisk | Select FriendlyName, HealthStatus, Size

PowerShell best practice is always to use the full cmdlet and parameter names in your scripts. The *-Object cmdlets and in particular Where-Object, Sort-Object and Select-Object are often abbreviated to Where, Sort and Select and the parameters only used where necessary.  This was the way I was advised to use them by Jeffrey Snover – who invented PowerShell –  when I wrote PowerShell in Practice. Good enough for me.



February 9, 2017  10:56 AM

PowerShell Summit 2017 – – more seats available

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

After selling out in record time we’ve managed to squeeze a few more seats in after discussion with the conference centre.

Those seats are live now.

They are very definitely, the absolute last set of seats we’ll be able to add this year.

First come – First served. When they’re gone – they’re gone

February 9, 2017  5:43 AM

POwerShell Summit 2017 – sold out

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

We sold the last seat for the 2017 Summit – https://eventloom.com/event/home/summit2017 yesterday.

If, and its a very big if, more seats become available we’ll notify you though the event web site and on powershell.org

February 1, 2017  2:14 PM

PowerShell on Linux installs

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Linux, Powershell

PowerShell on Linux installs are now easier as you can use the Linux package management tools to download and update PowerShell Core 6.0

Details from https://blogs.msdn.microsoft.com/powershell/2017/02/01/installing-latest-powershell-core-6-0-release-on-linux-just-got-easier/

January 31, 2017  2:17 PM

Append data to a file

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

A question on the forums – the user wanted to append data to a file. This is a common scenario when you’re creating a log file.

There’s 2 easy ways to do this.

Lets create a couple of variables with multi-line data

PS> $data = @’
>> This is
>> multiline data
>> ‘@
PS> $data
This is
multiline data

PS> $data2 = @’
>> This is
>> more multiline
>> data
>> ‘@
PS> $data2
This is
more multiline

First you could use Out-File

PS> Out-File -FilePath of.txt -InputObject $data
PS> Out-File -FilePath of.txt -InputObject $data2 -Append
PS> Get-Content -Path of.txt
This is
multiline data

This is
more multiline

First time you call Out-File you don’t have to use –Appemd but you can. On subsequent calls use -Append to add the data – if you don’t the file will be overwritten with the new data.

Second option is one you don’t see so much – Add-Content. In earlier versions of PowerShell this was your only option

PS> Add-Content -Path ac.txt -Value $data
PS> Add-Content -Path ac.txt -Value $data2
PS> Get-Content -Path ac.txt
This is
multiline data

This is
more multiline

If the file doesn’t exist Add-Content will create it.

Two ways to append data to a file

January 31, 2017  11:22 AM

Powershell versions

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

There are two common questions around PowerShell versions.

Firstly, what version of PowerShell am I running?

The easiest way to answer this is to open a PowerShell console and use the built in $PSVersionTable variable

PS> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.15019.1000
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.15019.1000
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3

$PSVersionTable is a hash table so the order of the results may be different for you

The data above is from the latest Windows 10 Insider Preview build (at the time of writing)

if you have Windows 10 with the Anniversary update you’ll see something like this

PS> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.14393.693
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.14393.693
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3

The PSVersion, BuildVersion and CLRVersion (>NET version) are slightly different. Note that you’ll get the same results in the PowerShell console or ISE.

If you’ve not looked at $PSVersionTable – the Edition entry may be new. That will read desktop for PowerShell 5.1 that is installed on full Windows. If you look at $PSVersionTable on Nano server you’ll see the Edition is Core. You’ll also see the Edition set to core on the PowerShell 6.0 alpha editions for Linux etc.

The other place that versions come into play are the extensions applied to powershell scripts, modules and module manifests. These are .ps1, .psm1, .psd1 respectively. Back in the days of PowerShell 1.0 there was a suggestion that future versions of PowerShell may utilise .ps2, .ps3 etc. This never came about and its probable that .p*1 extensions will keep being used.

Hope this helps clear any confusion on PowerShell versions

January 29, 2017  9:50 AM

Finding DNS static records

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
CIM, DNS, Powershell

An interesting question from the forums about finding DNS static records

You can view the records in a DNS zone

Get-CimInstance -Namespace root\MicrosoftDNS -ClassName MicrosoftDNs_Atype -ComputerName W16DC01  -Filter “DomainName = ‘manticore.org'” |
select OwnerName, Timestamp, IPAddress

but how do you know which are static records.

There isn’t an obvious way to do it but if you dig into the records (hint create a static record and look at the differences) you’ll see that static records have a timestamp of 0

So to see just the static records

Get-CimInstance -Namespace root\MicrosoftDNS -ClassName MicrosoftDNs_Atype -ComputerName W16DC01 -Filter “DomainName = ‘manticore.org’ AND Timestamp = 0” |
select OwnerName, Timestamp, IPAddress

Rather than using the CIM class directly it’s simpler to use the cmdlets from the DNSserver module – install the remote admin tools to get access.

To view the A type records

Get-DnsServerResourceRecord -ComputerName W16DC01 -ZoneName ‘manticore.org’ -RRType A

To view the static records only

Get-DnsServerResourceRecord -ComputerName W16DC01 -ZoneName ‘manticore.org’ -RRType A |
where {-not $_.TimeStamp}

Notice that you’re checking for the absence of a timestamp

January 29, 2017  8:23 AM

Using Hyper-V

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

When you think of using Hyper-V most people think of virtualising their infrastructure – big servers running 10s, 100s or even 1000s of virtual machines.

There is another reason for using Hyper-V

You can use Hyper-V to create a VM so you can install an application that may conflict with you standard workstation – as an example you may need access to a component of an older version of Office for instance Infopath 2010 but you don’t want that application to conflict with your installation of the latest and greatest version of Office.

The Windows client operating system has the ability to install Hyper-V since Windows 8. So if you’re running Windows 8, Windows 8.1 or Windows 10 AND your machine is capable of supporting Hyper-V:

– Windows Enterprise, Professional or Educational

– 64-bit processor with SLAT

– CPU support for VM monitor mode extension

– Minimum of 4GB of memory

Install Hyper-V

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V –All

Create a virtual switch and create your VMs

See https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/quick-start/enable-hyper-v and subsequent links

Better still get a copy of Learn Hyper-V in a Month of Lunches


Forgot Password

No problem! Submit your e-mail address below. We'll send you an e-mail containing your password.

Your password has been sent to: