PowerShell for Windows Admins

January 4, 2015  11:25 AM

Creating a PowerShellGet repository

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

In this post – http://blogs.msmvps.com/richardsiddaway/2014/12/21/delivering-powershell-code-with-the-november-preview/ – I showed how to use PowerShellGet, which is a feature new to PowerShell 5.0 to install PowerShell modules. By default PowerShelget uses the PowerShell gallery at https://www.powershellgallery.com as its source.

I don’t feel comfortable installing modules direct from a public gallery so I want my own.  I suspect that many organizations will want to use their own module repository rather than something on the Internet over which they have no control.

There are a number of options for setting up your own gallery.

You could create an online nuget feed. This is described in this post from the PowerShell team:

You could create your own nuget repository – an example of doing this can be found here – http://learn-powershell.net/2014/04/11/setting-up-a-nuget-feed-for-use-with-oneget/

After reading http://asaconsultant.blogspot.no/2014/05/build-your-local-powershell- module.html I decided to start with ProGet (http://inedo.com/proget/pricing) as it seemed simple and was installed locally so I could take it with me to do demos.

To keep things even simpler I went with the free version and used the download that also  installs SQL Express. The installer also can create a service INEDOPROGETSVC to host the web service ProGet will use. Set the Service to use the LocalSystem account so that it can access the location to which the modules will be published.

The ProGet default feed is nuget but you want your own for this game.  Its not obvious how to do this but open Proget administration page – http://localhost:81/administration

I’m using port 81 as this is running on my DSC server.

Click manage feeds and you’ll find a button labelled Create New Feed. Press the button.

You have 3 choices

A nuget feed

A chocolately feed

a npm feed (private registry)

Lets go with nuget.

After supplying a name and description I went with the defaults to complete the feed creation.

At this point PowerShellget can’t see the new repository so you need to register it.

£> Register-PSRepository -Name PowerShellModules -SourceLocation http://localhost:81/nuget/PowerShellModules -Installati
onPolicy Trusted

And it now shows in my list of PowerShell repositories

£> Get-PSRepository | fl Name, SourceLocation

Name           : PSGallery
SourceLocation : https://www.powershellgallery.com/api/v2/

Name           : MSPSGallery
SourceLocation : http://search.microsoft.com/default.aspx

Name           : PowerShellModules
SourceLocation : http://localhost:81/nuget/PowerShellModules

You need to set a location to which modules will be published

Set-PSRepository -Name PowerShellModules -PublishLocation ‘http://localhost:81/nuget/PowerShellModules’

Now to try and publish a module.

 I’m going to use the Pester module I downloaded in the previous article:

£> Publish-Module -Name Pester -NuGetApiKey “Admin:Admin” -Repository PowerShellModules -Verbose
VERBOSE: Repository details, Name = ‘PowerShellModules’, Location = ‘http://localhost:81/nuget/PowerShellModules’;
IsTrusted = ‘True’; IsRegistered = ‘True’.
VERBOSE: Repository details, Name = ‘PowerShellModules’, Location = ‘http://localhost:81/nuget/PowerShellModules’;
IsTrusted = ‘True’; IsRegistered = ‘True’.
VERBOSE: Repository details, Name = ‘PowerShellModules’, Location = ‘http://localhost:81/nuget/PowerShellModules’;
IsTrusted = ‘True’; IsRegistered = ‘True’.
VERBOSE: Module’Pester’ was found in ‘C:\Program Files\WindowsPowerShell\Modules\Pester’.
VERBOSE: Loading module from path ‘C:\Users\Richard\AppData\Local\Temp\409922302\Pester\Pester.psm1’.
VERBOSE: Repository details, Name = ‘PowerShellModules’, Location = ‘http://localhost:81/nuget/PowerShellModules’;
IsTrusted = ‘True’; IsRegistered = ‘True’.
VERBOSE: Repository details, Name = ‘PowerShellModules’, Location = ‘http://localhost:81/nuget/PowerShellModules’;
IsTrusted = ‘True’; IsRegistered = ‘True’.
VERBOSE: Using the specified source names : ‘PowerShellModules’.
VERBOSE: Getting the provider object for the OneGet Provider ‘NuGet’.
VERBOSE: The specified Location is ‘http://localhost:81/nuget/PowerShellModules’ and OneGetProvider is ‘NuGet’.
VERBOSE: Performing the operation “Publish-Module” on target “Version ‘3.2.0’ of module ‘Pester'”.
VERBOSE: Successfully published module ‘Pester’ to the module publish location

The -NuGetApiKey “Admin:Admin”  is the default and you’d want to change that for a production system.

Finally test the repository contents

£> Find-Module -Repository PowerShellModules

Version    Name                                Repository
——-    —-                                ———-
3.2.0      Pester                              PowerShellModules

January 1, 2015  5:25 AM

PowerShell in 2015

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

See Don Jones’ predictions for PowerShell in 2015 – http://blogs.technet.com/b/heyscriptingguy/archive/2015/01/01/powershell-predictions-for-2015.aspx

December 31, 2014  8:51 AM

PowerShell Summit NA 2015

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

We will be getting extra capacity for the PowerShell Summit NA 2015 in Charlotte. The extra places should become available 11 January 2015 – see http://powershell.org/wp/2014/12/30/powershell-summit-n-a-2015-additional-capacity/

for details.

Please check the powershell.org site for further news

December 31, 2014  8:42 AM

PowerShell review of 2014

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

See my review of 2014 from a PowerShell perspective on the Scripting Guy blog – http://blogs.technet.com/b/heyscriptingguy/archive/2014/12/31/2014-a-powershell-year-in-perspective.aspx

December 30, 2014  1:14 PM

More on dates

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

My recent post on date conversions seems to have generated a fair bit of confusion and discussion. The original task was to read in a string from a CSV file that contained a date in UK format – DD/MM/YYYY and reformat it to a string is US format – MM/DD/YYYY

As I showed you can’t use [datetime] type accelerator for this as it expects the date string to be in US format.

A number of people pointed out that you can use the –Date parameter on Get-Date

£> $strUK = ’25/12/2014′
£> Get-Date -Date $strUK

25 December 2014 00:00:00

Now if you want that output as a string in US format

£> Get-Date -Date $strUK -Format “MM/dd/yyyy”

Use a variable to contain that data and you can work with it as you wish.

You need to be aware that using –Date on Get-Date is culture aware:

£> Get-Date -Date ’25/12/2014′

25 December 2014 00:00:00
£> Get-Date -Date ’12/25/2014′
Get-Date : Cannot bind parameter ‘Date’. Cannot convert value “12/25/2014” to type “System.DateTime”. Error: “String was not recognized as a valid DateTime.”
At line:1 char:16
+ Get-Date -Date ’12/25/2014′
+                ~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (:) [Get-Date], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.GetDateCommand

December 30, 2014  9:10 AM

ANR and AD searches

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

A comment on this post –  http://richardspowershellblog.wordpress.com/2014/12/29/using-givenname-and-surname-instead-of-samaccountname/

suggested using ANR – Ambiguous Name Resolution as a method of searching AD.

ANR provides a fuzzy search mechanism for AD – think wildcard search. If you perform an ANR search you’ll get anything matches – using your input as the root of the wildcard search – across display name, given name, name, samaccountname and surname.

Consider the searches shown last time based on the name Dave Green. Lets perform a ANR search on the first name

£> Get-ADUser -Filter {anr -eq ‘Dave’} | select Name

Jo Daven
Dave Green
Dave Brown
Dave White

Get-ADUser -LDAPFilter “(anr=Dave)” | select Name

will give the same result.  In my AD I get 3 results. Any account where any of the names listed above that start with the letters ‘Dave’  will be returned. Notice that in one of the results the letters are in the surname not the first name.

Similar issues if you perform ANR searches based on surname

£> Get-ADUser -LDAPFilter “(anr=Green)” | select Name

Dave Green
Fred Green
Dale Greensmith


Get-ADUser -Filter {anr -eq ‘Green’} | select Name

This time notice that the surname Greensmith is returned as well as Green.

You could use the whole name:

£> Get-ADUser -LDAPFilter “(anr=Dave Green)” | select Name


£> Get-ADUser -Filter {anr -eq ‘Dave Green’} | select Name

Dave Green
Dave Greenly

NOTE: I created the Dave Greenly account after the previous searches which is why it didn’t show earlier.

ANR searches are also slower than searching on specific attributes because a number of properties are being searched.

An ANR search is a good first step if  you’re not sure what you’re looking for but you will usually need to refine the search using –Identity parameter or more specific filters if you if you want to get to a single object.

December 29, 2014  5:50 AM

Using GivenName and Surname instead of samAccountName

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

A recent comment on this post – https://richardspowershellblog.wordpress.com/wp-admin/post.php?post=2762&action=edit – asked about using the given name and surname rather than the samAccountName in Get-ADUser.

Get-ADUser has 4 options when using the – Identity parameter:

Account name = samAccountNmae

Distinguished Name


Security identifier = SID.

Using the given name and surname. on the surface doesn’t seem possible BUT (and there’s always a but with PowerShell) you can use the –Filter or –LDAPFilter parameters.

Where you know the samAcccountName you can do this:

Get-ADUser -Identity gdreen

Working with the names you could try this:

Get-ADUser -Filter {GivenName -eq ‘Dave’ -and Surname -eq ‘Green’}

Alternatively, you could use an LDAP filter:

Get-ADUser -LDAPFilter “(&(GivenName=Dave)(Sn=Green))”

The LDAP syntax is a bit more complex but you can parse it as

(GivenName=Dave) AND (Sn=Green)

You have to use the LDAP name, Sn, for the Surname property rather than the more friendly property name that the –Filter parameter allows.

If you wanted to modify the code in the original article to use this approach:

$users = Import-Csv -Path C:\Scripts\adtest.csv

foreach ($user in $users) {
$fname = $user.GivenName
$lname = $user.Surname

Get-ADUser -Filter {GivenName -eq $fname  -and Surname -eq $lname} -Properties * |
select SamAccountName, Division, Office, City

I’ve found that its easier to substitute variables into the filter rather than try and and use the object from the CSV file directly.

The LDAP filter version would be

$users = Import-Csv -Path C:\Scripts\adtest.csv

foreach ($user in $users) {

Get-ADUser -LDAPFilter “(&(GivenName=$($user.GivenName))(Sn=$($user.Surname)))” -Properties * |
select SamAccountName, Division, Office, City

In this case you’re substituting into a string and it works quite nicely.

December 23, 2014  12:38 PM

Date conversions

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Saw a question regarding the conversion of dates in UK format DD/MM/YYYY to US format MM/DD/YYYY

Using 25 December 2014 as an example

If you have a dat in US format you can do this

£> $sd = ’12/25/2014′
£> $d = [datetime]$sd
£> $d

25 December 2014 00:00:00

$d = [datetime]$sd   creates a datetime object

If you try that in UK format

£> $sduk = ’25/12/2014′
£> $d = [datetime]$sduk
Cannot convert value “25/12/2014” to type “System.DateTime”. Error: “String was not recognized as a valid DateTime.”
At line:1 char:1
+ $d = [datetime]$sduk
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvalidCastParseTargetInvocationWithFormatProvider

It fails.

.NET expects strings representing dates to be in US format.

£> [datetime]’25 December 2014′

25 December 2014 00:00:00

works but the data isn’t in that format.

The easiest way I know to create a date object when you have UK format strings would be:

£> $sd = ’25/12/2014′ -split ‘/’
£> $sd
£> $d = Get-Date -Day $sd[0] -Month $sd[1] -Year $sd[2]
£> $d

25 December 2014 18:36:05

December 23, 2014  10:18 AM

Merry Christmas from the PowerShell team

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The PowerShell team have produced wave 9 of the DSc resource kit – just in time for Christmas – http://blogs.msdn.com/b/powershell/archive/2014/12/17/another-holiday-present-from-the-powershell-team-dsc-reskit-wave-9.aspx

This wave contains a number of new resources and some updates to existing resources including the Exchange resource.

You can download the latest version of the resource kit from  https://gallery.technet.microsoft.com/DSC-Resource-Kit-All-c449312d

The team’s blog post states that you should check for the GA update (which is minimum requirement for running the DSC res kit) by testing to see if KB2883200 is installed. This won’t work if you’ve built you system using Windows media that incorporates the update.

A better test is to look at the build number. It should be 9400 or higher. You can see this by using $psversiontable

£> $PSVersionTable

Name                           Value
—-                           —–
PSVersion                      4.0
WSManStackVersion              3.0
CLRVersion                     4.0.30319.34014
BuildVersion                   6.3.9600.17400
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion      2.2

The version is  6.3.9600.17400  where 6.3 = Windows 2012 R2 and 9600 = the build

You can also use WMI

£> Get-CimInstance -ClassName Win32_Operatingsystem | Format-List BuildNumber, Version
BuildNumber : 9600
Version     : 6.3.9600

December 22, 2014  2:34 PM

European Summit 2015 call for topics #2

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The call for topics for the European PowerShell Summit is still open – http://powershell.org/wp/2014/11/24/call-for-presentations-for-powershell-summit-europe-2015/

Please submit your topics by the deadline of 11 January 2015.

A few people have suggested subjects for topics they would like to see:

Azure automation with SAM and/or workflows

SCCM advanced scripting

DSC advanced scripting


Test Driven Deployment with Pester

Deep dive integration of .NET and Win32API with PowerShell

Could you provide a session on one of these or another topic?

We will have a number of established speakers and PowerShell personalities attending but at all of the powershell.org Summits we like to take the opportunity to encourage new speakers.

If you’re not sure of a topic’s suitability or whether you should submit please get in touch and I’ll be happy to discuss

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: