PowerShell for Windows Admins


July 21, 2013  9:48 AM

Fun with prompts

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

At the PowerShell Jumpstart event there were a lot questions asking how Jeffrey Snover managed to get a dollar sign – $ – as his prompt. A lot of them centred on asking if this was a PowerShell v4 thing.

Its not a V4 thing. You have been able to change the prompt since v1.

The PowerShell prompt is by default the path of your current folder. This can easily take half the width if the screen if if you are several layers deep

You can change the PowerShell prompt by running a prompt function. For instance to change the prompt to a dollar sign

PS C:\Windows\system32> function prompt {
>> “$ ”
>> }
>>
$

I move the folder information into the header

$ function prompt {
>> “$ ”
>> $host.ui.RawUI.WindowTitle = $(get-location)
>> }
>>

Other useful tricks – are you running 32 bit or 64 bit PowerShell? Its easy to forget if you have numerous consoles open.

PS>function prompt {
>> if ([System.IntPtr]::Size -eq 8) {$size = ’64 bit’}
>> else {$size = ’32 bit’}
>> $host.ui.RawUI.WindowTitle = “$size $(get-location)”
>> “$ ”
>> }
>>
$

This adds 64 bit or 32 bit to the console header. As well as the location.

One final option is to show if you are running that console elevated or not.

function prompt {
if ([System.IntPtr]::Size -eq 8) {$size = ’64 bit’}
else {$size = ’32 bit’}

$currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
$secprin = New-Object Security.Principal.WindowsPrincipal $currentUser
if ($secprin.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator))
{$admin = ‘Administrator’}
else {$admin = ‘non-Administrator’}

$host.ui.RawUI.WindowTitle = “$admin $size $(get-location)”
“$ ”
}

The Windows identity of the current user is retrieved and used to create a security principal object. This is used to test is the security principal is in the Administrator role.

Add this prompt function to your profile and you get some useful reminders for while you are working and a minimalist prompt.

July 21, 2013  9:03 AM

PowerShell Deep Dives is published

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

PowerShell Deep Dives is a collection of chapters from PowerShell authorities world wide. The book is now published http://manning.com/hicks/

The royalties from the book all go to Save the Children

If you’ve bought a copy thank you for your support – your book will be with you soon. If you haven’t got a copy please buy one. You will be supporting a very good cause and getting your hands on PowerShell material you won’t find elsewhere.


July 17, 2013  2:05 PM

Internet Connection

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Can you find the network adapter on your machine that’s connected to the Internet? On a Windows 8/2012 machine its fairly simple:

PS> Get-NetConnectionProfile -IPv4Connectivity Internet

Name : NetworkName
InterfaceAlias : AdapterName
InterfaceIndex : 12
NetworkCategory : Private
IPv4Connectivity : Internet
IPv6Connectivity : LocalNetwork

What else can you discover?

The important information is the InterfaceIndex

Get-NetAdapter -InterfaceIndex 12

shows the NIC information such as name, MAC address and speed (similar to Win32_NetworkAdapter)

Get-NetAdapterAdvancedProperty -Name name

shows buffer data

Get-NetAdapterStatistics -Name name

shows transmitted data

Get-NetIPConfiguration -InterfaceIndex 12

pulls the IP configuration

This just scratches the surface to the networking modules in Windows 8/2012

The modules are based on new WMI classes for the most part so you won’t find them on legacy operating systems even with WMF 3 loaded.


July 16, 2013  12:51 PM

CSV fields with spaces in the field name

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

CSV files are one way we can get data into our scripts – but sometimes when we get given a CSV file it has spaces in the field name e.g.

“Area Number”
1
2
3
2
3
1
5

Dealing with this can be a bit awkward but you can access the field like this:

Import-Csv area.csv |
foreach {
$_.’Area Number’
}

Double quotes work as well

The trick comes if you need to add the field into a string

Import-Csv area.csv |
foreach {
“Area = ” + $_.’Area Number’ + ” is available”
}

String concatenation works. Alternatively, if you want to use string substitution:

Import-Csv area.csv |
foreach {
“Area = $($_.’Area Number’) is available”
}


July 15, 2013  12:32 PM

AD Management MEAP

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

A new MEAP was released last week for AD Management in a Month of Lunches. Chapters 1-15 are now available

http://www.manning.com/siddaway3/


July 8, 2013  3:31 PM

Case sensitive operators

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

PowerShell is more or less case insensitive so the operation in my previous post

$_.Substring(3,1) -ne “T”

will trigger on “T” or “t”
If you only want the uppercase version to fail then you can use the case sensitive version of –ne which is –cne.
This changes the script to:

function ptest {
[CmdletBinding()]
param(
[ValidateScript({$_.Substring(3,1) -cne “T” })]
[string]$server
)
Write-Host “$server”
}

You can read more about the comparison operators in
get-help about_Comparison_Operators


July 8, 2013  1:39 PM

Validating parameters

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

PowerShell provides a number of ways of validating the values input to the parameters in your scripts. One such way is Validate script. I came across an interesting question where the inquirer wanted to test an input parameter and throw an error if the 4th character was a “T”

One solution is:

function ptest {
[CmdletBinding()]
param(
[ValidateScript({$_.Substring(3,1) -ne “T” })]
[string]$server
)
Write-Host “$server”
}

Alternatively use a regular expression


July 7, 2013  2:52 PM

Measure-Object

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

One cmdlet that I don’t think gets used enough is Measure-Object. This enables you to find the minimum, maximum, sum and average of a set of numbers coming down the pipeline

PS> 1..12 | Measure-Object -Sum -Maximum -Minimum -Average

Count : 12
Average : 6.5
Sum : 78
Maximum : 12
Minimum : 1
Property :

You can also work with properties:

PS> Get-Process | Measure-Object -Property Handles -Sum -Maximum -Minimum -Average

Count : 59
Average : 481.101694915254
Sum : 28385
Maximum : 2734
Minimum : 0
Property : Handles

You don’t need to select all of the options.

PS> (Get-Process | Measure-Object -Property Handles -Average).Average
480.593220338983

Next time you need to find the maximum, minimum, average or sum remember measure-object instead of spending time writing your own routines


July 7, 2013  1:01 PM

Deleting a file with WMI

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Following on from the last post this is how you can delete a file.

Use the same file structure as previously

This time you need to use the CIM_DataFile class. It’s one of the few classes I’ve found that doesn’t have a Win32_ equivalent.

The class has a Delete method. Assuming you know the full path to the file

Get-CimInstance -ClassName CIM_DataFile -Filter “Name=’C:\\Expendable\\Target1\\proc.txt’ ” |
Invoke-CimMethod -MethodName Delete

You can perform most actions on files and folders using WMI but you can’t create a file or a folder


July 7, 2013  12:41 PM

Deleting Folders with WMI

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

I recently saw a question about deleting folders with WMI.

Let’s create a file structure we’re happy to delete

New-Item -Path c:\ -Name Expendable -ItemType Directory
New-Item -Path c:\Expendable -Name Target1 -ItemType Directory
New-Item -Path c:\Expendable -Name Target2 -ItemType Directory

Get-Process | Out-File -FilePath c:\Expendable\Target1\proc.txt
Get-Service | Out-File -FilePath c:\Expendable\Target2\serv.txt

A look through the WMI classes brings out Win32_Directory

PS> $class = Get-CimClass -ClassName Win32_Directory
PS> $class.CimClassMethods | ft -a

Name ReturnType Parameters
—- ———- ———-
TakeOwnerShip UInt32 {}
ChangeSecurityPermissions UInt32 {Option, SecurityDescriptor}
Copy UInt32 {FileName}
Rename UInt32 {FileName}
Delete UInt32 {}
Compress UInt32 {}
Uncompress UInt32 {}
TakeOwnerShipEx UInt32 {Recursive, StartFileName, StopFileName}
ChangeSecurityPermissionsEx UInt32 {Option, Recursive, SecurityDescriptor,…}
CopyEx UInt32 {FileName, Recursive, StartFileName, StopFileName}
DeleteEx UInt32 {StartFileName, StopFileName}
CompressEx UInt32 {Recursive, StartFileName, StopFileName}
UncompressEx UInt32 {Recursive, StartFileName, StopFileName}
GetEffectivePermission Boolean {Permissions}

The Delete method looks promising

CIM uses inert objects so we need to get an instance an pipe it into Invoke-CimMethod

Get-CimInstance -ClassName Win32_Directory -Filter “Name=’C:\\Expendable'” |
Invoke-CimMethod -MethodName Delete

When you delete a folder like this – the folder, its contents, any subfolders and their contents are deleted. They don’t appear in the recycle bin either so its a one way trip


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: