PowerShell for Windows Admins


October 14, 2015  5:07 AM

Modifying MAC address

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

Another question on the forum brought up an interesting point. User want adapter name and Mac address

PS> Get-NetAdapter | select Name, MacAddress

Name                         MacAddress
—-                         ———-
WiFi                         28-18-78-D0-05-11
Bluetooth Network Connection 28-18-78-D0-05-12

but wanted to remove the hyphens in the mac address so tried

PS> Get-NetAdapter | select Name, MacAddress | foreach {$_.MacAddress -replace ‘-‘,”}
281878D00511
281878D00512

This doesn’t work because the for each cmldet only knows to put put the new string when the hyphens have been replaced in the Mac address. The name is effectively filtered out.

The answer is to use a calculated field in select-object like this

PS> Get-NetAdapter | select Name, @{N=’MacAddress’; E={$_.MacAddress -replace ‘-‘,”}}

Name                         MacAddress
—-                         ———-
WiFi                         281878D00511
Bluetooth Network Connection 281878D00512

N = Name and E= Expression though they are usually shorten for brevity as shown

October 14, 2015  4:59 AM

NICs with IP addresses

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

A question on the forum asked about discovering those network adapters that had IP addresses configured. The user had tried

PS> Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter “IPAddress IS NOT NULL”
Get-WmiObject : Invalid query “select * from Win32_NetworkAdapterConfiguration where IPAddress IS NOT NULL”
At line:1 char:1
+ Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter “IPAdd …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (:) [Get-WmiObject], ManagementException
+ FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

Actually they’d tried the full WQL query. I don’t do that because its more typing than using the class name and a filter.

The problem is that IPAddress is a string array and WQL won’t let you query against an array of properties.

You have 2 choices

Get-WmiObject -Class Win32_NetworkAdapterConfiguration | where IPAddress

which is fine fro local machines but means you are filtering out results on the local machine when querying a remote machine – wasteful.

A better solution is to use the IPEnabled property. This is a boolean that is set to TRUE when an IP address (static or DHCP) has been set on a NIC. Your query then becomes

Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter “IPEnabled = $true”

OR

Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter “IPEnabled = $true”


October 13, 2015  10:45 AM

Microsoft Edge Browser

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Windows 10

For the most part I’ve been quite happy with the new Edge browser in Windows 10. One of the irritations was that I could only have one instance open at a time. This appears to have been resolved in the Windows Insider Preview build 10565 which allows multiple instances.

Nice


October 13, 2015  10:38 AM

NSlookup in PowerShell

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
DNS, Powershell

nslookup.exe is a command line executable that is used to discover the IP address of a remote machine from its FQDN. The results look something like this:

PS> nslookup powershell.org
DNS request timed out.
timeout was 2 seconds.
Server:  UnKnown
Address:  192.168.0.1

Non-authoritative answer:
DNS request timed out.
timeout was 2 seconds.
Name:    powershell.org
Addresses:  104.28.15.25
104.28.14.25

The output is text – not the most useful of things to use.

One option if you want to perform lookups in PowerShell is to write your self a script

$ns = (nslookup.exe powershell.org )[-4..-3]
$lookup = [PSCustomObject]@{
Name = ($ns[0] -split ‘:’)[1].Trim()
Address = ($ns[1] -split ‘:’)[1].Trim()
}
$lookup

Run nslookup and take the 3rd and 4th lines from the end of the output. Then create an output object where the text in the array is split at the : the second element is used and trimmed of blank spaces.

If you like using .NET static methods you can do this:

PS> [System.Net.DNS]::GetHostEntry(‘powershell.org’)

HostName       Aliases AddressList
——–       ——- ———–
powershell.org {}      {104.28.15.25, 104.28.14.25}

Best of all is the use the Resolve-DnsName cmdlet from the DnsClient module that’s present in Windows 8 and later

PS> Resolve-DnsName -Name ‘powershell.org’ | ft -a

Name           Type TTL Section IPAddress
—-           —- — ——- ———
powershell.org A    300 Answer  104.28.15.25


October 5, 2015  7:04 AM

Scripting Games September 2015

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

The puzzle for September is here http://powershell.org/wp/2015/09/05/september-2015-scripting-games-puzzle/

with the write up published here

http://powershell.org/wp/2015/10/03/2015-september-scripting-games-wrap-up/

Personally I don’t like the approach as it leads to code that’s difficult to read and maintain. I much prefer a simpler more verbose approach that is maintainable.


October 3, 2015  2:18 PM

Windows PowerShell in Action, Third Edition

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Books, Powershell

PowerShell in Action by Bruce Payette has been THE book for the PowerShell expert to learn how PowerShell works under the covers. If you  wanted to know how PowerShell works and why it works the way it does – this was the book.  PowerShell in Action second edition was written when PowerShell 2.0 was the new kid on the block but we’ve had PowerShell 3.0, 4.0 and now 5.0 since the book was written

Many people have asked if a new edition was going to happen.

The answer is yes and chapters 1 and 3 are now available through the Manning Early Access Program (MEAP).  It’s being completely revised with all text brought up to date for PowerShell 5.0 and new material covering all of the new features in PowerShell 3.0, 4.0 and 5.0 including Workflows, Desired State Configuration, PowerShell classes, programming APIs and more.

The MEAP is available from https://manning.com/books/windows-powershell-in-action-third-edition

