Summary: Learn about a revolutionary feature in Windows PowerShell 3.0 that lets you disconnect from and reconnect to PSSessions. Today we continue our exciting guest blog series that is written by Paul Higinbotham, a software design engineer for Windows PowerShell and June Blender, a senior programming writer for Windows Azure Active Directory. Here’s June… I hope that everyone got a chance to try the scenario that I discussed in Disconnected Sessions: Phenotype and Genotype (Part 1). In this post, I’ll show you how to use the InDisconnectedSessions parameter of Invoke-Command and share a few “gotchas” to keep you out of trouble.
Disconnect Immediately
Our savvy IT pro is ready to head to a long meeting. So, she starts a command in a disconnected session. The really efficient command that follows creates the remote session, disconnects from the session, and then runs the command in the disconnected session, thereby keeping all of the command results in the disconnected session:
PS C:> Invoke-Command -ComputerName Server02 {<commands>} -InDisconnectedSession -SessionName TestWeekly
Id Name ComputerName State ConfigurationName Availability
— —- ———— —– —————– ————
5 TestWeekly Server02 Disconnected Microsoft.PowerShell None When she returns from her meeting, the commands are still running. (Must have been a short meeting…)
PS C:> $s = Get-PSSession -ComputerName Server02 -Name TestWeekly | Connect-PSSession
PS C:> $s
Id Name ComputerName State ConfigurationName Availability
— —- ———— —– —————– ————
5 TestWeekly Server02 Opened Microsoft.PowerShell Busy
Gotchas: IdleTimeout
I know you’ll want to try this right now. Who wouldn’t? But before you run off, I want to give you some hints to avoid problems. The value of the IdleTimeout property of the PSSession determines how long the PSSession is maintained while it’s idle (including the heartbeat). When the timeout expires, Windows PowerShell removes the PSSession. This is especially important for disconnected PSSessions that might be left idle for long periods by design.
PS C:> (Get-PSSession -ComputerName Server01 -Name Diag).IdleTimeout
7200000 The default value of the IdleTimeout property of a PSSession is determined by the value of the IdleTimeoutMs property of the session configuration that is used to create the session. In this scenario, the IT pro did not specify a session configuration (New-PSSession -ConfigurationName <name>), so the PSSession used the default session configuration, Microsoft.PowerShell, where the value of the IdleTimeoutMs property is 7200000 milliseconds, or two hours.
PS C:> (Get-PSSessionConfiguration Microsoft.PowerShell).IdleTimeoutMs
7200000 There are several ways to extend the idle timeout of a PSSession:
- You can specify a longer idle timeout in the session options. The value that you specify must be less than or equal to the value of the MaxIdleTimeoutMs property of the session configuration. The MaxIdleTimeoutMs value of the Microsoft.PowerShell session configuration is Int32.MaxValues, which is more than 24 days, so it’s not typically an issue.
PS C: > (Get-PSSessionConfiguration Microsoft.Powershell).MaxIdleTimeoutMs
2147483647
The following command creates a session option object with an idle timeout of 24 hours:
PS C: > $o = New-PSSessionOption -IdleTimeout (60 * 60 * 24 * 1000)
PS C: > $s = New-PSSession -Name Diag -ComputerName Server01 -SessionOption $o
PS C: > $s.IdleTimeout
86400000
- You can change the idle timeout when you disconnect from the session. The Disconnect-PSSession command has an IdleTimeoutSec parameter. (Be careful—this value is in seconds, not milliseconds, like the others.)
PS C:> $s = Get-PSSession -ComputerName Server01 -name Diag
PS C:> $s.IdleTimeout
7200000
PS C:> Disconnect-PSSession $s -IdleTimeoutSec (60 * 60 * 24)
Id Name ComputerName State ConfigurationName Availability
— —- ———— —– —————– ————
7 Diag Server01 Disconnected Microsoft.PowerShell None
PS C:> $s.IdleTimeout
86400000
- You can create a session configuration with a longer idle timeout. When you create sessions that use this session configuration, they’ll have the longer idle timeout by default.
The IdleTimeoutMs property of a session configuration (the one that determines the default idle timeout of sessions) cannot exceed the maximum permitted idle timeout for a session configuration, which is the lesser of the MaxIdleTimeoutMs property of the session configuration and the IdleTimeout value for WSMan shells.
So, when you create a session configuration with a long idle timeout value, you might have to extend the shell IdleTimeout and the session configuration MaxIdleTimeoutMs. This command sequence creates a LongTimeout session configuration with a maximum idle timeout of 24 hours and a default idle timeout of 23 hours:
PS C:> Set-Item WSMan:Server01shellIdleTimeout -Value (60 * 24 * 24 * 1000)
PS C:> $to = New-PSTransportOption -MaxIdleTimeoutSec (60 * 60 * 24)
-IdleTimeoutSec (60 * 60 * 23)
PS C:> Register-PSSessionConfiguration -Name LongTimeout -TransportOption $to
PS C:> (Get-PSSessionConfiguration LongTimeout) | Format-List -Property *idle*
ProcessIdleTimeoutSec : 0
IdleTimeoutms : 82800000
MaxIdleTimeoutms : 86400000
Now, when you create a PSSession with the new session configuration, it has the long timeout by default.
PS C:> $s = New-PSSession -Name Diag -ComputerName Server01 -ConfigurationName LongTimeout
PS C:> $s.IdleTimeout
86400000
Gotchas: OutputBufferingMode
Another potential “gotcha” is the OutputBufferingMode. The output buffer for the session stores the output of commands before they are written to the console or to a file. Typically, output is delivered immediately, so the buffer never fills. But when a session is disconnected, the output can’t be written, so it piles up in the output buffer. OutputBufferingMode tells Windows PowerShell what to do when the output buffer is full.
The default value, Block, prevents commands from running when the buffer is full. You never lose output, but your commands are suspended until the buffer has empty space. The alternate value, Drop, lets the commands continue to run. The oldest output objects in the output buffer are replaced by the output of later commands. The commands are not interrupted, but you can lose results. Neither option is perfect, and the one you choose depends on the commands or scripts that you’re running and on whether and how they store data. The OutputBufferingMode value of a session is determined by the OutputBufferingMode value of the session configuration. You can change the value in a session configuration, create a session configuration with a different value, create a session option with a different OutputBufferingMode, or change the OutputBufferingMode when you disconnect from the session.
PS C:> $o = New-PSSessionOption -OutputBufferingMode Drop
PS C:> $s = New-PSSession -ComputerName localhost -name Diag -SessionOption $o
PS C:> $s.OutputBufferingMode
Drop
-or-
PS C:> $s | Disconnect-PSSession -OutputBufferingMode Drop
PS C:> $s.OutputBufferingMode
Drop
Sessions are User-Specific
The sessions that Get-PSSession -ComputerName gets are determined by who is asking. The cmdlet returns only the sessions that the current user created. So, if your colleague is looking for sessions that you created, they won’t see them. However, you can use group credentials to create a session that others can see.
Remember Remove-PSSession
Because the sessions are persistent, be sure to remove the sessions that you’re no longer using. Windows PowerShell will remove them when the IdleTimeout expires, but they will consume resources until that occurs.
PS C:> $s = Get-PSSession -ComputerName Server01 -name Diag
PS C:> $s | Remove-PSSession
And, if that’s not enough…
If you’re not already pretty jazzed about this, there’s more to come. In Windows PowerShell 4.0, you can enter a busy PSSession while a command is running. You can watch the command run, see output in the console, and even use Ctrl+C to stop a running command or script. (In Windows PowerShell 3.0, you’ll get a busy session error until the command completes.) ~June Thanks, June! I can’t wait to read Part 3. I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy
0 comments