Here are a few tips to use Powershell without using Google.

I know my way around Powershell quite OK. But I Googled a lot and when in a hurry I copied and pasted a lot. So I never took the time to be really in depth. Now is the time! And there is a way to write Powershell without Google! You need to know some very basics and how to study cmndlets, methods and properties.

Let's go!

Suppose you want to check if there are any PST's on a harddrive and let's pretend you know nothing, just like John Snow.

Find out what cmdlets are available with Get-Command

Obviously we need to recurse directories to see if there are any files with a .pst extension. So let's see if there's a cmdlet (a function) with 'dir' in it.

PS C:\Users\Jacqueline> get-command '*dir*'

CommandType     Name                         
-----------     ----
Alias           chdir -> Set-Location
Alias           dir -> Get-ChildItem
Alias           rmdir -> Remove-Item

Get-ChildItem looks like the cmdlet we need. Let's see how it works with the help files.

Get the help files

The problem with command line interfaces: you can't 'guess' which command to use and what the parameters are. So you will need to read the help files. And you will want to update them. Unfortunately, the help files are in c:\windows\system32, so you need to run the command as an Administrator. You can only update-help once a day unless you use the -Force parameter. So open a console as an Admin and run:

PS C:\> update-help -UICulture en-US -force

Needless to say an Internet connection is required. What if you don't have one?

 

Saving help to an alternate location

In that case you can save the help files on an alternate location or on a netwerk share and then update-help.

PS C:\> save-help -DestinationPath C:\powershell\help2 -force -UICulture en-US

and then (as an Administrator):

PS C:\> Update-Help -SourcePath C:\powershell\help2\ -force -UICulture en-US

Now you can use the help files.

Using the help

PS C:\> Help Get-ChildItem

Will display all there is to know about Get-Childitem. Like parameters and what kind of parameters it accepts (string, arrays and so on). If you scroll down the help you get to see the remarks:

REMARKS
    To see the examples, type: "get-help Get-ChildItem -examples".
    For more information, type: "get-help Get-ChildItem -detailed".
    For technical information, type: "get-help Get-ChildItem -full".
    For online help, type: "get-help Get-ChildItem -online"

The -examples are very convenient if you want to have a quick solution.

So now we can play a bit with Get-ChildItem. Let's discover its syntax:

SYNTAX
    Get-ChildItem [[-Path] ] [[-Filter] ] [-Exclude ] [-Force] [-Include ] [-Name] [-Recurse] [-UseTransaction
    []] []

    Get-ChildItem [[-Filter] ] [-Exclude ] [-Force] [-Include ] [-Name] [-Recurse] -LiteralPath  [-UseTransacti
    on []] []

    Get-ChildItem [-Attributes ] [-Directory] [-File] [-Force] [-Hidden] [-ReadOnly] [-System] [-UseTransaction] [
    ]

Here we see it accepts a -Path parameter which is an array because there are brackets: String[]. So we can input multiple search locations by creating an array of locations. Let's see how we can define an array in Powershell.

get-help array

And you will see you get very valuable information about how to create an array. I could create an array like this:

$search = @($env:HOMEPATH,"c:\temp")

Notice the quotes around c:\temp because we're dealing with strings.
The $env:HOMEPATH is already a variable which returns a string.

We can test the array like follows:

PS C:\Users\Jacqueline> $search = @($env:HOMEPATH\Dropbox,"c:\temp")
PS C:\Users\Jacqueline> $search
\Users\Jacqueline\Dropbox
c:\temp

Now we can do a search ilke this:

get-childitem -path $search -Recurse -Include "*.pst" 

I don't want to look at all those red error messages, so let's suppress them:

get-childitem -path $search -Recurse -Include "*.pst" -ErrorAction silentlycontinue

And now for real:

PS C:\Temp> get-childitem -path $search -Recurse -Include "*.pst" -ErrorAction SilentlyContinue

    Directory: C:\Users\Jacqueline\Dropbox\work


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----         5-4-2013     18:33      211305472 jacqueline.pst


    Directory: C:\temp


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        26-7-2015     13:12        5242880 archive.pst
-a----        26-7-2015     13:12        5242880 old.pst

Let's put the result in a variable, like so:

$pst = Get-ChildItem -Path "c:\" -Include "*.pst" -Recurse -ErrorAction SilentlyContinue

Investigating $pst with Get-Member

Like Get-Command and Get-Help, Get-Member is a really import cmdlet you should know about. With Get-Member we can investigate which properties and methods are available. How can I actually write a script or type a command-line command without having to memorize every object model found on MSDN?

Once you connect to an object you can pipe that object to Get-Member; in turn, Get-Member will enumerate the properties and methods of that object.

PS C:\Temp> $pst | Get-Member

   TypeName: System.IO.FileInfo

Name                      MemberType     Definition
----                      ----------     ----------
Mode                      CodeProperty   System.String Mode{get=Mode;}
AppendText                Method         System.IO.StreamWriter AppendText()
CopyTo                    Method         System.IO.FileInfo CopyTo(string destFileName), System.IO.FileInfo... Create                    Method         System.IO.FileStream Create()
CreateObjRef              Method         System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType)
CreateText                Method         System.IO.StreamWriter CreateText()
Decrypt                   Method         void Decrypt()
Delete                    Method         void Delete()
Encrypt                   Method         void Encrypt()
Equals                    Method         bool Equals(System.Object obj)

--MORE--

Scrolling down the list you will notice a Method GetType. Let's run that:

PS C:\Temp> $pst.GetType()

IsPublic IsSerial Name          BaseType
-------- -------- ----          --------
True     True     Object[]      System.Array

So $pst is an Array (we already knew that..) but what is in the array?

PS C:\Temp> $pst | ForEach-Object { write-host $_.GetType()}
System.IO.FileInfo
System.IO.FileInfo
System.IO.FileInfo
System.IO.FileInfo

So, we've got an array full of FileInfo objects. Each objects has a set of methods and properties, which we can query by using Get-Member.

Copying and renaming the PST's to another location

Let's copy the PST's to another location and rename then so some admin can import the PST into a mailbox.

Just copying is not that hard:

$pst | Copy-Item -Destination C:\Temp\pst-share

But if I want to rename the file as well I have to be a bit more 'developerish':

foreach ($f in $pst) {
    $name = $env:USERNAME + '-' + $f.Name
    Copy-Item $f.FullName -Destination "C:\temp\pst-share\$name"
  }

Let's debate on this script tomorrow.