PowerShell for Windows Admins


August 2, 2015  3:40 AM

Windows 10 upgrade–network instability on Surface Pro 2

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Windows 10

One thing I noticed after performing the recent upgrade to Windows 10 was that my network connection had become unstable. It was losing the DNS server configuration on an irregular and intermittent basis. Renewing the DHCP lease on my wireless connection would correct the issue.

My Windows 8.1 install had Hyper-V enabled which modifies the network connections. Removing Hyper-V seems to have resolved the issue as I haven’t had any further problems.

If you’re upgrading a Surface Pro 2 you may want to think about removing Hyper-V before the upgrade, then re-install after the upgrade.

August 1, 2015  4:05 AM

Scripting Games July 12015 thoughts on the solution

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

The July 2015 puzzle can be found here:

http://powershell.org/wp/2015/07/04/2015-july-scripting-games-puzzle/

Write a one-liner that produces the following output (note that property values will be different from computer to computer; that’s fine).

Write a one-liner that produces the following output (note that property values will be different from computer to computer; that’s fine).

PSComputerName ServicePackMajorVersion Version  BIOSSerial
————–         ———————– ——-  ———-
win81             0                       6.3.9600 VMware-56 4d 09 1 71 dd a9 d0 e6 46 9f

By definition, a one-liner is a single, long command or pipeline that you type, hitting Enter only at the very end. If it wraps to more than one physical line as you’re typing, that’s OK. But, in order to really test your skill with the parser, try to make your one-liner as short as technically possible while still running correctly.

Challenges:

•Try to use no more than one semicolon total in the entire one-liner

•Try not to use ForEach-Object or one of its aliases

•Write the command so that it could target multiple computers (no error handling needed) if desired

•Want to go obscure? Feel free to use aliases and whatever other shortcuts you want to produce a teeny-tiny one-liner.

By definition, a one-liner is a single, long command or pipeline that you type, hitting Enter only at the very end. If it wraps to more than one physical line as you’re typing, that’s OK. But, in order to really test your skill with the parser, try to make your one-liner as short as technically possible while still running correctly.

Challenges:

•Try to use no more than one semicolon total in the entire one-liner

•Try not to use ForEach-Object or one of its aliases

•Write the command so that it could target multiple computers (no error handling needed) if desired

•Want to go obscure? Feel free to use aliases and whatever other shortcuts you want to produce a teeny-tiny one-liner.

 

Initial thoughts.

One liner is a mis-nomer that has caused more problems than enough for the PowerShell community. The requirement is correctly stated as a single pipline.  One pipeline can spread over many lines but is called a one-liner. This is one line of code:

get-service; get-process;

but is not a one-liner because the semi-colon is a line termination character so you’ve combined 2 lines but into 1 but they’ll execute as 2 pipelines.

Obviously need to use CIM (WMI) to retrieve the data. Standard approach would be Win32_OperatingSystem & Win32_Bios

£> Get-CimClass *Bios

NameSpace: ROOT/cimv2

CimClassName
————
Win32_BIOS
Win32_SystemBIOS
£> Get-CimClass *OperatingSystem

NameSpace: ROOT/cimv2

CimClassName
————
CIM_OperatingSystem
Win32_OperatingSystem
Win32_SystemOperatingSystem

If you want to shave off a couple of characters you could use the CIM_OperatingSystem class as Boe suggests http://powershell.org/wp/2015/07/29/2015-july-scripting-games-wrap-up/

Be aware that the CIM_ classes adhere to the standard definition from the DMTF – http://www.dmtf.org/standards/cim and Win32_ classes are the Microsoft version from when WMI was introduced. The win32_ classes are often subtly different to the CIM_ classes so check carefully with Get-CimClass before using.

My first though was to use Get-CimInstance

