PowerShell for Windows Admins


January 31, 2017  2:17 PM

Append data to a file

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

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
data

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
data

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
data

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
Powershell

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
SerializationVersion           1.1.0.1

$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
SerializationVersion           1.1.0.1

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
Hyper-V

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

https://www.manning.com/books/learn-hyper-v-in-a-month-of-lunches


January 28, 2017  2:16 PM

Summit 2017–seats going fast

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

Seats a the PowerShell Summit –  https://eventloom.com/event/home/summit2017 – are going fast.

We’ve sold over 70% of the seats – they’re current 55 seats left split between 4-day and 3-day passes. The 3-day passes don’t go on sale until 12 February and we’ll be moving 3-day to 4-day as sales happen between now and then. We have a number of sales in the pipeline that will reduce the number of available seats as well.

We are at maximum capacity for the venue – and probably for the event in its present format.

We are expecting a rapid sell off of the remaining seats when open registration of 3-day passes. We don’t maintain any sort of waiting list and when the seats are gone – they’re gone.

If you are thinking of attending the 2017 Summit I’d advise you to get your seat booked quickly – I wouldn’t be at all surprised if we’d sold out by the end of February.


January 27, 2017  11:32 AM

Learn Hyper-V – Deal of the day – January 28 2017

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Hyper-V

Deal of the Day January 28: Half off my book Learn Hyper-V in a Month of Lunches. Use code dotd012817au at http://bit.ly/2jAIfWK

More information from DOTD’s page at https://www.manning.com/dotd


January 27, 2017  4:48 AM

wmic deprecated

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

I saw a forum post today where the question involved the use of the wmi command line tool wmic.

Wmic was deprecated in Windows Server 2012 – https://technet.microsoft.com/en-us/library/hh831568(v=ws.11).aspx. It will eventually be removed.

You should use the CIM cmdlets instead of wmic. The syntax is much easier and the resultant code is easier to understand.

A little known fact – the PowerShell project was originally started as a replacement for wmic.


January 24, 2017  3:10 PM

Community Lightning Demos

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

We are continually evolving the content we present at the PowerShell Summit. This year we’re bringing back something that was a feature of the early PowerShell Deep Dives and Summits – the Community Lightning Demos. We have a session set aside on Wednesday afternoon for this. Timescales will depend on the number of people wanting to show something.

In the words of PowerShell MVP Warren Frame who’s organising this for us:

Ever wanted to present at Summit but were unsure if you could? This is your opportunity to present something you’ve discovered to your peers in the PowerShell community. A code trick, or tip, a new module you’ve created, an open source module or a feature of a cmdlet that’s relatively unknown.. The list goes on and on. Anything PowerShell, or DevOps related that you think is cool and that will interest other people is a suitable topic. We’re looking for 5-10 minute demos. Something you’ve done, discovered, solved or run up against. This is your opportunity to “give back” to our community by sharing your knowledge. Make sure its something you can present from your laptop and that you don’t need extensive Internet access. A sign up sheet will be available Sunday, Monday and Tuesday. We just need your name and topic. Who knows you may be asked to present a full session at the following Summit. Some of our best speakers started in the Lightning Demos sessions of past events.

This is your opportunity to start presenting to a knowledgeable and appreciative audience. In past events we’ve had some amazing things come to light – things the PowerShell team didn’t realise about PowerShell. If you have something to share please consider signing up for this.


January 24, 2017  2:37 PM

WMF 5.1 now available

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The download for WMF 5.1 for down level operating systems is now available:

https://blogs.msdn.microsoft.com/powershell/2017/01/19/windows-management-framework-wmf-5-1-released/

WMF 5.1 can be installed on Windows 7 and 8.1 plus Windows Server 2008 R2, 2012, 2012 R2

Windows 10 and Server 2016 already have PowerShell 5.1 and don’t need this install.

if installing on Windows 7 or Server 2008 R2 the installation process has changed – READ THE RELEASE NOTES OR BE PREPARED FOR A LOT OF EXTRA EFFORT


January 12, 2017  10:48 AM

Using $_

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

The $_ symbol seems to be causing confusion from some recent forum questions I’ve seen.

$_ represents the current object on the pipeline – if you want to know why $_ was chosen you’ll have to read PowerShell in Action!

You can use $_ in a number of situations – in commands that perform an action on every object (or selected objects) on the pipeline. Here’s some of the commoner usages:

In the early versions of PowerShell you used it in the filter script of Where-Object

Get-Process | Where-Object -FilterScript {$_.CPU -gt 50}

This is more usually written as

Get-Process | Where {$_.CPU -gt 50}

As of PowerShell v3 if you are filtering on ONE property you can simplify the syntax

Get-Process | Where CPU -gt 50

which is a truncated version of

Get-Process | Where -Property CPU -gt -Value 50

When you write it like this its obvious what is happening. Get in the habit of thinking of the syntax in this manner even if you write in the shortened form

If you need to filter on TWO or more properties you have to use the old style syntax

Get-Process | Where {$_.CPU -gt 50 -AND $_.Handles -gt 1000}

In all of these cases you’re comparing a property of the current pipeline object against a value. If the comparison is true the object is passed onto the next step of the pipeline. If its false the object is discarded.

You can use $psitem in place of $_ if you prefer

Get-Process | Where {$psitem.CPU -gt 50}

In the Foreach-Object cmdlet you can use $_ to refer to the current object

Get-CimInstance -ClassName Win32_NetworkAdapter -Filter "NetEnabled = $true" |
ForEach-Object {
$ip = Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter "Index = $($_.DeviceId)"
$props = @{
Name = $_.NetConnectionId
Product = $_.ProductName
DHCP = $ip.DHCPEnabled
IP   = $ip.IPAddress
}
New-Object -TypeName PSObject -Property $props
}

$psitem also works in this situation

The third common usage of $_ is in select-object in calculated fields (you can do the same in Format-Table)

Get-CimInstance -ClassName Win32_LOgicalDisk -Filter "DriveType=3" |
select DeviceId, VolumeName,
@{N='Size(GB)'; E={[math]::Round($_.Size / 1GB, 2)}},
@{N='Used(GB)'; E={[math]::Round(($_.Size - $_.FreeSpace) / 1GB, 2)}},
@{N='Free(%)'; E={[math]::Round(($_.FreeSpace / $_.Size) * 100, 2 )}}

In this example we’re changing the size to GB from bytes and calculating the used space and the % free space. Again you could use $psitem instead of $_

ONE PLACE YOU CAN’T USE $_  IS IN A FOREACH LOOP

This fails

$nics = Get-CimInstance -ClassName Win32_NetworkAdapter -Filter "NetEnabled = $true"
$data = foreach ($nic in $nics) {
$ip = Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter "Index = $($_.DeviceId)"
$props = @{
Name = $_.NetConnectionId
Product = $_.ProductName
DHCP = $ip.DHCPEnabled
IP   = $ip.IPAddress
}
New-Object -TypeName PSObject -Property $props
}
$data |Format-List

To recap $_ (or $psitem) is used to represent the current object on the pipeline. You can us it in commands that are performing an action on every object on the pipeline.


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: