Working With PSSessions


Next time, instead of hopping on and off with PSSessions, try setting up a persistent connection.
1. Assign a session to a variable: $sess1 = Net-PsSession -ComputerName <netbios or IP>
2. Recall the variable to see the session ID & Name
3. Disconnect from the session without closing it; Disconnect-PsSession -id <#>
4. Later you can re-join it with Enter-PsSession -id <#>
5. When you are trully done with it: Get-PsSession | Remove-PsSession
(this closes all sessions. Use Remove-PsSession -id or -name for specific sessions)

What might be an interesting experiment is to try $sess1 | disconnect-pssession (etc.)

#tags: Powershell, PsSession, Remote Sessions, Enter-PsSession, Disconnect-PsSession, Remove-PsSession

Difference: Console, Jobs, or Workflow


Commands run from the console require you wait for each task to finish.

Jobs run in the background, freeing up the console.

Workflow runs multiple jobs in the background.
Note that Workflow is also durable (waits on reboots and such).

#tags: Console, Jobs, Workflow, Reboot, Powershell

Quick Hitters


Query User -Server:<machineName> is not Powershell but it is a quick & dirty way to get SessionName and ID for the logged on user of the specified machine.

‘HELP about_’ will bring up the list of all about_ topics

~ is a shortcut to your local profile. It represents c:\Users\<username>

Many Microsoft products (including the ISE) support CTRL + mouse wheel = Zoom in/out

Invoke-Command will work si·mul·ta·ne·ous·ly on multiple computers/servers

Hold down the ALT key while copying from PS console or ISE for block copy (instead of full lines).

$env: is your friend. It not only holds paths to many of your favorite locations but provides host information as well:

Paths: ALLUSERSPROFILE, APPDATA, asl.log, CommonProgramFiles, CommonProgramFiles(x86), ProgramW6432, ComSpec, configsetroot, HOMEDRIVE, HOMEPATH, LOCALAPPDATA, OneDrive, PHPRC, ProgramData, ProgramFiles, ProgramFiles(x86), ProgramW6432, PSModulePath, PUBLIC, SystemDrive, SystemRoot, TEMP, TMP, USERPROFILE, windir

Powershell has a lot of built in variables. But some are weird (and may not be PS in origin). Example $(whoami) which returns the ‘[Security.Principal.WindowsIdentity]::GetCurrent().Name’ which is domain(workgroup)\logged on username.

In ISE, to see help about a command, mouse over it and press CTRL + Space.

#tags: Query User, Help about, tilde, zoom, $env, Block Copy, Whoami, Help ISE, Powershell

ErrorAction In Action


Get the red out by adding routines to capture errors and then control when they are revealed. Never use $ErrorActionPreference in the head of your scripts. If you do, good luck with debugging! Instead use -ErrorAction SilentlyContinue inline with the command(s). This will capture non-terminating errors (you can make them terminating with the -ErrorAction Stop option).
Add in the -ErrorVariable with a variable name and you chose when and where to reveal any issues. Example

PS C:\> Get-process -Id 23,42 -ErrorAction SilentlyContinue -ErrorVariable MyErrors
PS C:\> $MyErrors.CategoryInfo | Select TargetName, Category

TargetName Category
———- ——–
23 ObjectNotFound
42 ObjectNotFound

Note the $Variable.CategoryInfo | Select TargetName, Category. This is much more elegant than the more traditional

$MyErrors | Foreach-Object { $_.CategoryInfo | Select-Object TargetName, Category }

These are the properties of CategoryInfo:
{Category}: ({TargetName}:{TargetType}):[{Activity}], {Reason}

For Terminating Errors, I personally don’t normally do anything with them because I want to see the information (any issues should have been addressed during creation/testing of the function). However, this is where Try{}Catch{}Finally{} work. Use the contents of the $Error built-in variable to return specific bits of information in your catch or finally block.

#tags: Error, Errors, Powershell, ErrorAction, ErrorVariable, ErrorActionPreference, Powershell


Roll Your Own Powershell Filter


In Powershell you can create Filters. In fact, they look very similar to a function:

Filter [<scope:>]<name> [(<$var>)] {doing stuff…}

The difference however is that a Filter has looping built in.
This means that when a Function is fed information from the pipeline, it waits until all the data is loaded. However, a Filter will process each object as it is passed. Low overhead and fast processing.
Here is a side-by-side test you can verify this with (note how clean the Filter code is).
Function Demo-Function {
ForEach ($File in $Input) {
Get-ChildItem C:\ -Recurse -ErrorAction SilentlyContinue | Demo-Function
Filter myFilter {

Get-ChildItem C:\ -Recurse -ErrorAction SilentlyContinue | myFilter
However, you can also get a Function to behave like a Filter:
Function Demo-Function {
Process { $_ }
Get-ChildItem c:\ | Demo-Function
This will also keep overhead low. But it does take some more setup and may not be a clear as a Filter.

#tags: Powershell, Filter