Disconnected Sessions: Phenotype and Genotype (Part 2)

Disconnected Sessions: Phenotype and Genotype (Part 2)

  • Comments 3
  • Likes

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:\Server01\shell\IdleTimeout -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 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • if there a way to let idletime unlimited?because i'd like to start a process remotely without disconnecting

  • if there a way to let idletime unlimited?because i'd like to start a process remotely without disconnecting

  • Hi

    Does this apply on InDisconnected Sessions?

    Im having some issues with users that needs to run a process for longer then 2 hours i a disconnected session.

    Any help would be appreciated.

    /Peter