This is translation of my article about some PowerShell tips & tricks not only for developers. I will split the article into more parts, so you won't get tired too early ;)

Operators and variables – Variables $$, $^

$$ and $^ are automatic variables that can be useful when using shell interactively. You will need it only rarely, but it could be worth knowing it. What's all that about can be seen in an example:

[0] Get-ChildItem -rec c:\temp\powershelltest\version1
... some files
[1] $^
Get-ChildItem
[2] $$
c:\temp\powershelltest\version1

The variables contain first and last token from the previous row. More accurately: Contains the first token in the last line received by the session and Contains the last token in the last line received by the session.
They can save your time when typing long paths passed to Get-ChildItem, Get-Item etc.

Have a look at StackOverflow that will prove that some people really use it.

Meta: 2010-05-14, Pepa

This is translation of my article about some PowerShell tips & tricks not only for developers. I will split the article into more parts, so you won't get tired too early ;)

Operators and variables – chain of operators

This technique is not used very often, but it can sometimes help you make your code more readable and you can avoid calling some cmdlets.
Just for this demo suppose that our directory contains these files:

ch01-2010-03-01.txt
ch01-2010-03-02.txt
ch02-2010-03-01.txt
ch02-2010-03-02.txt
ch03-2010-03-01.txt
ch04-2010-03-01.txt

We would like to get only those that begin with ch01. After that we want to parse only part of the file name that can be converted to [datetime]. You would probably do it like this:

[0] Get-ChildItem c:\temp\aa\ | 
   select -exp Name | 
   ? { $_ -like 'ch01*'} | 
   % { $_ -replace 'ch01-|\.txt','' } 

Looks pretty familiar, right? However, you can also use other approach.
Note that the code select -exp Name is not necessary in this case because [FileInfo] is converted to string. During this conversion file name is returned.
Update: [Fileinfo] is sometimes converted to full path. It depends on how the object was constructed. However, I consider this behaviour rather buggy..

[1] (Get-ChildItem c:\temp\aa\ | select -exp Name)  `
   -like 'ch01*'  `
   -replace 'ch01-|\.txt',''

Explanation

There are two things to highlight:
First – operators can be chained. So, operator replace could be split to two for the sake of readability. The code would then look like this: ...-replace 'ch01-','' -replace '\.txt',''. The result of first operator was used when evaluating the second operator. I haven't seen that documented anywhere. Maybe I wasn't searching hard enough. In case you will find some info about it, please let me know.

Second – some operators work with scalars and some with arrays. That's why we could use arrays as left operand for like and replace and the result were correct values.

Lets go even further with our example. Lets convert values that represent dates to datetime.
This is wrong: ... -replace 'ch01-|\.txt','' -as [datetime]. Why? In this case the operator tries to convert input objects (array) to date and that can't succeed. Anyway, we will change the code only a little and it behave correctly.

Compare:

Get-ChildItem c:\temp\aa\ | 
	select -exp Name | 
	? { $_ -like 'ch01*'} | 
	% { $_ -replace 'ch01-|\.txt','' } |
	% { $_ -as [datetime] } |
	? { $_ -le '2010-03-01' }
(Get-ChildItem c:\temp\aa\) `
	-like 'ch01*' `
	-replace 'ch01-|\.txt','' `
	-as [datetime[]] `
	-le '2010-03-01'

Any disadvantage?
There is only one: you have know that you will use this chaining and begin the command with parenthesis.

Meta: 2010-05-10, Pepa

This is translation of my article about some PowerShell tips & tricks not only for developers. I will split the article into more parts, so you won't get tired too early ;)

How many bytes is 1kB?

The today's tip will be very quick.
Do you exactly know how many bytes is 1MB or even 1GB? Are you tired of using 1024*1024*.. all the time? Then look at the examples below.
Note that there is no unit for 1 Byte. Just kidding ;)

[0]> 1kb, 1mb, 1gb, 1tb, 1pb
1024
1048576
1073741824
1099511627776
1125899906842624

What does it mean?
When working with files, you can think in terms of kilobytes/megabytes. Just use the size and add appropriate suffix. PowerShell will evaluate it automatically.

Meta: 2010-05-09, Pepa

This is translation of my article about some PowerShell tips & tricks not only for developers. I will split the article into more parts, so you won't get tired too early ;)

From time to time when working with Powershell you will find something interesting or a general pattern that makes your work easy or that helps you to understand some basics of PowerShell. In this article I will show you some of my tips and interesting useful patterns. Note that this article highlights only some of them. I had to select only some.

I won't touch advanced topics, that you will use only sometimes. I aim at everyday usage of PowerShell. Anyway, I hope at least some of them will be new to you.

Arbitrary names of functions

There are two scenarios how PowerShell is used. You have either your code snippets stored in script files and run them when needed (scheduled scripts, tools, modules, etc.). Or you just type in console and run the code immediatelly after you hit Enter.

When working with scripts, it is very important to keep them readable, comprehensible and independent. That's why you should use full cmdlet names and not only aliases (gci vs. Get-ChildItem). Alias gci can mean something completely different on other machine.

When working with console, your requirements change. You use aliases very frequently and type the shortest code, (gci|?{!$_.PSIsContainer}|select -exp Length). The important thing is to reach the goal, no matter how.

PowerShell makes things easy, because you can use pretty interesting names for your functions and aliases. Let's have a look at some examples:

[0]# well known functions ?? a ?:
[1]function ?? { if ($args[0]) { $args[0] } else { $args[1] } }
[2]function ?: { if (&$args[0]) { $args[1] } else { $args[2] } }

[3]?? $null 'default value'
default value
[4]?: {1} 'is 1' 'is not 1'
is 1
[5]?: {get-process nonexisting -ea 0} 'process exists' 'process doesn''t exist'
process doesn't exist

[6]function * { '*'*10 }
[7]function = { Set-Variable -scope Global -Name $args[0] -Value $args[1] }
[8]= a 100; $a
1
[9]$a = 200; $a #still works

Last example is tip by Johannes Rössel. He uses just Ctrl+D, Enter to exit Posh session. No more exit.

[10]# let's define function with name CTRL+D
[11]New-Item -Path "function:$([char][int]4)" -ItemType function -Value { exit }

Meta: 2010-05-04, Pepa

I usually have a lot of applications open that I use from time to time, not too frequently. It may be email client, one of my browsers or a PowerShell console that I use for some tests, conversions, etc.
Why not to hide them and bring to front only when you need it? Just press a hotkey and the window is shown. Just press a hotkey and the windows is hidden (you don't see it in your taskbar, but the process is running).

(not only) For this purpose I use AutoHotkey. If you don't know this tool, it's worth checking. It's not just a simple mapping "if this key is pressed, run application at this path"; you will see a pretty scripting language.

Show / hide PowerShell console

As I said I have usually at least one PowerShell console open. Most of the time I use browser or Visual studio, so the Posh window might be hidden. How to do that?

First I need a way how to identify the Posh console. The window class would be ok, but Posh console has the same class as the window where cmd.exe is hosted. Besides that if more than one Posh console is open, I would not be able to distinguish between them.
That's why I make the window title unique:

[1]: $host.ui.RawUI.WindowTitle = 'myuniquewindowtitle'

From now on the title of the console is 'myuniquewindowtitle' (check the taskbar for example).

Then I will add a function to AutoHotkey script that hides or shows the window depending if it is visible or not.

LAlt & `::
  DetectHiddenWindows, on
  PoshWinName := "myuniquewindowtitle"
  IfWinExist, %PoshWinName%
  {
    IfWinActive, %PoshWinName%
    {
      WinHide, %PoshWinName%
      WinActivate ahk_class Shell_TrayWnd
    }
    else
    {
      WinShow, %PoshWinName%
      WinActivate, %PoshWinName%
    }
  }
  DetectHiddenWindows, off
  return

Just press left alt and tilde and you will see that it works.
I saw base for this script in some comments, thanks for that.

Similarly you can hide and show any window. If the window title is not always the same, you can specify it by window class – AutoHotkey tool will help you with finding the name of the class.

Meta: 2009-12-23, Pepa

After a week in the wild (~ without Internet) I quickly skimmed through blog posts and noticed something like this: Get-ChildItem |... | Select-Object {(gci $_.FullName).CreationTime}. Did you notice the script block {(gci $_.FullName).CreationTime}?

What does the script block mean?

When I begun with PowerShell it was quite hard to find something about the syntax or how to use it. For someone who tries to get into PowerShell, here is just a quick review:

  • Get-ChildItem | Select-Object Name,Length
    This command simply selects Name and Length properties from passed objects – System.IO.FileInfo and System.IO.DirectoryInfo
  • Get-ChildItem | Select-Object {[int]($_.Length/1mb)},Name
    The property Length is replaced by a script block that gets the value from pipeline and returns something. Note that the script block may do whatever you want, e.g. run a SQL query (hm, silly) or get your Twitter timeline. The point is that the column is computed.
  • Get-ChildItem | Select-Object @{"Name"="Size (MB)"; "Expression"={[int]($_.Length/1mb)}},Name
    Where is the change? We don't pass script block as parameter value, we pass a hashtable. There are two pairs – first one with a key "Name" that specifies the name of the resulting property and second one with the key "Expression" that specifies the value of the property.
    Note that the value for "Expression" si the same script block that was supplied in the command #2.
  • Get-ChildItem | Select-Object @{"N"="Size (MB)"; "E"={[int]($_.Length/1mb)}},Name
    The last command is the same as #3 but the keys are shortened to "N" (insted of "Name") and "E" (instead of "Expression"). The keys are not case sensitive, so you can use "n" and "e" as well.

Other command lets

If you are interested in other command lets that support this type of syntax, go to the New-CustomColumn function PowerShell V1.0 post by The PowerShell Guy. Then you might end up with something like this:

Get-ChildItem | Format-Table @{
    Label="Full name"; 
    Expression={$_.FullName}; 
    FormatString="$((Get-Date)) {0}"; 
    Alignment="right" 
}

One last note: if you use Select-Object don't expect that the properties are evaluated every time you access them. Consider them as fields (their name in PowerShell is NoteProperty). They are evaluated at the time when they are created.

Meta: 2009-09-21, Pepa