Archives for the Month of August, 2011

Enforcing Single-User Access to PowerShell Remoting

I got a question today with an interesting request – “How do I ensure that only one user can access a machine via PowerShell Remoting at a time?”

We do have direct functionality to limit multiple sessions, but it that limit applies to sessions by the same user - see: MaxShellsPerUser for full detail about that setting. If you are doing some sort of self-service portal where everybody shares the same local username / password, MaxShellsPerUser is one way to solve the problem.

More commonly, though, you might want to enforce this restriction across all users on the machine. One useful thing to configure then is MaxConcurrentUsers. Set MaxConcurrentUsers = 1 and MaxShellsPerUser = 1, and you’ve enforced single-user access.

If your needs are more complex than this, we can solve this with a custom PowerShell session configuration. Perhaps we’d like to offer unrestricted access to administrators on the (default) Microsoft.PowerShell configuration, but enforce throttling on a new one called “Contoso.Build”.

If you’ve never set up a custom session configuration before, there are many great resources. Ravikanth Chaganti, one of our awesome MVPs, has written a great introduction to them here:

This is also covered in the PowerShell Cookbook, recipe 29.20.

Now, once you’ve got a startup script for your custom session configuration, you can use a system-wide Named Mutex to enforce your quota limits. This is pretty advanced scripting, so don’t be worried if it looks intimidating.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025

function IsMachineIdle
{
   
$sessionHandle = New-Object System.Threading.Mutex $false,"PowerShellSessionMutex"
    $isAvailable = $false

    try
    {
       
$isAvailable = $sessionHandle.WaitOne(1000
)
    }
   
catch [System.Threading.AbandonedMutexException]
    {
       
$isAvailable = $true
    }

    $isAvailable
}

if(-not IsMachineIdle)
{
   
"Sorry, the machine is in use. Try again in 5 minutes."
    exit
}

## Continue on with preparing a session

If you want to get more advanced (saying who is logged on, etc.), roll up your sleeves and dig in!