August 2013 - Posts

Server Core Module

On a Windows Server 2012 system you will find a ServerCore module with two cmdlets

Get-DisplayResolution
Set-DisplayResolution

On a full GUI system the cmdlets work

PS> Get-DisplayResolution
1366x768
1280x1024

 

And thats it!  Not a lot but it shows the basic information

You set the resolution like this

Set-DisplayResolution -Width 1366 -Height 768

 

If you look in the functions both actually call the setres command!

Third Age of PowerShell

We’re now firmly in the Third Age of PowerShell.

The First Age covered the betas and PowerShell 1.0

PowerShell was adopted by developers and admins (with a scripting background) that saw the need for better automation tools and went looking for them. Information was sketchy, and every new discovery of how to do something generated a blog post.

Exchange 2007 relied on PowerShell for some activities but most admins only used it when they had to and in a very begrudging way. The moans about functionality that was only available through PowerShell went on & on

while ($true){
  Write-Host "Why can't I use the GUI"
}

PowerShell was very niche with a relatively small number of (very vocal) supporters and was viewed as something that had to be used rather than a tool admins were comfortable with.

The Second Age started with the release of Windows Server 2008 R2 and PowerShell 2.0

Many of the functionality gaps were filled and PowerShell came of age. Microsoft made PowerShell support mandatory for all products – some did it better than others which is still true to day.

Admins began to sit up and take notice as the body of information grew. Blogs began to die away though which is a shame in many ways.

The Scripting Games cut over to being PowerShell only.

The start of the Third Age is defined by the release of PowerShell 3.0 and Windows Server 2012. The amount of PowerShell functionality has gone through the roof – there are still bits of the PowerShell functionality in Server 2012 I haven’t touched.

Admins are beginning to embrace PowerShell. The last 12 months or so I’ve heard a lot of statements that start “I can use PowerShell to do that..”

PowerShell is here to stay and its a must learn technology. The self-proclaimed industry experts are now jumping on the bandwagon and pushing PowerShell as if they invented it.

So where do we go from here.

PowerShell 4.0 will be with us in October with the availability of Server 2012 R2. It has some evolutionary features but I don’t think there’s anything revolutionary.

We’ll still be in the Third Age.

The Fourth Age will start when the majority of admins use PowerShell as a matter of course and you can’t really work on the Windows platform without it.

Come on Microsoft - Make my day & remove the GUI permanently from Windows Server.

Posted by RichardSiddaway | with no comments
Filed under:

Travelling devices

Disclaimer: The following is based on my personal experiences and needs that may well not match yours. Feel free to disagree with my conclusions. I offer my insights to help others decide on the devices that suit them.

 

I’ve been using a number of devices over the last six months or so and found they all have problems. They have seemed to settle into niches though.

Microsoft Surface RT.

The great thing about this is that it has the Microsoft Office installed. Complete versions of Word, Excel, PowerPoint and OneNote.  The email client is reasonable – its the standard Windows 8 mail app. It also shares settings with my other Windows 8 devices. And best of all it has PowerShell installed. PowerShell is constrained and restricted but it is very useful. The fact that it has a full size USB port makes movign files between devices very easy. The stand is a brilliant idea that makes using it on a desk much more comfortable.

The aspect ratio is 16:9 rather than the more common 4:3 which makes using it as a reader a bit awkward. Its also too big to be used comfortably as an e-reader.

Mainly used for meetings, conferences and writing while travelling. I’ve written several chapters of my latest book on it and though the touch keyboard isn’t brilliant it is more than usable.

Number 1 choice for working.

Kindle Fire HD

This is my device of choice if I’m on holiday. Very good size as an e-reader and good email client. The apps are OK but the screen is too small to work on documents except for a quick skim read. The web browser is fast. Linking to my main laptop is easy through a USB cable which makes transferring files simple.

iPad

This is the least useful of all my devices. The Kindle app is flashy with the simulated page turning but it isn’t comfortable to hold for long periods. The fact that you have to link through itunes to move files around is a pain. It is useful reading  technical books due to the screen size. The retina display that’s raved about doesn’t look any better to my eyes than any of the other devices. The email client is so-so. It still reports the number of unread messages incorrectly. The on screen keyboard isn’t very well laid out – especially the odd characters like # where you have to go to a third level. The web browser is so and unresponsive.

 

Apart from being another screen when researching through technical books its not used that much.  Definitely the one I could live without.

 

The best e-reader of all for long distance flights/trains is still my simple Kindle device!

 

I still have a netbook that runs Windows 8. It’s used when I need a full Windows 8 device that’s got a small footprint.

Posted by RichardSiddaway | with no comments
Filed under:

Filtering AD searches

Interesting question came up regarding how you define a Filter when you are searching for particular users. With the Microsoft cmdlets you can define a filter or an ldapfilter.

In these examples we’re looking for users that don’t have email addresses. First lets look at a filter

PS> Get-ADUser -Filter {mail -notlike "*"} | select Name, objectclass | group objectclass -NoElement

Count Name
----- ----
  776 user

The filter is looking for any user accounts that have a mail attribute that isn’t like any characters – in otherwords empty. The advantage of using the –Filter parameter is that the syntax is easy and is what you’re used to in other PowerShell cmdlets such as Where-Object.

The LDAP filters get a bit more complicated

PS> Get-ADUser -LDAPFilter "(&(objectCategory=user)(!mail=*))" | select Name, objectclass | group objectclass -NoElement


Count Name
----- ----
  776 user

Same results but the filter is much more difficult to understand

"(&(objectCategory=user)(!mail=*))"

& means AND

! means NOT

so this reads as

objectcategory=user AND NOT(mail = anything)

The advantage to using an LDAP filter is that you can re-use it on the GUI tools or directorysearcher

You need to be careful if you use Get-ADObject instead of Get-ADUser. Using the same LDAPFilter as above is fine

PS> Get-ADObject -LDAPFilter "(&(objectCategory=user)(!mail=*))" | select Name, objectclass | group objectclass -NoElement

Count Name
----- ----
  776 user

but if you change objectcategory to objectclass which seems reasonable you get very different results:

PS> Get-ADObject -LDAPFilter "(&(objectClass=user)(!mail=*))" | select Name, objectclass | group objectclass -NoElement

Count Name
----- ----
   30 computer
  776 user
    2 msDS-ManagedServiceAcc...
    1 msDS-GroupManagedServi...

 

Huh!  - Computers?

This because computers, users and managed service accounts all derive from the same AD schema class – users BUT they have different objectcategories to separate them.

There’ll be a lot more on searching AD and LDAP filters in AD management in a month of lunches – www.manning.com/siddaway3

Setting an IP address

I need to add an IP address to an adapter.  I could use the GUI or WMI but with Windows 8/2012 and above I’ve got all of the nifty networking cmdlets to play with.

Lets start with finding the adapter to use

PS>Get-NetAdapter

will show all of the adapters. Unlike ipconfig it only shows real NICs – thats physical and virtual but not stuff like “Tunnel adapter Teredo Tunneling Pseudo-Interface”

The one I’m interested in is

Name             ifIndex Status
----             ------- ------
Connections      21 Up

You can find the IP addresses associated with this NIC

PS>Get-NetIPAddress -InterfaceIndex 21 -AddressFamily IPv4


IPAddress         : 10.0.50.100
InterfaceIndex    : 21
InterfaceAlias    : Connections
AddressFamily     : IPv4
Type              : Unicast
PrefixLength      : 24
PrefixOrigin      : Manual
SuffixOrigin      : Manual
AddressState      : Preferred
ValidLifetime     : Infinite ([TimeSpan]::MaxValue)
PreferredLifetime : Infinite ([TimeSpan]::MaxValue)
SkipAsSource      : False
PolicyStore       : ActiveStore

 

To add the IP address use:

New-NetIPAddress -InterfaceIndex 21 -AddressFamily IPv4 -IPAddress 10.0.18.100 -PrefixLength 24

Job done.

If you have to do this on a regular basis you can script finding the adapter and setting the IP address in one pass

Protecting your csv files

I’m using csv files for this example but it applies to other types of file as well. Let’s produce a csv file:
Get-ChildItem -Path C:\Users\Richard\Documents -File |
select FullName, Length, LastWriteTime |
Export-Csv files.csv

This gives a small, useful set of data for the purposes of this post.
You can read the data back in:
Import-Csv .\files.csv

You have decided you need to keep a record of how these files are changing over time. You have further decided that you will create a csv file for each individual day you run the command. The individual files will carry the date as part of the name.
You can create the file name incorporating the date like this:
$file = "Files_$( (get-date -Format "s").Split("T")[0]).csv"

Creating the csv file then becomes:
Get-ChildItem -Path C:\Users\Richard\Documents -File |
select FullName, Length, LastWriteTime |
Export-Csv $file

You can read the file using $file or its name
Import-Csv $file
Import-Csv Files_2013-08-29.csv

Ideally you only want to produce this file once a day and don’t want to overwrite an existing file. Rather than building your own checks you can use the –NoClobber parameter on Export-Csv.  If you try to overwrite an existing file you will get an error:

£> Get-ChildItem -Path C:\Users\Richard\Documents -File | select FullName, Length, LastWriteTime | Export-Csv $file -NoClobber

Export-Csv : The file 'C:\scripts\Files_2013-08-29.csv' already exists.
At line:1 char:97
+ ... astWriteTime | Export-Csv $file -NoClobber
+                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceExists: (C:\scripts\Files_2013-08-29.csv:String) [Export-Csv], IOException
    + FullyQualifiedErrorId : NoClobber,Microsoft.PowerShell.Commands.ExportCsvCommand

The –Force parameter won’t override the -NoClobber
£> Get-ChildItem -Path C:\Users\Richard\Documents -File | select FullName, Length, LastWriteTime | Export-Csv $file -NoClobber -Force
Export-Csv : The file 'C:\scripts\Files_2013-08-29.csv' already exists.
At line:1 char:97
+ ... astWriteTime | Export-Csv $file -NoClobber -Force
+                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceExists: (C:\scripts\Files_2013-08-29.csv:String) [Export-Csv], IOException
    + FullyQualifiedErrorId : NoClobber,Microsoft.PowerShell.Commands.ExportCsvCommand

This technique is useful when you have automated processes producing your files. If the process can be run multiple times per day and you want to preserve the first set of data produced then use –NoClobber.
There are other cmdlets with a –NoClobber parameter:
£> get-help * -Parameter NoClobber

Name
----
Import-Module
Export-Console
Export-Alias
Export-Clixml
Export-Csv
Export-FormatData
Out-File

-NoClobber isn’t infallible –for instance you could explicitly delete the file but it does add a useful level of protection.

Posted by RichardSiddaway | with no comments
Filed under:

It’s the little things

I’ve been spending some quality time with PowerShell 2.0 recently. When it was all we had it was great but there’s a bunch of things I miss from PowerShell 3.0 including:

CIM cmdlets

CIM sessions

Workflows

Module auto loading

Improved tab completion

PowerShell 3.0 ISE especially the combined input/output panes

Of them all it’s the last three that I really miss the most. You become accustomed to the new features and how they make your life easier. To quote “You don’t know what you’ve got ‘til it’s gone”.

So very true but you appreciate them more when you get back to using them.

Posted by RichardSiddaway | with no comments

DNS zone types

I was looking at the DNS zones for a project I’m working on. I needed to discover the conditional forwarder zone and hence the IP address of the DNS server to which the forwarding was occurring.

The zone I wanted had a ZoneType of 4 which puzzled me.

I remembered showing code to create a conditional forwarder in PowerShell in Practice (www.manning.com/siddaway)

$ip = “192.168.40.1”
$zone = [WMIClass]”\\dc02\root\MicrosoftDNS:MicrosoftDNS_Zone”
$zone.Create(“conditional.com”, 3, $true, $null, $ip)

When creating a conditional forwarder you use 3 for the zone type but when reading the zone you get a 4 as the zone type. Other zone types have similar differences

Primary zone (forward or reverse lookup) = create as type 0 and read as type 1

Stub zone = create as type 2 and read as type 3

This is another of the oddities that make WMI so much fun to work with. Easy when you know what’s happening but confusing when you don’t – just like so much with WMI. Does the W stand for Weird?  Smile

The Windows Server 2012 DNS cmdlets make this sooooo  much easier.

Posted by RichardSiddaway | with no comments
Filed under: ,

AD Management MEAP–chapter 17

My Learn AD Management in a Month of Lunches is moving on apace with the release of chapter 17 to the Early Access Process. This one covers AD replication

www.manning.com/siddaway3

Enjoy

International Module

The International module has an interesting set of cmdlets:
£> Get-Command -Module International | select Name

Name
----
Get-WinAcceptLanguageFromLanguageListOptOut
Get-WinCultureFromLanguageListOptOut
Get-WinDefaultInputMethodOverride
Get-WinHomeLocation
Get-WinLanguageBarOption
Get-WinSystemLocale
Get-WinUILanguageOverride
Get-WinUserLanguageList
New-WinUserLanguageList
Set-Culture
Set-WinAcceptLanguageFromLanguageListOptOut
Set-WinCultureFromLanguageListOptOut
Set-WinDefaultInputMethodOverride
Set-WinHomeLocation
Set-WinLanguageBarOption
Set-WinSystemLocale
Set-WinUILanguageOverride
Set-WinUserLanguageList

£> Get-WinHomeLocation | fl *

GeoId        : 242
HomeLocation : United Kingdom

£> Get-WinSystemLocale | fl *

Parent                         : en
LCID                           : 2057
KeyboardLayoutId               : 2057
Name                           : en-GB
IetfLanguageTag                : en-GB
DisplayName                    : English (United Kingdom)
NativeName                     : English (United Kingdom)
EnglishName                    : English (United Kingdom)
TwoLetterISOLanguageName       : en
ThreeLetterISOLanguageName     : eng
ThreeLetterWindowsLanguageName : ENG
CompareInfo                    : CompareInfo - en-GB
TextInfo                       : TextInfo - en-GB
IsNeutralCulture               : False
CultureTypes                   : SpecificCultures, InstalledWin32Cultures, FrameworkCultures
NumberFormat                   : System.Globalization.NumberFormatInfo
DateTimeFormat                 : System.Globalization.DateTimeFormatInfo
Calendar                       : System.Globalization.GregorianCalendar
OptionalCalendars              : {System.Globalization.GregorianCalendar, System.Globalization.GregorianCalendar}
UseUserOverride                : True
IsReadOnly                     : False

Digging into the formats and calendars
£> Get-WinSystemLocale | select -ExpandProperty NumberFormat

CurrencyDecimalDigits    : 2
CurrencyDecimalSeparator : .
IsReadOnly               : False
CurrencyGroupSizes       : {3}
NumberGroupSizes         : {3}
PercentGroupSizes        : {3}
CurrencyGroupSeparator   : ,
CurrencySymbol           : £
NaNSymbol                : NaN
CurrencyNegativePattern  : 1
NumberNegativePattern    : 1
PercentPositivePattern   : 1
PercentNegativePattern   : 1
NegativeInfinitySymbol   : -Infinity
NegativeSign             : -
NumberDecimalDigits      : 2
NumberDecimalSeparator   : .
NumberGroupSeparator     : ,
CurrencyPositivePattern  : 0
PositiveInfinitySymbol   : Infinity
PositiveSign             : +
PercentDecimalDigits     : 2
PercentDecimalSeparator  : .
PercentGroupSeparator    : ,
PercentSymbol            : %
PerMilleSymbol           : ‰
NativeDigits             : {0, 1, 2, 3...}
DigitSubstitution        : None

£> Get-WinSystemLocale | select -ExpandProperty DateTimeFormat

AMDesignator                     : AM
Calendar                         : System.Globalization.GregorianCalendar
DateSeparator                    : /
FirstDayOfWeek                   : Monday
CalendarWeekRule                 : FirstFourDayWeek
FullDateTimePattern              : dd MMMM yyyy HH:mm:ss
LongDatePattern                  : dd MMMM yyyy
LongTimePattern                  : HH:mm:ss
MonthDayPattern                  : d MMMM
PMDesignator                     : PM
RFC1123Pattern                   : ddd, dd MMM yyyy HH':'mm':'ss 'GMT'
ShortDatePattern                 : dd/MM/yyyy
ShortTimePattern                 : HH:mm
SortableDateTimePattern          : yyyy'-'MM'-'dd'T'HH':'mm':'ss
TimeSeparator                    : :
UniversalSortableDateTimePattern : yyyy'-'MM'-'dd HH':'mm':'ss'Z'
YearMonthPattern                 : MMMM yyyy
AbbreviatedDayNames              : {Sun, Mon, Tue, Wed...}
ShortestDayNames                 : {Su, Mo, Tu, We...}
DayNames                         : {Sunday, Monday, Tuesday, Wednesday...}
AbbreviatedMonthNames            : {Jan, Feb, Mar, Apr...}
MonthNames                       : {January, February, March, April...}
IsReadOnly                       : False
NativeCalendarName               : Gregorian Calendar
AbbreviatedMonthGenitiveNames    : {Jan, Feb, Mar, Apr...}
MonthGenitiveNames               : {January, February, March, April...}


