Getting Started (PowerShell)

From vwiki
Revision as of 12:55, 7 May 2019 by Sstrutt (talk | contribs) (→‎Scripts: Add "Scheduled Tasks")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Installation

Subject specific useful links are listed in the sections below, the following provide links to installers and general documentation...

Whilst Win2008 ships with Powershell V2, it isn't necessarily available, to install...

  1. Go to Server Manager
  2. Go into Features, then Add Features
  3. Tick Windows Powershell, and then Next

Normally a restart isn't required

If you're running scripts from a machine that does not have (or has dodgy) internet access, then running PowerShell scripts can mean a very long wait before they start to run. In which case you need to disable certificate checking (its the checking for certificate revocation that needs to time-out before a script will run)...

  1. In Internet Explorer
  2. Go to Internet Options, and then Advanced
  3. Then under Security uncheck Check for publisher's certificate revocation

User Profile

Its possible to create a customised profile so that modules, settings etc are available. This is achieved by running a PowerShell script whenever PowerShell starts

  1. Locate your profile path
    • Write-Host $profile
      
  2. Create a PowerShell script in the exact path

You could for example log all PowerShell activity to a OneDrive folder...

$today = (Get-Date).ToString("yyyy-MM-dd")
Start-Transcript -Path "$home\OneDrive\Scripts\transcripts\$env:computername-PID$pid-$today.txt" -Append -NoClobber

Execution Policy

On the first run you need to allow Powershell to scripts to execute, otherwise you'll get an error that contains the following when trying to run a script...

  • cannot be loaded because the execution of scripts is disabled on this system.

You need to run the command below as an administrator, otherwise you'll get an error like...

  • Set-ExecutionPolicy : Access to the registry key 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell' is denied.

So if you're using Windows 7, for example, you'll need to start the Powershell console as an administrator (right-click Run as administrator), regardless of whether you're currently logged in as an admin).

 Set-ExecutionPolicy RemoteSigned

It is possible to bypass the Execution Policy entirely (though you do so at your own risk, should only be used to run a script you trust where you haven't the time to fix the underlying problem, and should be reverted afterwards)...

 Set-ExecutionPolicy Bypass

If you have no admin rights over the PC you're using, then can try to use Suspend option rather than Yes (sets just for your current session, doesn't try to write to the registry), this doesn't work in all cases. Alternatively you can hack the Environment variable that controls the Execution Policy (again, this isn't permanent, and may not work in all versions)...

$env:PSExecutionPolicyPreference = "RemoteSigned"

To see your current execution policy use...

Get-ExecutionPolicy

To run a script, without tinkering with the Execution Policy first, run from a command prompt

powershell.exe -executionpolicy remotesigned .\Example.ps1

Installed Version

To check the main installed version use either of the following command lines...

Get-Host | Select version      
$host.version

However, if you might have installed something other than the normal RTM or GA release version you'll need to the registry key HKLM\Software\Microsoft\PowerShell\1, which will have the following values of interest...

Value Data Meaning
Install 1 Installed (not version number - Microsoft may have intended this to be a version marker at inception, but it is not used as such)
PID 89383-100-0001260-04309 RTM (Release to Manufacturing)
PID 89393-100-0001260-00301 RC2 (Release Candidate 2)

For more info on release version acronyms, see Software Release Life Cycle

Help Commands

Get-Help <cmd>              # Provides help for CmdLets, use wildcards to broaden results.
$object | Get-Member       # Provides information about an object (variable)
$object.gettype()          # Provides variable type info (string, array, etc)

Conditional Operators

Comparison

Operator Description
-eq Equal to (implied case insensitive)
-ieq Equal to (case insensitive)
-ceq Equal to (case sensitive)
-lt Less than
-gt Greater than
-ge Greater than or Eqaul to
-le Less than or equal to
-ne Not equal to
-match Match (ie string contains) anywhere within string (can be regex)
-notmatch Does not match (ie string contains) (can be regex)
-like Like (ie string is), stricter than match (can be regex)
-notlike Not like (ie string is not) (can be regex)

Logic

Operator Description
-not Not
 ! Not
-and And
-or Or

Useful One-Liners

Command Description
Get-Content <file-path> | Out-GridView Display (log)file in the nice Grid View window
(Get-Location -PSProvider FileSystem).ProviderPath Current working directory
$MyInvocation.MyCommand.Name Current script or function name (if in a function)
$host.UI.RawUI.WindowTitle = "Wibble" Change command shell title (to Wibble)

