Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / PowerShell

A PowerShell Introduction

4.77/5 (21 votes)
4 Oct 2014CPOL5 min read 34.6K   365  
PowerShell is a very powerful tool, yet it's difference to the classic DOS command prompt gives you a hard time if you are used to the CMD. This article shall guide you into the World of PowerShell and give you an easy start.

Introduction

PowerShell is the better Command Prompt. It allows you to use any .Net functionality and access a lot of Windows' not-so-obvious functionality which were difficult to access with the CMD. PowerShell is based on .Net 2.0 and connects the philosophy of Pipes and Filters (known from Unix Shells) with the paradigm of object orientated programming.

The core of the PowerShell is based on small functionality units, called Cmdlets ("command-lets"). A list of the Cmdlets can be retrieved this Microsoft Technet page.

Background - Syntax

The syntax of the scripting language used for Powershell Scripts has its own syntax. This chapter gives you a brief overview over the syntax and removes some of the traps a PowerShell script hides in it.

Variables and Constants

#Variables are defined with a leading '$':
$programFilesX86 = (${env:ProgramFiles(x86)}, ${env:ProgramFiles} -ne $null)[0]

The above example sets the variable "programFilesX86" to the path of the program files folder for x86 programs. Because the folder doesn't exist on x86 platforms, the variable is set to the ordinary program files directory if the x86 folder isn't available.

#Constants are also defined with a leading '$' - 
#To distinguish them from variables, they shall be written in all-capital letters.
$CONSTVAL = "This value can't be changed"
Set-Variable CONSTVAL -option ReadOnly 

Even though not needed by interpreter specifications, I recommend you to write constants in all-capital letters to distinguish them from variables.

Functions

PowerShell script files are interpreted and if a method is called which isn't read by the interpreter before it is called, PowerShell will encounter an error. The best way to avoid this error trap is to define a method called "Main" at the top, and then define a jump to this very method at the end of the file:

function main{
   #main function, as known from classic structured programs.
   myFunction
}

function myFunction{
   Write-Host "myFunction was called"
}

main #Jump to execute main

The example below is supposed to do the exact same, but will not be able to run because the function "myFunction" isn't interpreted at the time it is called.

myFunction #Error - myFunction wasn't read yet, but is already called

function myFunction{
   Write-Host "myFunction was called" #will never be reached
}

Basic commands

File System

As the Command Prompt already did, PowerShell provides a vast amount of Cmdlets to access the file system and modify files and directories.

Copy a File

Files can be copied using the Copy-Item Cmdlet, where the first parameter specifies the source file and the second parameter specifies the source file's full path:

Copy-Item -Path "C:\Source\Powershell" -Destination "C:\Testumgebung"

The copy process can be made recursive by adding the -Recures parameter at the end of the command:

Copy-Item -Path "C:\Source\Powershell" -Destination "C:\Testumgebung" -Recurse

Get File or Folder information

File or folder information can be obtained using the Get-Item Cmdlet:

Get-Item -Path "C:\"

Image 1

To get information about the child items of a path, you can either use Get-Item with an added wildcard or Get-ChildItem:

Get-Item -Path "C:\*"
Get-ChildItem -Path "C:\"

Both Cmdlets return details on the child items of C:\:

Image 2

Remove a file or a directory

Remove-Item -Path "C:\Source\Test1\*.txt" -Recurse -Force

The -Recurse parameter can only be applied to files, while -Force also deletes locked files. In the above shown parametrization, any *.txt file will be removed from C:\Source\Test1 and its subfolders.

Copy a file or a directory

Copy-Item -Path "C:\Source\*.txt" -Destination "C:\Source\Textfiles" -Recurse

This command copies any *.txt file from C:\Source and its subfolders to C:\Source\Textfiles, and the sub folder structure remains unchanged.

Interaction with Processes

PowerShell provides a vast amount of Cmdlets to help you analyze and manipulate running processes.

You can start a new process with almost any possible option:

Start-Process powershell.exe

would start a new PowerShell instance. Start-Process is a mighty Cmdlet and does provide a lot of parameters. A list of all parameters can be found at this Microsoft Technet Homepage.

To get a list of all running processes on your system, you can use

Get-Process

This displays a list of all running processes, including some additional information:

Image 3

Of course you can search for a very specific process by it's name:

Get-Process powershell

Image 4

This behavior can be extended by searching for more than one process name, for example PowerShell and the Windows Explorer:

Get-Process powershell,explorer

Image 5

You get the idea - Any number of process names can be checked that way. In case you are looking for a process which isn't running, PowerShell will return an error (e.g. throw). What you might haven't known yet is that the usage of wildcards is allowed for the process name, means that

Get-Process power*

will return every running process which starts with "power". Those who happen to know the WMI class Win32_Process may have recognized that all the demonstrated things can be done easily by this class. But PowerShell can do more: WMI doesn't expose properties such as company or product version, but PowerShell does. In the following example, Get-Process gets piped through the Select-Object Cmdlet, filtering out any information except the process name, product version, and the company:

Get-Process powershell | Select-Object name,productversion,company

Image 6

Now you ask yourself how you are supposed to know which properties are available through get-process, don't you? You can find it out by yourself. The following line pipes get-process through get-member and displays all available members:

Get-Process | Get-Member

Try it out by yourself - You'll get a very long list of Members, and you are free to use all of them.

Of course you will sooner or later encounter the situation that you need to stop a running process - Use the stop-process Cmdlet to do it. It accepts either a process id or process name as parameter:

Stop-Process 23498
Stop-Process -processname notepad

Use .Net classes within your PowerShell Script

The following function starts a process using the .Net System.Diagnostics namespace. Of course the same can be achieved by simply using the Start-Process Cmdlet, but it gives you a good start on the syntactically correct way to use .Net classes in your PowerShell Script.

function StartProcess([string]$filePath, [array]$arguments, [bool] $waitForExit)
{
    $pinfo = New-Object System.Diagnostics.ProcessStartInfo #Make a new Process start info object
    $pinfo.FileName = $filePath #set the file name to the filePath argument
    $pinfo.RedirectStandardError = $true #standard error and stdout shall be redirected
    $pinfo.RedirectStandardOutput = $true
    $pinfo.UseShellExecute = $false
    $pinfo.Arguments = $arguments #set the arguments to the arguments specified $arguments
    $p = New-Object System.Diagnostics.Process #create a process
    $p.StartInfo = $pinfo # assign start info to the process
    $p.Start() | Out-Null # start the process
    IF($waitForExit){ #wait until the process has exited (if specified)
        $p.WaitForExit()
    }
}

Utilities

This chapter gives some examples of PowerShell functions I wrote myself. All of these functions provide a functionality which isn't given by existing Cmdlets, but still of use in many cases.

Create a directory if it doesn't exist

Just creating a directory throws an error if the directory already exists. This little helper function avoids this problem by only creating the directory if it doesn't exists:

function CreateDirectoryIfNotExisting([string]$dirPath){
   IF(!(Test-Path -Path $dirPath)){#check if the directory exists
      New-Item -ItemType directory -Path $dirPath #create it if it doesn't exist
   }
}

Abort script execution if a file/directory is missing

This function aborts the execution of the script if the specified file is missing on the file system.

function AbortIfFileMissing ([string]$filePath, [string]$name)
{
    IF(!(Test-Path $filePath)){#Not being able to find file throws
        Throw ("ERROR: The File $name was not found! Expected path: $filePath")
    }
    ELSE{
        Write-Host ("File " + $name + " found. It's located at " + $filePath)
    }
}

The function which has the same functionality regarding to a directory can be implemented following the same scheme:

function AbortIfDirectoryMissing ([string]$dirPath, [string]$name)
{
    IF(!(Test-Path $dirPath)){#Not being able to find directory throws
        Throw ("ERROR: The directory $name was not found! Expected path: $dirPath")
    }
    ELSE{
        Write-Host ($name + " found. It's located at " + $dirPath)
    }
}

Further reading

 

This chapter gives you a collection of Links which you can use to read further, more detailed information about specific PowerShell topics.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)