Get-CimInstance -ClassName Win32_OperatingSystem |
select PSComputerName, ServicePackMajorVersion, Version,
@{N=’BIOSSerial'; E={(Get-CimInstance -ClassName Win32_Bios).SerialNumber}}

But for the local machine that won’t return the PSComputerName attribute unless you use the –ComputerName parameter and point to the local machine or pipe the computer name to the cmdlet

Get-WmiObject doesn’t have that problem

Get-WmiObject -ClassName Win32_OperatingSystem |
select PSComputerName, ServicePackMajorVersion, Version,
@{N=’BIOSSerial'; E={(Get-CimInstance -ClassName Win32_Bios).SerialNumber}}

The trick here is to use a calculated field to get the BIOS serial number

I prefer using Invoke-Command to get the data   from a  remote machine. I get the RunSpaceId as well but that can be filtered out.

The last part of the puzzle was to shrink the code to the smallest number of characters possible. I’ve never seen the point of that in production use so never bother – if I wanted to write something unreadable I’d use Perl. The time taken to shrink is never regained and I can use tab completion to get my code input quickly and working. Boe has done an excellent job of showing that could be done so I’ll point you  in that direction

 

 

 


July 29, 2015  7:30 AM

Windows 10

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Windows 10

Went through the Windows 10 upgrade procedure this morning. Fairly quick process – just over the hour including download on a slow broadband link. Most of my settings from Windows 8.1 were saved.

 

So far impressions are reasonable to good.

 

PowerShell 5.0 is installed

£> $PSVersionTable

Name                           Value
—-                           —–
PSVersion                      5.0.10240.16384
WSManStackVersion              3.0
SerializationVersion           1.1.0.1
CLRVersion                     4.0.30319.42000
BuildVersion                   10.0.10240.16384
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3

 

The Edge browser (IE replacement) is missing functionality for managing favourites and doesn’t appear to incorporaet an RSS feed reader. IE is still available – hunt through program files to get to the exe.

 

The Mail app doesn’t supply a unified view across all mailboxes.

 

The big improvement over Windows 8/8.1 is that you get a unified view of applications. No more metro style or desktop. Everything runs on the desktop though the lack of a left and bottom border on the PowerShell console is weird.

 

So far nothing leaps out as a show stopper


July 28, 2015  11:23 AM

PowerShell Summit NA 2016–call for topics warning

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

A conference organiser’s work is never done. The dust has just settled from PowerShell Summit NA 2015 and we’re gearing up for PowerShell Europe 2015.

We also need to start thinking about PowerShell NA 2016! A post on powershell.org

http://powershell.org/wp/2015/07/28/powershell-summit-na-2016-call-for-topics-coming-soon/

serves as a warning to start thinking about topics for PowerShell NA 2016 which will be in Bellevue (Seattle) again. The official call for topics will go out next week all being well.

Don’t worry about PowerShell Europe 2016 – we haven’t forgotten about that – the call for topics will occur towards the end of the year.


July 28, 2015  5:26 AM

WMI dates

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

Dates as reported by WMI still seem to cause a lot of problems. If you use the WMI cmdlets

£> Get-WmiObject -Class Win32_OperatingSystem | select *date* | fl
InstallDate   : 20131205101649.000000+000
LocalDateTime : 20150728121320.002000+060

 

That format is year, month, day, hour, minute, second then fractions of a second after the decimal point with the final +nnn indicating an offset from Greenwich Mean Time  (UTC) for time zones and daylight saving time.

You can read the date presented by WMI but its not intuitive.

The PowerShell team added a ConvertToDateTime() to the object output by WMI so that you can easily perform date conversions

£> Get-WmiObject -Class Win32_OperatingSystem | select @{N=’Install'; E={$_.ConvertToDateTime($_.Installdate)}}, @{N=’Lo
calDate'; E={$_.ConvertToDateTime($_.LocalDateTime)}} | fl
Install   : 05/12/2013 10:16:49
LocalDate : 28/07/2015 12:16:26

 

Though my preferred solution these days is to use the CIM cmdlets as they convert the date for you without any extra effort

£> Get-CimInstance -ClassName Win32_OperatingSystem | select *date* | fl
InstallDate   : 05/12/2013 10:16:49
LocalDateTime : 28/07/2015 12:17:29


July 25, 2015  7:44 AM

Self signed certificates for testing

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

A question on the forum

http://powershell.org/wp/forums/topic/cannot-add-digital-signature-to-my-script/#post-27883

indicated a problem when using a self signed certificate for testing code signing.

According to the about_signing help file

CREATE A SELF-SIGNED CERTIFICATE
——————————–
To create a self-signed certificate in use the New-SelfSignedCertificate
cmdlet in the PKI module. This module is introduced in Windows PowerShell
3.0 and is included in Windows 8 and Windows Server 2012. For more
information, see the help topic for the New-SelfSignedCertificate cmdlet.

To create a self-signed certificate in earlier versions of Windows, use
the Certificate Creation tool (MakeCert.exe). This  tool is included in
the Microsoft .NET Framework SDK (versions 1.1 and later) and in the
Microsoft Windows SDK.

However the cert produced by New-SelfSifgnedCertificate only appears to function as a SSL self signed cert. It isn’t accepted as a code signing cert.

You can still get the makecert utility for Windows 8.1 from

https://msdn.microsoft.com/en-gb/windows/desktop/bg162891.aspx

and Windows 8 from

https://msdn.microsoft.com/en-us/library/windows/desktop/hh852363.aspx

The makecert utility can be found in

C:\Program Files (x86)\Windows Kits\8.1\bin\x64
or

C:\Program Files (x86)\Windows Kits\8.1\bin\x86

for the 64 & 32bit versions respectively

While you shouldn’t use self-signed certs for production they are useful for testing. My recommendation is to use the makecert utility rather than the PKI cmdlet

 


July 23, 2015  11:26 AM

Devops Tools

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
DevOps

DevOps is the fusion of development and operations practices to give you faster, more reliable, roll out of functionality to your organisation.  Its a growing area and while much of DevOps practice is cultural rather than technical you will need at least some tools to get the job done.

There are a growing number of tools available and finding what you need can be difficult. I stumbled across this site:

http://www.devopsbookmarks.com/

which functions as an aggregation point for a significant number of the current tools. Even if you don’t need them now its worth knowing what’s available.

Don’t forget PowerShell and in particular Desired State Configuration in all of this though.


July 22, 2015  8:23 AM

PowerShell documentation and more

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

PowerShell has a new home.  This site on MSDN https://msdn.microsoft.com/en-us/powershell is the centre for Microsoft’s PowerShell documentation. Book mark it now!


July 22, 2015  8:04 AM

Using parameters instead of read-host when getting AD replication data

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

I’ve seen a lot of scripts recently that use Read-Host to get input data.  This is generally not best practice – I tend to only use Read-Host if I want to get a password and obscure the text on screen.

A better practice is to use parameters – either in a function or a script. As an example consider this function that gets AD replication metadata

function get-ADReplmetadata {
param (
[Parameter(Mandatory=$true)]
[string]$ldapfilter,

[Parameter(Mandatory=$true)]
[string]$attribute,

[string]$server = ‘server02′
)
Get-ADObject -LDAPFilter “($ldapfilter)”  -Properties $attribute |
Get-ADReplicationAttributeMetadata -Server $server -Attribute $attribute

}

Get-ADReplicationAttributeMetadata  is awkward to use because it only accepts a distinguished name or a GUID for identifying the object you want to access. Remembering distinguished names or GUIDs  is a pain so I use get-AdObject with an LDAP filter and pipe it to Get-ADReplicationAttributeMetadata .

The $server parameter defaults to server02 but can be overridden if you want to use another domain controller

I make the ldapfilter and attributes mandatory so I get prompted if I forget

This example pulls back meta data for just the Name

get-ADReplmetadata -ldapfilter ‘samAccountName=Richard’ -attribute Name

This example pulls back all metadata

get-ADReplmetadata -ldapfilter ‘samAccountName=Richard’ -attribute *


July 21, 2015  2:54 PM

Data for comparisons

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

A question on the forum asked about storing data used in comparisons, The example was based on a list if IP addresses where some were known to be good and the questioner wanted to filter out the known good ones so he just had to investigate the rest.

You could put the data in your script

Remove-Item -Path C:\TestScripts\unknownip.txt -Force
$safe = ‘127.0.0.1’,
‘10.10.54.199’,
‘10.10.54.200’,
‘192.168.0.1’
$ips = ‘127.0.0.1’, ‘10.10.54.199’, ‘172.16.5.1’, ‘192.168.0.47’, ‘10.10.54.200’

foreach ($ip in $ips){
if ($ip -notin $safe) {
Out-File -InputObject $ip -FilePath C:\TestScripts\unknownip.txt -Append
}
}

cat C:\TestScripts\unknownip.txt

The advantage is that you only maintain one file. The disadvantage come sif you want to use the data in another script.

Another approach is to put the data in  a file

127.0.0.1
10.10.54.199
10.10.54.200
192.168.0.1

I saved it as safeips.txt

The script changes to

Remove-Item -Path C:\TestScripts\unknownip.txt -Force
$safe = Get-Content -Path C:\TestScripts\safeips.txt

$ips = ‘127.0.0.1’, ‘10.10.54.199’, ‘172.16.5.1’, ‘192.168.0.47’, ‘10.10.54.200’

foreach ($ip in $ips){
if ($ip -notin $safe) {
Out-File -InputObject $ip -FilePath C:\TestScripts\unknownip.txt -Append
}
}

cat C:\TestScripts\unknownip.txt

In production you’d obviously read the IPs to test from a file of some kind rather than hard code in the script.

The second approach involves maintaining 2 files but gives greater flexibility – its the approach I prefer

 

 

 


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: