PowerShell

  • If scripts are not enabled, run PowerShell as Administrator and call:

    Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Confirm
    
  • Install PowerShell Community Extensions

Determine what version of PowerShell is installed

$psversiontable.psversion

Install Modules

Persistent History

$MaximumHistoryCount = 31KB
$PoshHistoryPath = "$home\_posh_history.xml"

# Load history if history file exists
if (Test-path $PoshHistoryPath)
    { Import-CliXml $PoshHistoryPath | Add-History }

# Save history on exit, remove duplicates
Register-EngineEvent PowerShell.Exiting {
    Get-History -Count $MaximumHistoryCount | Group CommandLine |
    Foreach {$_.Group[0]} | Export-CliXml "$home\_posh_history.xml"
    } -SupportEvent

# hg function to search history
function hg($arg) {
    Get-History -c $MaximumHistoryCount | out-string -stream |
    select-string $arg
    }

PSReadline

# PSReadline
Import-Module PSReadLine
Set-PSReadlineKeyHandler -Key UpArrow -Function HistorySearchBackward
Set-PSReadlineKeyHandler -Key DownArrow -Function HistorySearchForward
Set-PSReadlineKeyHandler -Key Tab -Function MenuComplete

Text

Write a file in UTF-8 without the BOM

http://stackoverflow.com/questions/5596982/using-powershell-to-write-a-file-in-utf-8-without-the-bom

Out-File -Encoding "UTF8" force the BOM when using UTF-8. Use the following:

[System.IO.File]::WriteAllLines($File, $Contents)

Control Processes

Get-Process shows current processes. You can kill a process with Stop-Process and process ID:

Get-Process ProcessName | Stop-Process

For example:

Get-Process ClipboardHelpAndSpell | Stop-Process

GNU/Linux commands equivalents

PowerShell Community Extensions (PSCX)

Path

  • Get-PathVariable
  • Set-PathVariable
  • Add-PathVariable

Remoting

http://superuser.com/questions/643120/windows-powershell-screen-equivalent/643606

New-PSSession -ComputerName localhost

Get-PSSession -ComputerName localhost | Disconnect-PSSession

PowerShell Remoting vs ssh

  • In PowerShell Remoting, basically everything happens in the local machine; you send cmdlets to remote machines and get the results back.
  • With ssh, one logs into a remote machine, and then use a utility such as screen to make persistent sessions.
  • With PowerShell Remoting, one generates PSSessions from the local machine, and then Enter those PSSessions via Enter-Pssession.

Enable Remoting

On the remote computer:

Enable-PSRemoting

Check the port on the remote machine

http://stackoverflow.com/questions/5458565/powershell-remote-enabling

On the local computer:

cd WSMan:\localhost\Listener
WSMan:\localhost\Listener> dir
[cut]
WSMan:\localhost\Listener> cd .\Listener_1084132640
WSMan:\localhost\Listener\Listener_1084132640> dir
WSManConfig:
icrosoft.WSMan.Management\WSMan::localhost\Listener\Listener_1084132640
Name Value
---- -----
Address *
Transport HTTP
Port 5985

Configure TrustedHosts

On the local computer:

Set-Item WSMan:\localhost\Client\TrustedHosts *
Set-Item WSMan:\localhost\Client\TrustedHosts $office
Restart-Service winrm

You can check it by:

Get-Item WSMan:\localhost\Client\TrustedHosts

Connect to the remote machine

On the local computer:

$targetServer = "xxx.xx.xxx.xx"
$remotePowerShellPort = 5985

$ConnectionURI = ("http://{0}:{1}" -f $targetServer, $remotePowerShellPort)

Invoke-Command:

$remoteSession = New-PSSession -ConnectionURI $ConnectionURI

Invoke-Command -Session $remoteSession -ScriptBlock {Get-Process} -AsJob

Enter-PSSession:

Enter-PSSession -ConnectionURI $ConnectionURI

Exit-PSSession

Note

Enter-PSsession without session argument makes a temporary PSSession automatically, which is not persistent. You have to make a PSSession first via New-PSSession and then enter into that PSSession.

Note

In default WinRM configuration, you can skip -ConnectionURI and http:// and use the ip address as the computer name.

With credentials

$Cred = Get-Credential "remotecomputername\username"
Enter-PSSession XXX.XX.XX.XX -Credential $cred

Interactive Remote Session

Open a persistent interactive session:

$s = New-PSSession -ConnectionURI $ConnectionURI
Enter-PSSession -Session $s

Disconnect from the session:

Exit-PSSession
Disconnect-PSSession -Session $s -OutputBufferingMode Drop -IdleTimeoutSec 2147483647

Recover the session:

$session = Get-PSSession -ConnectionURI $ConnectionURI

You can re-enter the remoting session:

Enter-PSSession -Session $s

Note

It seems this session is limited in a sense that console outputs will not be shown correctly; for example, invoking vim will make console to hang. I haven’t figured out how to fix this. It seems it is a inherent problem of remoting.

Remote Disconnected Sessions

about Remote Disconnected Sessions

  1. Creates a session to the ConnectionURI computer:

    > New-PSSession -ConnectionURI $ConnectionURI
    

    > New-PSSession -ConnectionURI $ConnectionURI -Name “IPython Notebook Server”

  2. To get the session, use the ConnectionURI parameter of Get-PSSession with a value of $ConnectionURI:

    > Get-PSSession -ConnectionURI $ConnectionURI
    
  3. To disconnect a PSSession use the Disconnect-PSSession cmdlet:

    > Get-PSSession -ConnectionURI $ConnectionURI | Disconnect-PSSession
    
  4. To connect a disconnected PSSession, use the Connect-PSSession cmdlet:

    > Connect-PSSession -ConnectionURI $ConnectionURI -Name Session2
    
  5. Run a command remotely in a disconnected session:

    > Invoke-Command -ConnectionURI $ConnectionURI -InDisconnectedSession -ScriptBlock {ipython notebook --profile=nbserver}
    
  6. Run a command remotely as a job in a disconnected session:

    > $s =  Invoke-Command -ConnectionURI $ConnectionURI -InDisconnectedSession -ScriptBlock {Start-Job -ScriptBlock {ipython notebook --profile=nbserver}}
    
    • In this case, you need to do Receive-PSSession to be able to access the session:

      > Receive-PSSession $s
      

Start A Remote Job that Returns the Results to the Local Computer (Asjob)

http://technet.microsoft.com/en-us/library/hh849719.aspx

Runs the command as a background job on a remote computer. Use this parameter to run commands that take an extensive time to complete.

When you use AsJob, the command returns an object that represents the job, and then displays the command prompt. You can continue to work in the session while the job completes. To manage the job, use the Job cmdlets. To get the job results, use the Receive-Job cmdlet.

For example:

$ Invoke-Command -ConnectionURI $ConnectionURI -ScriptBlock {python C:\Users\joon\Dropbox\playground.py} -AsJob
$ Invoke-Command -ConnectionURI $ConnectionURI -ScriptBlock {ipython notebook --profile=nbserver} -AsJob

Note

Problem with this is that since the results are returned to the local computer, once the local session is ended, the results are lost. I think the job gets lost as well.

Start A Remote Job that Keeps the Results on the Remote Computer

http://technet.microsoft.com/en-us/library/hh847805.aspx

I think this can be very useful.

  1. Generate a new PSSession, or connect to an existing one. Let $s denote the session variable.

  2. Invoke a command as a Start-Job in the session:

    Invoke-Command -Session $s -ScriptBlock {Start-Job -ScriptBlock {python C:\Users\joon\Dropbox\playground.py}}
    
  3. You can Disconnect-Pssession -Session $s freely, without killing the job.

  4. To get list of jobs in the session $s:

    Invoke-Command -Session $s -ScriptBlock {Get-Job}
    
  5. To get the output from the job:

    Invoke-Command -Session $s -ScriptBlock {Receive-Job JobId -keep}
    

Example: one session, multiple remote jobs

# Open a new PSSession
> $s = New-PSSession -ConnectionURI $ConnectionURI -Name Persistent

# Invoke command on the remote server
> {Start-Job -Name NBServer -ScriptBlock {ipython notebook --profile=nbserver}} | % { Invoke-Command -Session $s -ScriptBlock $_; };

# Disconnect $s with maximum IdleTimeoutSec
> Disconnect-PSSession -Session $s -OutputBufferingMode Drop -IdleTimeoutSec 2147483647

# Conncet to $s
> Connect-PSSession $s

# Run additional jobs
> {Start-Job -Name Playground -ScriptBlock {python C:\Users\joon\Dropbox\playground.py}} | % { Invoke-Command -Session $s -ScriptBlock $_; };

# Get list of jobs in $s
> {Get-Job} | % { Invoke-Command -Session $s -ScriptBlock $_; };

# Get the output from the job with name Playground
> {Receive-Job -Name Playground -Keep} | % { Invoke-Command -Session $s -ScriptBlock $_; };