PowerShell for Windows Admins


January 18, 2015  10:11 AM

PowerShell Summit NA 2015 Agenda changes

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

We’ve had to make some minor changes to the Summit agenda – the revised schedule is shown on the event web site – http://eventmgr.azurewebsites.net/event/home/PSNA15

January 18, 2015  5:02 AM

PowerShell Heroes 2015

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

Powershell.org has announced the 2015 list of PowerShell Heroes- http://powershell.org/wp/2015/01/17/announcing-our-2015-powershell-heroes/

These are people who have made an outstanding contribution to the PowerShell community but have not been recognised in other ways (such as an MVP award)

Please join me in congratulating them


January 12, 2015  11:41 AM

Event log dates

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

You can use Get-EventLog to query the event logs on you system

Get-EventLog -LogName System

One frequent task is to check if events occurred during a specific timespan. You may feel that you need to use a where-object filter to do this but there is a simple method.

Get-EventLog -LogName System -After (Get-Date -Date ‘1/1/2015′)

Will return all events after the given date. if you don’t give a time your results start at midnight.

Get-EventLog -LogName System –Before (Get-Date -Date ’10/1/2015′)

Will return all events before 10 January 2015.

You ususally use –Before in conjunction with –After to specify a data range

Get-EventLog -LogName System -After (Get-Date -Date ‘1/1/2015′) -Before (Get-Date -Date ’10/1/2015′)

You can make these ranges quite specific

Get-EventLog -LogName System -After (Get-Date -Date ’10/1/2015 14:31:00′) -Before (Get-Date -Date ’10/1/2015 15:00:00′)


January 11, 2015  5:21 AM

Add-Computer is your friend

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

When spinning up new machines and joining them to the domain at least 2 reboots are required. One when you rename the machine (Windows used to let you specify the name at install time – the removal of that feature was a step backwards) and the other when you join it to the domain.

I was looking at the help file for Add-Computer and discovered you can rename the machine as you join it to the domain. Miss one reboot and get the build finished quicker.

$cred = Get-Credential manticore\richard
Add-Computer -Credential $cred -DomainName manticore -NewName W12R2Web02 -Restart –Force

Nice and simple – I like this.


January 9, 2015  11:30 AM

foreach, pipelines and $_

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

I’ve recently seen a few questions where people have been using a pipeline inside a foreach loop and experienced problems when they’ve tried to access properties on the looping objects. To illustrate we’ll start with a CSV file containing emailaddresses and job titles.

£> Import-Csv -Path C:\Test\userdata.txt

emailaddress             title
————             —–
gdreen@Manticore.org     Boss
dbrown@Manticore.org     Underling
dwhite@Manticore.org     Underling
jdaven@Manticore.org     Minion
fgreen@Manticore.org     Minion
dgreensmth@Manticore.org Minion
dgreenly@Manticore.org   Minion

This is definitely an employee friendly organisation

At the moment AD doesn’t contain any job title information

£> $users = Import-Csv -Path C:\Test\userdata.txt

foreach ($user in $users){
$mail = $user.EmailAddress

Get-ADUser -Filter {EmailAddress -eq $mail} -Properties Title |
select Name, Title

}

Name                                      Title
—-                                      —–
Dave Green
Dave Brown
Dave White
Jo Daven
Fred Green
Dale Greensmith
Dave Greenly

The approach that causes problems is this:

£> $users = Import-Csv -Path C:\Test\userdata.txt

foreach ($user in $users){
$mail = $user.EmailAddress

Get-ADUser -Filter {EmailAddress -eq $mail} -Properties Title |
foreach {Set-ADUser -Identity $_ -Title $_.Title} |

Get-ADUser -Filter {EmailAddress -eq $mail} -Properties Title |
select Name, Title
}

Name                                      Title
—-                                      —–
Dave Green
Dave Brown
Dave White
Jo Daven
Fred Green
Dale Greensmith
Dave Greenly

When you use foreach as a keyword the $_ and $psitem variables aren’t available. These variables represent the current object on the pipeline.  The foreach keyword loop doesn’t have a pipeline as such.

Inside the foreach a pipeline is created

Get-ADUser -Filter {EmailAddress -eq $mail} -Properties Title |
foreach {Set-ADUser -Identity $_ -Title $_.Title -PassThru} |
select Name, Title

$_ is used correctly to identify the object on which Set-ADUser is to work – its the current object on the pipeline.

The use of  $_.Title  to set the user’s job title is where the problem really bites.  $_.Title  refers to the Title property of the current object on the pipeline so you are setting the Title to its existing value.

You need to reach back to the $user object that represents the current object from the set you are looping through with foreach to get the correct value

£> $users = Import-Csv -Path C:\Test\userdata.txt

foreach ($user in $users){
$mail = $user.EmailAddress

Get-ADUser -Filter {EmailAddress -eq $mail} -Properties Title |
foreach {Set-ADUser -Identity $_ -Title $user.Title} |

Get-ADUser -Filter {EmailAddress -eq $mail} -Properties Title |
select Name, Title
}

Name                                      Title
—-                                      —–
Dave Green                                Boss
Dave Brown                                Underling
Dave White                                Underling
Jo Daven                                  Minion
Fred Green                                Minion
Dale Greensmith                           Minion
Dave Greenly                              Minion

 

You’ll see similar problems if you have nested foreach-object loops or a switch statement inside a foreach-object loop.  $_ always refers to the current context and you have to either reach back to the looping variable in the csae of a foreach or set variables on the data in the outer foreach before entering the nested foreach.

 

 


January 7, 2015  2:27 PM

DHCP scope lease time

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
DHCP, Powershell, Windows Server 2012, Windows Server 2012 R2

I wanted to reduce the lease time on a DHCP scope

$lt = New-TimeSpan -Hours 12
Set-DhcpServerv4Scope -ScopeId 10.10.54.0 -LeaseDuration $lt

You could even make it a one liner if you wished

Set-DhcpServerv4Scope -ScopeId 10.10.54.0 –LeaseDuration (New-TimeSpan -Hours 12)


January 6, 2015  11:50 AM

A use for default parameters – default powershellget repository

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

When you use Find-Module by default all repositories are searched

£> Find-Module -Name Pester | ft Version, Name, Repository -a

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

If you don’t give a module name that could be a lot of data to sort through. If you are running an internal repository you may want to check that repository first and only use other repositories if that one doesn’t contain the module.

£> Find-Module -Name Pester -Repository PowerShellModules  | ft Version, Name, Repository -a

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

This means that you have to type the repository name each time. It would be better if you could make a particular repository the default.  One way to do this is to define default parameters. This functionality was introduced in PowerShell 3.0

£> $PSDefaultParameterValues.Add(“Find-Module:Repository”, ‘PowerShellModules’)
£> $PSDefaultParameterValues

Name                           Value
—-                           —–
Find-Module:Repository         PowerShellModules
£> Find-Module -Name Pester | ft Version, Name, Repository -a

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

You can override the default if you wish

£> Find-Module -Name Pester -Repository PSGallery  | ft Version, Name, Repository -a

Version Name   Repository
——- —-   ———-
3.2.0   Pester PSGallery

You can do the same for install-module so that it will default to your internal repository

£> $PSDefaultParameterValues.Add(“Install-Module:Repository”, ‘PowerShellModules’)
£> Install-Module -Name Pester -Force -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: 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: In PSModule Provider – ‘Get-InstalledPackage’.
VERBOSE: The specified Location is ‘NuGet’ and OneGetProvider is ‘NuGet’.
VERBOSE: Downloading module ‘Pester’ with version ‘3.2.0’ from the repository
http://localhost:81/nuget/PowerShellModules’.
VERBOSE: NuGet: Installing ‘Pester 3.2.0′.
VERBOSE: NuGet: Successfully installed ‘Pester 3.2.0′.
VERBOSE: Module ‘Pester’ was installed successfully.

-Force was used as the module is already installed.

Your default parameters now look like this

£> $PSDefaultParameterValues

Name                           Value
—-                           —–
Find-Module:Repository         PowerShellModules
Install-Module:Repository      PowerShellModules

Add the two lines

$PSDefaultParameterValues.Add(“Find-Module:Repository”, ‘PowerShellModules’)

$PSDefaultParameterValues.Add(“Install-Module:Repository”, ‘PowerShellModules’)

To your profile and your defaults will be available every time you start PowerShell


January 6, 2015  2:56 AM

PowerShell Summit Europe 2015–topic submissions

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

Topic submissions for the PowerShell Summit Europe are still open. If you want to be considered as a speaker please submit your topic very soon.

At the moment there aren’t enough submissions to enable us to put on a quality event. The 2014 European Summit was an excellent event with many good sessions – now is the time to submit your sessions. We need your sessions.

We have a policy of accepting sessions from new speakers as well as established experts. It’s not who you are but the quality of the session that counts.

Details on how to submit session proposals are available here

http://powershell.org/wp/2014/11/24/call-for-presentations-for-powershell-summit-europe-2015/