£> Get-WinSystemLocale | select -ExpandProperty OptionalCalendars

MinSupportedDateTime : 01/01/0001 00:00:00
MaxSupportedDateTime : 31/12/9999 23:59:59
AlgorithmType        : SolarCalendar
CalendarType         : Localized
Eras                 : {1}
TwoDigitYearMax      : 2029
IsReadOnly           : False

MinSupportedDateTime : 01/01/0001 00:00:00
MaxSupportedDateTime : 31/12/9999 23:59:59
AlgorithmType        : SolarCalendar
CalendarType         : USEnglish
Eras                 : {1}
TwoDigitYearMax      : 2029
IsReadOnly           : False

And finally the language(s)
£> Get-WinUserLanguageList

LanguageTag     : en-GB
Autonym         : English (United Kingdom)
EnglishName     : English
LocalizedName   : English (United Kingdom)
ScriptName      : Latin script
InputMethodTips : {0809:00000809}
Spellchecking   : True
Handwriting     : False

Now you know where to go to find the cultural and locale settings are configured. The big question though is do you use the Set-* cmdlets in this module to modify these settings?  My suspicion is no because you would to modify a large number of settings to achieve consistency. The cmdlets may be useful for tweaking settings for particular tasks.

Windows Error Reporting Cmdlets

Windows Error Reporting (WER) captures software crash and hang data from Windows systems. The data is sent to Microsoft for analysis. The data captured by WER is used to identify those bugs that are affecting customers the most. Fixing those bugs benefits the whole Windows user community.

WER is an optional configuration during the installation of Windows and some other Microsoft products.

How can you tell if WER is configured on your machines?

Windows 8/2012 has a PowerShell module for working with WER configuration.

£> Get-Command -Module WindowsErrorReporting | select Name

 

You can view the current WER configuration:

£> Get-WindowsErrorReporting
Enabled

You can disable WER:

£> Disable-WindowsErrorReporting
True
£> Get-WindowsErrorReporting
Disabled

And you can enable WER:

£> Enable-WindowsErrorReporting
True
£> Get-WindowsErrorReporting
Enabled

These cmdlets are only available on Windows 8/2012 and above. The module is labelled as a script module but it is actually loaded as a dll so its unlikely to be portable to legacy versions of Windows.

Windows 8.1/2012 R2 RTM

Windows 8.1 & Windows Server 2012 R2 have gone RTM (Release To Manufacturing). The General Availability date is 18 October but it looks like you won’t be able to get your hands on it before then even with a TechNet/MDSN subscription.

No fair.

Why bother trying to keep up to date when Microsoft pull stunts like this. All other new versions of Windows as far back as I can remember have been made available on TechNet and MSDN within a month of RTM. 

Announcing RTM and then imposing nearly 2 month delay on making it available to the technical community won’t win many friends.

Posted by RichardSiddaway | with no comments

DSC Cheat Sheet

The big news item in PowerShell v4 is Desired State Configuration (DSC).  Its unlikely that I’ll be writing much here about DSC because its too close to what I do for a living at the moment.  I’m not giving away all my secrets  Smile

A quick reference cheat sheet for DSC has been published – details from

http://blogs.technet.com/b/stefan_stranger/archive/2013/08/26/powershell-v4-desired-state-configuration-cheat-sheet.aspx#!

Enjoy

Posted by RichardSiddaway | with no comments
Filed under:

Get-AdUser and –properties

The Get-ADuser cmdlet returns a small subset of properties by default:

PS> Get-ADUser -Identity Richard


DistinguishedName : CN=Richard,CN=Users,DC=Manticore,DC=org
Enabled           : True
GivenName         : Richard
Name              : Richard
ObjectClass       : user
ObjectGUID        : b94a5255-28d0-4f91-ae0f-4c853ab92520
SamAccountName    : Richard
SID               : S-1-5-21-3881460461-1879668979-35955009-1104
Surname           :
UserPrincipalName :
Richard@Manticore.org

 

You can use the –Properties parameter to return more properties

Get-ADUser -Identity Richard -Properties *

returns all properties

You can select a subset of properties by specifying their names

Get-ADUser -Identity Richard -Properties MemberOf, Country

 

If you want to use wildcards you need to use select

Get-ADUser -Identity Richard -Properties * | select last*

String Concatenation revisited

There a few ways to concatenate (join together) strings in PowerShell.

The obvious way is to use the concatenation operator  +

£> $a = "Hello"
£> $b = "World"
£> $a + " " + $b
Hello World

You can use string substitution

£> $a = "Hello"
£> $b = "World"
£> "$a $b"
Hello World

but remember that only works when you are using double quotes. Single quotes give you

£> '$a $b'
$a $b

You can also use the format operator   –f

£> $a = "Hello"
£> $b = "World"
£> "{0} {1}" -f $a, $b
Hello World

One final method is to put your strings into the elements of an array and use the –join operator

£> $d = @()
£> $d += "Hello"
£> $d += "World"
£> $d
Hello
World
£>
£> $d -join " "
Hello World

Which one should you use. Simple, whatever works best to solve your problem.

PowerShell often supplies multiple options to solve a problem. Use whichever you are most comfortable with and is the easiest to use in the context of the problem you are trying to solve.

Posted by RichardSiddaway | with no comments
Filed under:

PowerShell 4 available in October

Microsoft has announced that Windows 2012 R2, System Center 2012 R2 and Windows 8.1 will be on general availability on October 18. The important point being that Windows 2012 R2 & Windows 8.1 bring PowerShell v4

http://blogs.technet.com/b/server-cloud/archive/2013/08/14/windows-server-2012-r2-system-center-2012-r2-and-windows-intune-update-available-october-18th.aspx

If the pattern of previous releases is followed they will be available earlier through MSDN.

Pity it couldn’t have been 8 days earlier – would have made a nice birthday present

Posted by RichardSiddaway | with no comments
Filed under:

PowerShell Jump start pt 2

The second part of the PowerShell jump start – Tools and Scripting - was broadcast on 1 August

The recordings are now available from

http://www.microsoftvirtualacademy.com/training-courses/advanced-tools-scripting-with-powershell-3-0-jump-start#fbid=ueva0zXsYy9

The first set of recordings are still available at

http://www.microsoftvirtualacademy.com/training-courses/getting-started-with-powershell-3-0-jump-start#fbid=ueva0zXsYy9

I even get a mention Smile

Posted by RichardSiddaway | with no comments
Filed under:

AD Management in a Month of Lunches–chapter 16 MEAP

The next chapter of AD Management in a Month of Lunches has been released to MEAP

www.manning.com/siddaway3

Chapter 16 deals with Sites and Subnets

Enjoy

Finding the typo

A project I’m working on involves 1000s of lines of code, across numerous modules and folders. When I make changes, like everyone else, I sometimes mistype a command. When your system throws an error and its in nested several levels deep in your code and you’re not sure where it is – who you going to call?

Unfortunately, Ghostbusters can’t help you. But PowerShell can help.  I’d type [swtch] instead of [switch]. Nice easy way to find the spelling mistake. Open a PowerShell prompt in the top folder and

Get-ChildItem -Recurse -File | Select-String -Pattern "[swtch]" –SimpleMatch

You will get the file and line number containing the typo. Simple.

Posted by RichardSiddaway | with no comments
Filed under:

More prompts

In this post http://msmvps.com/blogs/richardsiddaway/archive/2013/07/21/fun-with-prompts.aspx I showed some of the things you can do to change the prompt in PowerShell.  I now use £> as my prompt.

What I hadn’t realised is that there is a PowerShell help file:

get-help about_Prompts

It builds on the information in my post including information on how the prompt changes when you enter a remote session

Posted by RichardSiddaway | 1 comment(s)
Filed under:
More Posts Next page »