Spying on Function Source Code

Here is a quick way how to find the source code of PowerShell functions:

${function:Clear-Host} | clip

This would copy the Clear-Host source code to the clipboard, and when you paste it, you’ll see how Clear-Host works:

$RawUI = $Host.UI.RawUI
$RawUI.CursorPosition = @{X=0;Y=0}
    @{Top = -1; Bottom = -1; Right = -1; Left = -1},
    @{Character = ' '; ForegroundColor = $rawui.ForegroundColor; BackgroundColor = $rawui.BackgroundColor})

As always, there is much to learn. If you’d like to fill the PowerShell console with a character different than space, i.e. ‘X’, with yellow foreground on green background, try this:

    @{Top = -1; Bottom = -1; Right = -1; Left = -1},
    @{Character = 'X'; ForegroundColor = 'Yellow'; BackgroundColor = 'Green'})

Note that this works only in true PowerShell console hosts.

Twitter This Tip! ReTweet this Tip!

Modern Alternative to More

In a PowerShell console, you can continue to pipe to more, just like in cmd.exe, to view results page by page. However, more does not support real-time pipelining, so all data needs to be collected first. This can take a long time and burn much memory:

dir c:windows -Recurse -ea 0  | more

A better way is to use PowerShell’s own paging mechanism:

dir c:windows -Recurse -ea 0  | Out-Host -Paging

Note that this all requires a true console window. It won’t work in graphical hosts.

Twitter This Tip! ReTweet this Tip!

Creating SMB Shares Remotely

Here are a couple of lines that remotely create an SMB share on a server:

#requires -Version 3.0 -Modules CimCmdlets, SmbShare -RunAsAdministrator
$computername = 'Server12'
$shareName = 'ScriptExchange'
$fullAccess = 'domaingroupName'

$session = New-CimSession -ComputerName $computername
New-SMBShare -Name $shareName -Path c:Scripts -FullAccess $fullAccess -CimSession $session
Remove-CimSession -CimSession $session

You can then map a network drive to that share from your client. Note that network shares are per user, so when you map it with your Administrator account, it is not accessible in Windows Explorer.

$computername = 'Server12'
$shareName = 'ScriptExchange'
net use * "\$computername$shareName"

Twitter This Tip! ReTweet this Tip!

Important PowerShell Variables

Here is a list of important PowerShell variables: $pshome is the path to the place where PowerShell lives. $home is the path to your personal profile folder. And $PSVersionTable returns the PowerShell version and the versions of important subcomponents:

PS> $pshome


PS> $PSVersionTable

Name                           Value                                                                                          
----                           -----                                                                                          
PSVersion                      5.1.14393.0                                                                                    
PSEdition                      Desktop                                                                                        
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}                                                                        
BuildVersion                   10.0.14393.0                                                                                   
CLRVersion                     4.0.30319.42000                                                                                
WSManStackVersion              3.0                                                                                            
PSRemotingProtocolVersion      2.3                                                                                            

$profile is the path to your personal autostart script that gets loaded automatically whenever your current PowerShell hosts starts (provided the file exists). $profile.CurrentUserAllHosts is the profile script that is loaded with any host. And $env:PSModulePath lists the folders where PowerShell modules can be stored that are auto-discoverable for PowerShell:

PS> $profile

PS> $profile.CurrentUserAllHosts

PS> $env:PSModulePath -split ';'
C:Program FilesWindowsPowerShellModules


Twitter This Tip! ReTweet this Tip!

Read-Host Blocks Automation

Using Read-Host to ask for user information can be problematic because it prevents scripts from running unattended. A better way could be to wrap Read-Host in the param() block. This way, the information can be submitted via arguments for unattended operation, and prompted for interactive usage:

    $Name = $(Read-Host -Prompt 'Enter your name'),
    $Id = $(Read-Host -Prompt 'Enter your ID')

"You are $Name and your ID is $Id"

When you run above script, it prompts you with all the freedom Read-Host provides to design a prompt text. You can however also run the script with parameters:

PS> C:myscript.ps1 –Name test –Id 12 

If you do not need custom prompting, you can go even simpler, and declare parameters as mandatory by adding [Parameter(Mandatory)] above each parameter variable.

Twitter This Tip! ReTweet this Tip!