Please submit your proposals soon as we can’t run the European PowerShell Summit without them


January 5, 2015  10:33 AM

Accessing your PowerShellget repository from another machine

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

So far the new PowerShellGet repository has been accessed from the local machine. You need to register the new repository on each machine from which you want to access it.

Register-PSRepository -Name PowerShellModules -SourceLocation http://W12R2DSC:81/nuget/PowerShellModules -InstallationPolicy Trusted

The only change to is substituting the name of the server for localhost in the source location URI.

NOTE: you will need to ensure that the Windows firewall is either off or allows the appropriate traffic through to the server hosting you repository

You can use the new repository

PS C:\Windows\system32> Get-PSRepository | ft Name, SourceLocation -AutoSize

Name              SourceLocation
—-              ————–
PSGallery         https://www.powershellgallery.com/api/v2/
MSPSGallery       http://search.microsoft.com/default.aspx
PowerShellModules http://w12r2dsc:81/nuget/PowerShellModules

And see the modules

PS C:\Windows\system32> Find-Module -Name Pester | ft -a

Version Name   Repository        Description
——- —-   ———-        ———–
3.2.0   Pester PSGallery         Pester provides a framework
3.2.0   Pester PowerShellModules Pester provides a framework

And install modules

PS C:\Windows\system32> Install-Module -Name pester -Repository PowerShellModules

PS C:\Windows\system32> Get-Module -ListAvailable pest* | ft -a
Directory: C:\Program Files\WindowsPowerShell\Modules
ModuleType Version Name   ExportedCommands
———- ——- —-   —————-
Script     3.2.0   Pester {Describe, Context, It, Should…}


January 5, 2015  5:01 AM

Working with multiple PowerShellGet repositories

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

In http://blogs.msmvps.com/richardsiddaway/2015/01/04/creating-a-powershellget-repository/  I showed how to create a repository to use with PowerShellGet.  At the end of that article PowerShellGet would search all of the defined repositories for a module

£> Find-Module -Name Pester | Format-Table Version, Name, Repository -AutoSize

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

If you delete the Pester module and want to re-install it you need to specify the repository otherwise you get an error:

£> Install-Module -Name Pester -Verbose
VERBOSE: The -Repository parameter was not specified.  PowerShellGet will use all of the registered repositories.
VERBOSE: Getting the provider object for the OneGet Provider ‘NuGet’.
VERBOSE: The specified Location is ‘https://www.powershellgallery.com/api/v2/’ and OneGetProvider is ‘NuGet’.
VERBOSE: Getting the provider object for the OneGet Provider ‘NuGet’.
VERBOSE: The specified Location is ‘http://search.microsoft.com/default.aspx’ and OneGetProvider is ‘NuGet’.
VERBOSE: Getting the provider object for the OneGet Provider ‘NuGet’.
VERBOSE: The specified Location is ‘http://localhost:81/nuget/PowerShellModules’ and OneGetProvider is ‘NuGet’.
WARNING: ‘Pester’ matched module ‘Pester/3.2.0′ from provider: ‘PSModule’, repository
https://www.powershellgallery.com/api/v2/’
WARNING: ‘Pester’ matched module ‘Pester/3.2.0′ from provider: ‘PSModule’, repository
http://localhost:81/nuget/PowerShellModules’
OneGet\Install-Package : Unable to install, multiple modules matched ‘Pester’. Please specify a single -Repository.
At C:\Windows\system32\WindowsPowerShell\v1.0\Modules\PowerShellGet\PSGet.psm1:615 char:21
+             $null = OneGet\Install-Package @PSBoundParameters
+                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (Microsoft.Power….InstallPackage:InstallPackage) [Install-Package], E
xception
+ FullyQualifiedErrorId : DisambiguateForInstall,Microsoft.PowerShell.OneGet.CmdLets.InstallPackage

 

£> Install-Module -Name Pester -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: 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: In PSModule Provider – ‘Get-InstalledPackage’.
VERBOSE: Performing the operation “Install-Module” on target “Version ‘3.2.0’ of module ‘Pester'”.
VERBOSE: The specified Location is ‘NuGet’ and OneGetProvider is ‘NuGet’.
VERBOSE: Downloading module ‘Pester’ with version ‘3.2.0’ from the repository
http://localhost:81/nuget/PowerShellModules’.
VERBOSE: NuGet: Installing ‘Pester 3.2.0′.
VERBOSE: NuGet: Successfully installed ‘Pester 3.2.0′.
VERBOSE: Module ‘Pester’ was installed successfully.


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: