Posts Tagged ‘powershell’
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.
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!
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
—-
SOFTGRIDWORK2PS 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.
How to Use PowerShell to Create a Stopwatch and Alarm
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.
- Your coworkers breaks (but not your own, right?)
- How long a Chkdisk or Defrag runs on a machine.
- How long it takes your coffee go cool off (or your Mountain Dew to warm up – try doing THAT with measure-command.
- 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.stopwatchCreate an alarm:
while ($sw.elapsed.minutes –lt 20) {$null}; invoke-item “c:\users\public\music\sample music\kalimba.mp3”