If you want to know how PowerShell really works this is the book you need. I’ve used the first and second editions for many years and its always been the book I’ve turned to when I’m stuck. I’m honoured to be helping Bruce produce the third edition of this book and hope you get as much out of it as we’ve put into it.

Enjoy


October 2, 2015  8:24 AM

Quick update check

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell, WSUS

Want to check on any updates that haven’t been fully applied in your environment. Run this on your WSUS server (2012 R2)

£> Get-WsusUpdate -Classification All -Status Any -Approval AnyExceptDeclined |
where InstalledOrNotApplicablePercentage -ne 100

You can modify the filters:

Classification = one of All, Critical, Security, WSUS

Status = one of NoStatus, InstalledOrNotApplicable, InstalledOrNotApplicableOrNoStatus, Failed, Needed, FailedOrNeeded, Any

Approval = one of Approved, Unapproved, AnyExceptDeclined, Declined


October 1, 2015  2:47 AM

Strings and collections

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

A question on the forum brought up a point that often confuses PowerShell novices.

QUESTION: What’s the difference between

$computers = ‘W12R2SUS, W12R2DSC’

and

$computers = ‘W12R2SUS’, ‘W12R2DSC’

ANSWER:

The first is a string

PS> $computers.GetType() | ft -a

IsPublic IsSerial Name   BaseType
——– ——– —-   ——–
True     True     String System.Object

The second is an array – a collection of strings

PS> $computers.GetType() | ft -a

IsPublic IsSerial Name     BaseType
——– ——– —-     ——–
True     True     Object[] System.Array

The difference is important when you try to use $computers as the value for a parameter where you want to supply a list of computer names:

if you use the string – you’ll get an error

PS> $computers = ‘W12R2SUS, W12R2DSC’
PS> $ps = New-PSSession -ComputerName $computers
New-PSSession : One or more computer names are not valid. If you are trying to pass a URI, use the -ConnectionUri
parameter, or pass URI objects instead of strings.
At line:1 char:7
+ $ps = New-PSSession -ComputerName $computers
+       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (System.String[]:String[]) [New-PSSession], ArgumentException
+ FullyQualifiedErrorId : PSSessionInvalidComputerName,Microsoft.PowerShell.Commands.NewPSSessionCommand

You have to use an array

PS> $computers = ‘W12R2SUS’, ‘W12R2DSC’
PS> $ps = New-PSSession -ComputerName $computers
PS> $ps

Id Name            ComputerName    State         ConfigurationName     Availability
— —-            ————    —–         —————–     ————
2 Session2        W12R2DSC        Opened        Microsoft.PowerShell     Available
1 Session1        W12R2SUS        Opened        Microsoft.PowerShell     Available

A trap that everyone falls into at some time or other but one that can be avoided


September 30, 2015  1:16 PM

PowerShell DSC for Linux 1.1

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Linux, Powershell

PowerShell DSC for Linux 1.1 has been released.

http://blogs.msdn.com/b/powershell/archive/2015/09/30/powershell-dsc-for-linux-version-1-1-is-now-available-and-new-linux-resources.aspx

With bug fixes, support for the separation of configuration and node ids  and new resources this release makes it easier than ever to manage your Linux boxes through DSC


September 30, 2015  12:24 PM

Controlling copies

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

I was recently asked about ‘forcing’ a copy so that only the files you want are copied

Consider a folder with lots of files. I want to copy those files that start with the letter t and have a txt extension

PS> Get-ChildItem -Path C:\test2\t*.txt
  Directory: C:\test2
Mode                LastWriteTime         Length Name
—-                ————-         —— —-
-a—-       08/08/2015     14:14              0 test.txt
-a—-       08/08/2015     14:16              0 test1.txt
-a—-       08/08/2015     14:17              0 test2.txt
-a—-       08/08/2015     14:17              0 test3.txt
-a—-       08/08/2015     14:17              0 test4.txt

I want to copy to c:\test1 which is empty

PS> Get-ChildItem -Path C:\test1\
PS>

Defining the copy is simply a matter of setting the path to files you want

PS> Copy-Item -Path C:\Test2\t*.txt -Destination C:\test1\ -Verbose
VERBOSE: Performing the operation “Copy File” on target “Item: C:\Test2\test.txt Destination: C:\test1\test.txt”.
VERBOSE: Performing the operation “Copy File” on target “Item: C:\Test2\test1.txt Destination: C:\test1\test1.txt”.
VERBOSE: Performing the operation “Copy File” on target “Item: C:\Test2\test2.txt Destination: C:\test1\test2.txt”.
VERBOSE: Performing the operation “Copy File” on target “Item: C:\Test2\test3.txt Destination: C:\test1\test3.txt”.
VERBOSE: Performing the operation “Copy File” on target “Item: C:\Test2\test4.txt Destination: C:\test1\test4.txt”.
PS> Get-ChildItem -Path C:\test1\
    Directory: C:\test1
Mode                LastWriteTime         Length Name
—-                ————-         —— —-
-a—-       08/08/2015     14:14              0 test.txt
-a—-       08/08/2015     14:16              0 test1.txt
-a—-       08/08/2015     14:17              0 test2.txt
-a—-       08/08/2015     14:17              0 test3.txt
-a—-       08/08/2015     14:17              0 test4.txt


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: