PowerShell for Windows Admins


July 5, 2015  8:09 AM

Scripting Guy new series

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

Ed Wilson, the Scripting Guy, is starting a new series of posts on writing PowerShell scripts – he’ll also cover what to script, when to script and when to work interactively.

First post is here http://blogs.technet.com/b/heyscriptingguy/archive/2015/07/05/weekend-scripter-when-to-write-a-powershell-script.aspx

Strongly recommend this series to all PowerShell users

July 4, 2015  5:21 AM

Scripting Games July 2015 puzzle

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

Head over to http://powershell.org/wp/2015/07/04/2015-july-scripting-games-puzzle/ for our inaugural Scripting Games puzzle.

I’ll publish a solution at the end of the month


July 2, 2015  1:20 PM

Processing NULL AD values

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

Back in this post https://richardspowershellblog.wordpress.com/2012/12/09/bulk-modifications-using-set-aduser/

I showed how to perform a bulk change to a number of AD accounts using a CSV file to input the data

I was recently asked what happens if one of the input values is null.

£> Set-ADUser -Identity fgreen  -Division ‘Test’
£> Get-ADUser -Identity fgreen  -Properties Division
DistinguishedName : CN=Fred Green,OU=Testing,DC=Manticore,DC=org
Division          : Test
Enabled           : False
GivenName         : Fred
Name              : Fred Green
ObjectClass       : user
ObjectGUID        : 8cf64233-9a87-43dc-8ce1-4f26bf78e12d
SamAccountName    : fgreen
SID               : S-1-5-21-195014076-723736408-1406369008-1112
Surname           : Green
UserPrincipalName : fgreen@Manticore.org

£> $div = $null
£> Set-ADUser -Identity fgreen  -Division $div
£> Get-ADUser -Identity fgreen  -Properties Division

DistinguishedName : CN=Fred Green,OU=Testing,DC=Manticore,DC=org
Division          :
Enabled           : False
GivenName         : Fred
Name              : Fred Green
ObjectClass       : user
ObjectGUID        : 8cf64233-9a87-43dc-8ce1-4f26bf78e12d
SamAccountName    : fgreen
SID               : S-1-5-21-195014076-723736408-1406369008-1112
Surname           : Green
UserPrincipalName : fgreen@Manticore.org

 

If the value is already set – a NULL value will effectively clear it

If a value isn’t set – nothing happens

£> $div = $null
£> Get-ADUser -Identity dbrown  -Properties Division
DistinguishedName : CN=Dave Brown,OU=Testing,DC=Manticore,DC=org
Division          :
Enabled           : False
GivenName         : Dave
Name              : Dave Brown
ObjectClass       : user
ObjectGUID        : 346649f7-6f69-4f20-985f-b2b08674b942
SamAccountName    : dbrown
SID               : S-1-5-21-195014076-723736408-1406369008-1109
Surname           : Brown
UserPrincipalName : dbrown@Manticore.org

 

£> Set-ADUser -Identity dbrown  -Division $div
£> Get-ADUser -Identity dbrown  -Properties Division
DistinguishedName : CN=Dave Brown,OU=Testing,DC=Manticore,DC=org
Division          :
Enabled           : False
GivenName         : Dave
Name              : Dave Brown
ObjectClass       : user
ObjectGUID        : 346649f7-6f69-4f20-985f-b2b08674b942
SamAccountName    : dbrown
SID               : S-1-5-21-195014076-723736408-1406369008-1109
Surname           : Brown
UserPrincipalName : dbrown@Manticore.org

 

An empty string on the otherhand

$div = ”
Set-ADUser -Identity dbrown  -Division $div

Set-ADUser : replace
At line:1 char:1
+ Set-ADUser -Identity dbrown  -Division $div
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidOperation: (dbrown:ADUser) [Set-ADUser], ADInvalidOperationException
+ FullyQualifiedErrorId : ActiveDirectoryServer:0,Microsoft.ActiveDirectory.Management.Commands.SetADUser

Causes an error

Bottom line – if you’re passing in a CSV file check that the values in it aren’t NUL or empty – either by validating the parameters in your function or by writing extra code. The first way is much preferred


July 1, 2015  10:51 AM

String startswith method

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
.NET, Powershell

If you look at the methods available on a string one of them is StartsWith(). It tests if a given string starts with another string

 

£> ‘frgrughrugu’.StartsWith

OverloadDefinitions
——————-
bool StartsWith(string value)
bool StartsWith(string value, System.StringComparison comparisonType)
bool StartsWith(string value, bool ignoreCase, cultureinfo culture)

 

The first option is the easiest to use and the most common scenario

£> ‘frgrughrugu’.StartsWith(‘frg’)
True
£> ‘frgrughrugu’.StartsWith(‘xya’)
False

Unlike most things in PowerShell this comparison is NOT case insensitive

£> ‘frgrughrugu’.StartsWith(‘fRg’)
False

 

The second option helps by letting you use the members of the System.StringComparison enumeration to control the way the comparison is performed

£> $ct = [System.StringComparison]::CurrentCultureIgnoreCase

£> ‘frgrughrugu’.StartsWith(‘frg’, $ct)
True
£> ‘frgrughrugu’.StartsWith(‘fRg’, $ct)
True

 

The final option allows you to use a culture to control the way the comparison is performed. $null implies use the current culture. Note how the boolean controlling the case sensitivity works:

£> ‘frgrughrugu’.StartsWith(‘frg’, $true, $null)
True
£> ‘frgrughrugu’.StartsWith(‘fRg’, $true, $null)
True
£> ‘frgrughrugu’.StartsWith(‘fRg’, $false, $null)
False
£> ‘frgrughrugu’.StartsWith(‘frg’, $false, $null)
True


July 1, 2015  8:13 AM

Domain Admins password last set

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

A recent question on the forums asked about getting the date a password was last set and the password never expires status for the domain admins group

This is one way of doing it

Get-ADGroupMember -Identity ‘Domain Admins’ |
foreach {
Get-ADUser -Identity $psitem.samAccountName -Properties PasswordLastSet, PasswordNeverExpires |
select Name, PasswordLastSet, PasswordNeverExpires
}

Get the group and for each member get the aduser information and select the properties to display.

Get-ADGroupMember and Get-AdUser work together on the pipline so you can also do this:

Get-ADGroupMember -Identity ‘Domain Admins’ |
Get-ADUser -Properties PasswordLastSet, PasswordNeverExpires |
select Name, PasswordLastSet, PasswordNeverExpires


June 30, 2015  10:00 AM

Removing HomeDrive and HomeFolder settings

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

 

Back in this post https://richardspowershellblog.wordpress.com/wp-admin/post.php?post=2343&action=edit I showed how to set the users home directory and home drive.

I was recently asked how to remove entries from those attributes.

The easiest way is to use the –Clear parameter with set-AdUser

Set-ADUser -Identity gdreen -Clear HomeDrive, HomeDirectory


June 29, 2015  12:06 PM

CIM filters

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
CIM, Powershell, WMI

I was looking up Win32_SystemDriver on the MSDN site and noticed there was some PowerShell example code

Get-WmiObject -Class Win32_SystemDriver |
Where-Object -FilterScript {$_.State -eq “Running”} |
Where-Object -FilterScript {$_.StartMode -eq “Manual”} |
Format-Table -Property Name,DisplayName

A better way to write this would be:

Get-WmiObject -Class Win32_SystemDriver -Filter “State=’Running’ AND StartMode=’Manual'” | Format-Table -Property Name, DisplayName –AutoSize

or

Get-CimInstance -ClassName Win32_SystemDriver -Filter “State=’Running’ AND StartMode=’Manual'” | Format-Table -Property Name, DisplayName -AutoSize

Do the filtering in the CIM call – especially if you’re running this against a number of remote machines. That way you limit the network traffic you’re returning


June 29, 2015  9:12 AM

Parsing ipconfig /displaydns with regular expressions

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
DNS, Powershell

In yesterdays post I used a series of split operations to parse the strings produced by ipconfig /displaydns

 

Regular expressions should give a more power full way to perform this task. Not being a big fan of regular expressions I tend not to use them but for the sake of experimentation I thought I’d try and figure out a set of regex to use.

 

This is as far as I’ve got

 

$props = [ordered]@{
RecordName = “”
RecordType = “”
Section    = “”
TimeToLive = 0
DataLength = 0
Data       = “”
}

$recs = @()

$cache = ipconfig /displaydns
for($i=0; $i -le ($cache.Count -1); $i++) {
if ($cache[$i] -like ‘*Record Name*’){
$rec = New-Object -TypeName psobject -Property $props
$rec.RecordName = $cache[$i] -replace “(\s*\w*){2}(\s\.){5}(\s\:\s)”, “”
$rec.Section = $cache[$i+4] -replace “\s*\w*(\s\.){7}(\s\:\s)”, “”
$rec.TimeToLive = $cache[$i+2] -replace “(\s*\w*){3}\s(\s\.){4}(\s\:\s)”, “”
$rec.DataLength = $cache[$i+3] -replace “(\s*\w*){2}(\s\.){5}(\s\:\s)”, “”

$irec = ($cache[$i+5] -split “: “)
$rec.RecordType = ($irec[0].TrimStart() -split ‘ ‘)[0]
$rec.Data = $irec[1]

$recs += $rec
}
else {
continue
}
}

$recs | Format-Table –AutoSize

 

I still need to work out how to process the data and record type using regular expressions


June 28, 2015  1:53 PM

Parsing ipconfig /displaydns

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
DNS, Powershell

 

A recent question on the forum asked how you could get the contents on Windows 7 machines and earlier.

On later machines – Windows 8 and above –  its easy because you can use Get-DnsClientCache from the DnsClient module. This module is based on CIM classes that aren’t present on Windows 7 and earlier systems.

You can use ipconfig /displaydns to display the data but it looks like this

Record Name . . . . . : ns-nw.noaa.gov
Record Type . . . . . : 1
Time To Live  . . . . : 81966
Data Length . . . . . : 4
Section . . . . . . . : Additional
A (Host) Record . . . : 161.55.32.2

so you need to parse the strings into a format that you can work with.

This is one solution

$props = [ordered]@{
RecordName = “”
RecordType = “”
Section    = “”
TimeToLive = 0
DataLength = 0
Data       = “”
}

$recs = @()

$cache = ipconfig /displaydns
for($i=0; $i -le ($cache.Count -1); $i++) {
if ($cache[$i] -like ‘*Record Name*’){
$rec = New-Object -TypeName psobject -Property $props
$rec.RecordName = ($cache[$i] -split -split “: “)[1]
$rec.Section = ($cache[$i+4] -split -split “: “)[1]
$rec.TimeToLive = ($cache[$i+2] -split -split “: “)[1]
$rec.DataLength = ($cache[$i+3] -split -split “: “)[1]

$irec = ($cache[$i+5] -split “: “)
$rec.RecordType = ($irec[0].TrimStart() -split ‘ ‘)[0]
$rec.Data = $irec[1]

$recs += $rec
}
else {
continue
}
}

$recs | Format-Table –AutoSize

Create an ordered hash table of output properties and an empty array to hold the results.

Get the output of  ipconfig /displaydns into $cache which will be an array of strings

Loop through $cache

if the record is like *Record Name*’ then process that record and the next five records to give the results.  The actual data record is split twice to give the record type and the data – otherwise you’ll have to translate the numeric values in the Record Type line.

The results are put into an object which is added to the output array.

Continue looping through $cache until you meet the next line with a Record Name or end of file.

Finally display the results.

This works but is messy – I’m going to investigate alternatives


June 27, 2015  10:50 AM

Scripting Games

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

See what’s happening with the Scripting Games –  http://blogs.technet.com/b/heyscriptingguy/archive/2015/06/27/powershell-spotlight-yeah-it-s-the-scripting-games.aspx

Thank about the requirements and offer to help as outlined in the article.


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: