May 13, 2015

Converting to the local time

To convert a date/time string from GMT (or any other time zone)

[DateTime]::Parse('2015-05-08T15:17:52Z')

Source : #PSTip Converting to the local time

August 12, 2014

Don’t Count, Measure

How often do you use the  Count property of an object to get the number of items in it ?

$SomeArray.count

The problem is that if you try to get the  Count property on a null object or on a object that is not a collection or an array it will throw an exception.

The solution is to use the Measure-Object cmdlet :

($SomeArray | measure-object).count

June 13, 2014

How to call a Powershell script from the command line and return an ERRORLEVEL

Sometimes you want to call a powershell script from the command line and get an ERRORLEVEL a the exit if an exception is throw in the script (ex: With a scheduled task).

In Powershell v2 you could do this :

powershell.exe -noprofile -command ". c:\test-exit.ps1 -erroraction stop;exit $LastExitCode"

Unfortunately this does not work anymore in Powershell v4 (always return ERRORLEVEL 0). It looks like the $LastExitCode is not define anymore for a script by Powershell (only for an external process).  But Powershell seems to now behave as expected and exit with an ERRORLEVEL=1 if any error occurs in your script. So now, the following code should works :

powershell.exe -noprofile -command ". c:\test-exit.ps1 -erroraction stop"

If you really want to check if your script was successful and return a special ERRORLEVEL, you should use the $? variable :

powershell.exe -noprofile -command ". c:\test-exit.ps1 -erroraction stop;if ($?){exit 0}else{exit 99}"

Don’t forget :

  • To use dote-sourcing, the small dot (.) in  front of the script name.
  • To use the –command parameter instead of the –file parameter. The two parameters behave differently.
  • To set the –erroraction stop. If you keep the default value of continue, your script will not stop and the ERRORLEVEL will not be set to 1.

May 2, 2014

Find all files modified after a date

To find all files modified after may 1st, 2014 :

Get-ChildItem .\ -recurse | Where-Object { ($_.PsIsContainer -eq $false) -and ($_.LastWriteTime -gt (get-date '2014-05-01')) } | select fullname,lastwritetime,length | Out-GridView

January 6, 2014

Loading (import) a module with arguments

You can use the –ArgumentList parameter of the import-module cmdlet to pass arguments when loading a module.

You should use a param bloc in your module to define your parameters :

param(
    [parameter(Position=0,Mandatory=$false)][boolean]$BeQuiet=$true,
    [parameter(Position=1,Mandatory=$false)][string]$URL
)

Then call the import-module cmdlet like this :

import-module .\myModule.psm1 -ArgumentList $True,'http://www.microsoft.com'

As may have already noticed, you can only supply values (no names) to –ArgumentList. So you should define you parameters carefully with the position argument.

October 29, 2013

How to export/pipe/copy results to Excel

Sometimes you just want to paste the result of a cmdlet into an Excel spreadsheet.

First you will probably try to copy the content from a Gridview :

get-process | out-gridview

But you will realise that the column’s headers are missing.

Why not try to pipe the result into the clip command and paste it in Excel :

get-process | clip

Well not so great, everything is in one big column (no delimiter).

Ok, let’s try to convertto-csv before doing the copy :

get-process | convertto-csv -Delimiter "`t" -NoTypeInformation | clip

Looks great … but if you happen to have any french characters, they will not appear in Excel.

So, my final solution is to re-encode the output in UTF8 by saving it to a file :

get-process | export-csv -Delimiter ";" -NoTypeInformation -force -path "$env:TEMP\export-csv.csv" -Encoding UTF8; start-process excel "$env:TEMP\export-csv.csv"

August 23, 2013

How to use write-verbose with an object

When you are debugging some times you want to use the write-verbose cmdlet to display an object or a collection.  It would have been really nice to be able to do :

write-verbose (Get-EventLog -LogName system -Newest 3 -EntryType Error)

unfortunately this will produce an error :

Write-Verbose : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'Message'. Specified method is not supported.

The write-verbose cmdlet only takes a string as a paramter, objects are not allowed.
The trick is to use the out-string cmdlet like this :

write-verbose (Get-EventLog -LogName system -Newest 3 -EntryType Error | Out-String)

You can event make it look a little bit prettier :

write-verbose (Get-EventLog -LogName system -Newest 5 -EntryType Error| format-list -Property TimeGenerated,Entrytype,EventID,Source,Message | out-string)