Posts Tagged ‘powershell’

PostHeaderIcon How To Run Scripts With PowerShell

If you’re new to PowerShell, some of the first things you’ll want to do are find your way around, find the commands, aliases.  Some of the concepts, like figuring out the pipe, and how to use it, can be a struggle.

Before long, though, you’re going to start getting used to it, and then you’ll want to start saving your work so you can reuse it.  You can do that by saving a text file with a .ps1 extension.  A ps1 is just a PowerShell script.  You don’t have to have anything else in it other than the same commands you use when you’re typing in to the PowerShell console.  In fact, anything that you can type into the console can be typed into a .ps1 file exactly the same way, and then run.

So this is for my PowerShell people that are just getting to know their way around, and need to start either working with PowerShell profiles or start running PS1 files.  Once you’ve gotten the script doing what you want, you can also run a PowerShell script as a scheduled task.

Here are some things you can (and should) do to work with ps1 files, including your profile:

Tip 1:  Set the Execution Policy on One Machine (Use Group Policy for a Domain)

PowerShell takes security seriously.  By default, you cannot run scripts at all, not even your profile.  The execution policy defines what scripts you can run. 

There are four settings for the execution policy.  You can set this to whatever you like, but it may have already been set for you in your environment via group policy.  Here are the different settings you can set the execution policy to, from most restrictive to least

An execution policy is applied to a scope.  There are three scopes you can apply the policy setting to:  LocalMachine (the computer), CurrentUser (the user), or Process (the currently running PowerShell session and the policy goes away once the window is closed.)  If you don’t specify a scope, you’re setting the LocalMachine policy.  Also, there is a preference in applying scopes:  Process overrides CurrentUser, which in turn overrides LocalMachine.

  • Undefined – If all scopes are undefined then it is set to the default, which is restricted.
  • Restricted – No scripts may run at all.
  • AllSigned – All scripts that have a digital signature may run.
  • RemoteSigned – Local scripts may run.  Scripts executed from the network must be digitally signed.
  • Unrestricted – All scripts may run.
  • Bypass – All scripts may run, and all warnings and prompts are disabled.

Which execution policy you set is up to you.  Usually a prudent choice is RemoteSigned.  Here’s how you set it

Set-ExecutionPolicy  RemoteSigned

Easy, right?  Well without setting the execution policy, all of your scripts, even your own profile, won’t run at all.

Tip 2: Save Work You Will Use Again in a Script

If you’re not already using the Integrated Scripting Environment (ISE), you should really get to know it.

When you go to start PowerShell, instead look for the option to start PowerShell ISE.  Using the ISE gives you an opportunity to save the work that you’ve been doing often, and you can run bits and pieces of your script as you’re writing it to make sure it’s working as you intend.

Tip 3: Use a PowerShell Profile

If you are starting to get into writing down the things you do, you should look at creating a profile.  The profiles (there are multiples actually) are very useful for defining functions, mapping PSDrives, and importing modules.  If you haven’t setup your profile yet, I’ve written a post outlining how to setup your PowerShell profile

Tip 4: Use Comments, Even For Scripts Only You Will Use

When typing out your scripts into a ps1 file, it’s a great idea to use comments liberally.  Even if you think you will not be sharing this script with others, you will likely be sharing it with yourself 6 months after you wrote it.  The things that you thought would always be obvious suddenly are not.  You can save yourself a lot of frustration and time decoding your own scripts if you just add some comments throughout the script describing what you’re attempting to do with it.

The comment character for PowerShell is the Number Sign (Pound Sign, or #).  Anything written after a # in a PowerShell script file (ps1), or even in the console, are not processed but instead passed over. 

You can easily comment out a single line of your script by placing a “#” at the beginning of it, like this:

# Write-Host “This Line is a comment.  It won’t write anything”
# This is a comment too. 

# Comments can be used at the end of a single line to describe what is happening

$myVariable = 2 + 4    # This should set $myVariable to 6.

You can also comment with a comment block.  Anything written (even on multiple lines) is commented out.  A comment block starts with <#, and then anything after that is a comment until the comment block ends with a #>

<# This is a comment block

Still a comment

This is the last comment line #>

Write-host “Uncommented now”

I hope this is a help to those of you just starting out with PowerShell, and that it helps move you from just starting out, to taking the next steps towards automating with Windows PowerShell.

PostHeaderIcon Beginning PowerShell Free Tutorial – Creating Your Profile

Whether you’re new to PowerShell or not, when you find yourself ready to start customizing PowerShell and making it do a few tricks, you’re going to want to setup your profile.

Don’t worry, I will show you how to create your profile, and even show you how to add a few cool things to your profile.  You are about to develop the skills to tame that PowerShell profile!

Read the rest of this entry »

PostHeaderIcon PowerShell How To Ping a List of Computers

This quick free lesson in PowerShell teaches you how to use the ping class to get a list of offline computers.  It is fast and easy, and the results are much easier to work with than using ping.exe.

Using the .Net Ping Class

PowerShell is built for speed, and it leverages the .Net framework to make this happen. 

To check the computers status, a Ping request is sent to each computer in a list. 

To start pinging, an object of the Ping class is instantiated:

$ping = new-object system.net.networkinformation.ping

Easy, right?

This avoids having to use the sloppy mess of processing through the text returned by ping.exe.

What is the difference?

By using a .Net object for the ping results, we can still use the object that is returned.  We can save the objects themselves and reference them back later.  The beauty of PowerShell.  The Power.  We want (and get) much more information.  The results of

ping 192.168.1.1

is a wall of text (an array of 11 strings, actually,) while the result of

$ping.send(“192.168.1.1”)

Is a .Net object of the "system.net.networkinformation.pingreply” class.  A pingreply has a property (named ‘status’) that tells us if the ping was successful or not; the address of the ping; and the miliseconds that it takes to get the reply.

To get results that are usable, keep your ping replies in a variable of results, like this:

$pingreturns = $ping.send(“192.168.1.1”)

Alright, we’ve got the base now for finding out if the computer is reachable.

Get Your Computer List Ready

The list of computers we want to ping.  You don’t have to limit your list to only computers. If the network device has Internet Control Message Protocol (ICMP) available (most do) and turned on (depends), it will return pings when they are received. You could ping network printers, or routers, for example.

Here are some examples of loading the ping list:

Get Computer List From Textfile

If you have several computers that you want to check frequently, add them to a text file so it’s easy to save, and easy to update the file instead of modifying the script.

“computer1”,”computer2”,”192.168.1.100”,”192.168.1.1” | out-file c:\users\public\documents\pinglist.txt

Now you’ve got a text file.  Quake with fear, bitches!  Note the use of hostnames and IP Addresses.  It’s fine to do that, you can mix and match.  That list is 4 computers, not a collection of 2 computers listed by hostname and IP.

Update the list of computers as needed.

To load the list of computers:

$complist = gc c:\users\public\documents\pinglist.txt

Get Computer List Manually

$complist = “computer1”, “computer2”

Easy, simple, and easy.  To change the list, you’d change it in the script itself. 

Get Computer List From Other Parts Of The Script

$servers = get-qadcomputer –service domain.com *serv*

$complist = $servers | select name

This seems normal, but it’s actually different, because you’re saving a list of objects into $complist, instead of a list of strings.  Here’s the difference

PS C:\ScriptGenius> $stringlist = "Computer1", "Computer2"
PS C:\ScriptGenius> $stringlist[0]
Computer1
PS C:\ScriptGenius> $stringlist[0].gettype()

IsPublic IsSerial Name                                     BaseType
——– ——– —-                                     ——–
True     True     String                                   System.Object

Compare that to the item in the object list

PS C:\ScriptGenius> $objectlist = get-qadcomputer *work* | select name
PS C:\ScriptGenius> $objectlist[0]

Name
—-
SOFTGRIDWORK2

PS C:\ScriptGenius> $objectlist[0].gettype()

IsPublic IsSerial Name                                     BaseType
——– ——– —-                                     ——–
True     False    PSCustomObject                           System.Object

While the two seem at first to be the same:

$ping.send($stringlist[0])

Works.

$ping.send($objectlist[0])

Does not, but it is at least salvageable.  To make that ping work,  the name property of the psCustomObject (the computer account returned by get-qadcomputer) must be referenced.

$ping.send($objectlist[0].name)

Works.

Get Computer List From an IP Range

This will do an IP sweep for a subnet, pinging along the way.

1..254 | % {$ping.send(“192.168.1.$_”) | select address, status}

Putting it All Together

Now that we’ve seen the pieces, here’s how it all works together.

$computers = get-content C:\scriptgenius\computers.txt

$ping = new-object system.net.networkinformation.ping

$pingreturns = @()

foreach ($entry in $computers) {

  $pingreturns += $ping.send($entry)

}

An array is used here to collect multiple ping results.  When completed, this can be used like this.

$pingreturns[4].status

or

$pingreturns | ? {$_.status –ne “success”} | select address

Instead of piping that to “select address” we could just as easily take action on those failed IP addresses.  Like sending the list of offline computers to the administrative team on on-call person via email.

PostHeaderIcon How to Use PowerShell to Create a Stopwatch and Alarm

60_minutes

So you want a quick and easy stopwatch with PowerShell to time how long you’ve been at a task?  Want to see how long it takes for your coworkers to realize you’re awesome?  Would you like to use PowerShell as a timer or alarm clock?   You can easily use PowerShell to keep track of how long an antivirus scan or checkdisk is taking on another system!

PowerShell contains many of the .NET class library by default, but there are thousands more waiting for you to connect them.

The Stopwatch class is available as part of the System.Diagnostics namespace. To gain access to the classes in it you have to load the namespace.

[System.Reflection.Assembly]::LoadWithPartialName(“System.Diagnostics”)

Once loaded, you can create a stopwatch object.

$sw = new-object system.diagnostics.stopwatch

now that you’ve got your stopwatch, you have access to the methods and properties of the stopwatch class:

Method
Usage
Notes
Start $sw.start() Begin the stopwatch counting
Stop $sw.stop() Stops the stopwatch counting
Reset $sw.reset() Stops the counter and sets elapsed to zero

 

Property
Usage
Notes
IsRunning $sw.IsRunning Returns True/False
Elapsed $sw.Elapsed Returns all elapsed information
.Days $sw.elapsed.days Integer (Int32) days
(how many whole days)
.Hours $sw.elapsed.hours Int32 Hours
.Minutes $sw.elapsed.minutes Int32 Minutes
.Seconds $sw.elapsed.seconds Int32 Seconds
.Milliseconds   Int32 Milliseconds
.Ticks   Int64 Ticks
.TotalDays You get the point  
.TotalHours and  
.TotalMinutes this table is getting  
.TotalSeconds crowded  
.TotalMilliseconds    
     
ElapsedTicks $sw.elapsedticks does not require “elapsed.ticks”
ElapsedMilliseconds $sw.elapsedmilliseconds does not require “elapsed.milliseconds”
Excellent, dude.  I now know one more useless thing to do with PowerShell.

Wrong!  you now know 2 useless things to do with PowerShell:

Tracking Time and Setting Alarms

A note about this:  There IS a measure-command cmdlet in Powershell, which is great because it automatically starts the timer when the command starts, and ends it when the command is over.  But there are some drawbacks to using measure-command:

  • Output is suppressed, like this:

get-qaduser domain\me

returns my acct, but:

”measure-command {get-qaduser domain\me }”

returns the time it takes to get my acct. It does not output my user account to the screen.

  • It runs on only one script block.  If you want to time several commands, or check to see how long a whole process takes (especially if you have an external force like a coworker or other department) a measure-command isn’t going to work.

Things you can time: Here is just a small sample of things you can time.

  1. Your coworkers breaks (but not your own, right?)
  2. How long a Chkdisk or Defrag runs on a machine.
  3. How long it takes your coffee go cool off (or your Mountain Dew to warm up – try doing THAT with measure-command.
  4. How long it takes to parse through enormous lists of users/computers/anything else.

How to set an alarm: Want to work on a project for 20 minutes?  Or how bout start playing an annoying song 15 minutes after you leave for lunch?

while ($sw.elapsed.minutes –lt 20) {$null}; invoke-item “C:\users\public\Music\Sample Music\kalimba.mp3”

3 parts really make this work.

1) (elapsed.minutes -lt 20)  -  We identify our alarm time – in this case "don’t do anything until the timer hits 20 minutes".

2) {$null}  – While we’re waiting we just do nothing.

3) invoke-item c:\music.mp3 – "invoke-item" means open the file with it’s default program – for me it plays in Media Player, or Winamp – depending on what machine I’m on.  

When the music plays, you know the timer is up!

ilovepowershell.com Quick-Commands:

Load the diagnostic objects:
[System.Reflection.Assembly]::LoadWithPartialName("System.diagnostics")

Create a stopwatch:
$sw = new-object system.diagnostics.stopwatch

Create an alarm:
while ($sw.elapsed.minutes –lt 20) {$null}; invoke-item “c:\users\public\music\sample music\kalimba.mp3”

Real Time Web Analytics