PowerShell Process

To get information about the current running PowerShell session process, use...

$proc = [System.Diagnostics.Process]::GetCurrentProcess()

...from which you can get all sorts of performance and other metrics such as total CPU time taken, various memory usage metrics and so forth. Which can be useful if you have a script that you want to run continuously, but you want to be able to monitor that its behaving (no excessive CPU usage or memory leaking).

The object type returned by the above is exactly the same as is returned by Get-Process.

Process Priority

In order to change the priority of the current PowerShell process, use...

( [System.Diagnostics.Process]::GetCurrentProcess() ).PriorityClass = "NewPriority"

...where NewPriority is any of (though I'd recommend limiting to either BelowNormal or AboveNormal)...

Priority Description
Idle Only runs when system is idle, which may mean that the process never gets enough execution time to do anything useful.
BelowNormal Ensures that the process will yield to most other processes running on the system (good for background tasks).

By default, scheduled tasks run as Below Normal (in Win2008, and maybe others)

Normal Default - recommended for most tasks
AboveNormal Ensures that most other processes running on the system will yield to the PowerShell process (good for urgent, high priority tasks).
High Process will try to run immediately.
Can lead to a system having constant high CPU and sluggish overall performance.
RealTime Process overrides all other processes (including system tasks).
Can lead to an unresponsive, locked out system unless process has been specifically written to run in RealTime mode, or will only run for a very brief period.

If you run scripts that can be CPU intensive, and/or run for a long time. This can lessen the impact on your desktop or server (wherever the script is running).

To check the current priority of your shell or script use...

( [System.Diagnostics.Process]::GetCurrentProcess() ).PriorityClass

Scripts

Include Files

In order to include another Powershell script in a parent script, use a . and then the path to the file (there's a space between them), eg

. .\lib\include_file.ps1

Script Arguments

In order to be able to parameters to a script the $args variable can be used. Each argument is provided within the array in order, eg

# 1st param is send yes or no
# 2nd param is email address

if ($args[0]) {
    Write-Host "Email sending enabled...!"
    Write-Host "Will send to" $args[1]
} else {
    Write-Host "Email sending disabled."
}

So for example...

[PS > ./params.ps1 0
Email sending disabled.
[PS > ./params.ps1 1 test@abc.com
Email sending enabled...!
Will send to test@abc.com

Logging

The easiest way to setup logging from with a script is to use the Transcript functionality which will log all output to a transcript file. Note that Write-Host only places line feeds at the end of lines, not carriage returns, therefore Notepad will display such output as one long line. You'll need to use an editor that can handle lines only terminated by LF's (WordPad if you can't install anything, otherwise get something better, eg http://www.scintilla.org/SciTE.html).

Start-Transcript -Path C:\Users\name\Scripts\script.log -Append -NoClobber
# script
Stop-Transcript

Scheduled Tasks

To run a script as a scheduled task, complete the task config as normal, in the Action tab populate as follows...

  • Program/Script - PowerShell
  • AddArguments (optional) - As below (not optional!)
    • Basic: script.ps1
    • Where paths have spaces and your script takes parameters (eg ScriptParam): "& 'C:\Path\To Script\script.ps1'" -ScriptParam ScriptParamData
  • Start in (optional) - As below (optional, but recommended)
    • C:\Path\To Script
    • Do not add quotes, even if your path has spaces

Call External Process

Running an external executable is a bit of a faff, but it can be done...

$cmd = "rrdtool.exe update $rrd $updates"
$proc_res = &$executioncontext.InvokeCommand.NewScriptBlock($cmd)


Slow Start-Up

PowerShell isn't the fastest thing in the world to start, the fact that a basic PowerShell command prompt uses of 50MB of RAM gives some indication that its not lean and mean (but once up and running, and when running efficient script it can be very fast). However if its taking minutes rather than seconds to start then there is something going wrong.

Normally this is due to the fact that the machine you're running from has no (or limited) internet access. To workaround the problem you need to disable Certificate Revocation Checking...

  1. In Control Panel, open Internet Options
  2. Go to the Advanced tab, and scroll down to the Security section
  3. Untick the Check for publisher's certificate revocation

There is no increased security risk imposed by doing this on a machine with no/limited internet access, as the checks were previously timing-out and being bypassed anyway.