Latest posts by Michael Pietroforte (see all)

These different options correspond to the three parameters -VisibleCmdlets, -SessionType, and -LanguageMode of the New-PSSessionConfigurationFile cmdlet.

VisibleCmdlets ^

Restricting the visible cmdlets in sessions is the most straightforward way to restrict what users can do with PowerShell. In my previous post, I demonstrated how you can ensure that only cmdlets that begin with the Get verb are available. Even though this limits users to only retrieve information from the corresponding computer, you usually want to prevent standard users from being able to gather data that they don’t really need for their work.

Thus, a better practice is to exactly define what cmdlets are visible for a user or a group. This might cost a little more time. However, in many cases, it is pretty obvious what cmdlets a user needs.

To add a specific list of cmdlets to the session configuration that the user can work with, you can use these commands:

New-PSSessionConfigurationFile -VisibleCmdlets Get-Process,Select-Object -Path .\VisibleCmdlets.pssc
Register-PSSessionConfiguration -Path .\VisibleCmdlets.pssc -Name myEndPoint

The -VisibleCmdlets parameter expects an array as input. So don’t set the value you pass in quotes. You can then try your session configuration this way:

$mySession = New-PSSession -ConfigurationName myEndPoint
Invoke-Command -Session $mySession {Get-Process –Name Explorer}

If you try to run a cmdlet that is not in your list, you will receive an error message telling you that the cmdlet was not recognized.

The Get-ChildItem cmdlet is not available in the session

The Get-ChildItem cmdlet is not available in the session.

If you have help desk staff that just needs to run a script, you can quickly determine all cmdlets used in the script with this command:

Get-Content .\myScript.ps1 | Select-String -Pattern "\w+-\w+" | Select Matches

This lists all strings in the script text that contain a hyphen. If you want it a bit more reliable, you can run the code below. It will generate an array of the cmdlet names used in the script, which you can then pass to the -VisibleCmdlets parameter directly.

$AllCmdlets = Get-Command -CommandType Cmdlet | Select-Object -ExpandProperty Name
$myScript = Get-Content .\myScript.ps1
[Regex]$Regex = '\w+-\w+'
$PossibleCmdlets = $Regex.Matches($myScript) | Foreach-Object {$_.Value}
$CmdletsInScript = Compare-Object -ReferenceObject $AllCmdlets -DifferenceObject $PossibleCmdlets -IncludeEqual -ExcludeDifferent -PassThru
New-PSSessionConfigurationFile -VisibleCmdlets $CmdletsInScript -Path .\VisibleCmdlets.pssc
Register-PSSessionConfiguration -Path .\VisibleCmdlets.pssc -Name VisibleCmdlets

This little program compares all strings in your script that contain a hyphen with the cmdlets that the Get-Command cmdlet finds in your current session. Of course, this can only work if you didn’t use cmdlet aliases in your script. This gives you a good example of why following best practices makes sense.

It is important to note that, despite its name, the -VisibleCmdlets parameter can’t be used to make cmdlets visible that you excluded by the other methods described below. Perhaps a better name for the parameter would have been “-SoleCmdlets.” However, you can use the -VisibleCmdlets parameter to further restrict the visible cmdlets in session configurations that you constrained by other means.

SessionType ^

Another way to restrict the available cmdlets in a session is through the -SessionType parameter. The New-PSSessionConfigurationFile cmdlet knows three session types: Default, Empty, and RestrictedRemoteServer.

An empty session is literally empty. It doesn’t contain any cmdlets or language elements. You have to add anything you need in the session configuration yourself. Unfortunately, you can’t add single cmdlets through a session configuration file to an empty session. You have to first add a PowerShell module or snap-in and then remove unwanted cmdlets with the help of the -VisibleCmdlets parameter:

New-PSSessionConfigurationFile -SessionType Empty -ModulesToImport ActiveDirectory -VisibleCmdlets Get-ADUser -Path .\GetADUser.pssc
Register-PSSessionConfiguration -Name GetADUser -Path .\GetADUser.pssc
$GetADUser = New-PSSession -ConfigurationName GetADUser

The only available cmdlet session in the session would be Get-ADUser:

Invoke-Command -Session $GetADUser {Get-ADUser}

This commands works, whereas the next one will produce an error message:

Invoke-Command -Session $GetADuser {Get-ADDomain}

To test whether language elements such as operators are available, you can try the following example:

Invoke-Command -Session $GetADuser {$User = Get-ADUser Administrator; $User -match "Administrator"}

This command will produce the error message: The syntax is not supported by this runspace. However, if you replace line one in the example with this next one, you can use the -match operator:

New-PSSessionConfigurationFile -VisibleCmdlets Get-ADUser -Path .\GetADUser.pssc

Of course, the examples only work if the ActiveDirectory module is available on the computer.

The session type RestrictedRemoteServer is for sessions where a user has to interactively enter a remote session. Thus far, most of our examples only support PowerShell Remoting through Invoke-Command.

New-PSSessionConfigurationFile -SessionType RestrictedRemoteServer -Path .\RestrictedRemoteServer.pssc
Register-PSSessionConfiguration -Path RestrictedRemoteServer.pssc -Name RestrictedRemoteServer
$RestrictedRemoteServer = New-PSSession -ConfigurationName RestrictedRemoteServer
Enter-PSSession -Session $RestrictedRemoteServer

This session type contains seven so-called proxy functions that are required for interactive sessions: Get-Command, Get-FormatData, Select-Object, Get-Help, Measure-Object, Exit-PSSession, and Out-Default. A proxy function is a wrapper function around the original cmdlet that modifies the capabilities of the cmdlet, for example, by adding or removing parameters.

For instance, the Get-Command cmdlet supports the -Verb parameter that allows you to search for cmdlets that begin with a certain verb. The corresponding proxy function in sessions of the type RestrictedRemoteServer doesn’t support this parameter. You also have to know that aliases of the cmdlets are not available. Thus, you can’t exit an interactive session with Exit; only Exit-PSSession will work.

The proxy function Get-Command lacks the -Verb parameter

The proxy function Get-Command lacks the -Verb parameter.

As with a session configuration of the type Empty, you have to add all cmdlets you need and also take into account that, by default, no language elements are available. For some reason, you can’t add the PowerShell core modules to those two session types. (At least I didn’t figure out how to do it. Please let me know if you know how.) Thus, the core cmdlets, such as Get-Process or Add-Content, won’t be available in the corresponding sessions.

If you want your users to be able to enter an interactive session where all the core PowerShell cmdlets are available, you have to work with the default session type and use the -VisibleCmdlets parameter to add the above-mentioned seven cmdlets to the session configuration.

The value Default for the -SessionType parameter is somewhat superfluous as it has the same effect as if you omit the parameter altogether. The corresponding session configuration will create full-blown PowerShell sessions.

LanguageMode ^

The -LanguageMode parameter allows you to determine which PowerShell language elements, such as operators and variables, will be available in a session. The parameter accepts the values FullLanguage, ConstrainedLanguage, NoLanguage, and RestrictedLanguage.

The reason we couldn’t use the -match operator in the session types Empty and RestrictedRemoteServer is because the default value of the -LanguageMode parameter is NoLangugage for these session types. In addition to operators, you also can’t use script blocks and variables in this language mode.

New-PSSessionConfigurationFile -Path .\NoLanguage.pssc
Register-PSSessionConfiguration -Name NoLanguage -Path .\NoLanguage.pssc
$mySession = New-PSSession -ConfigurationName NoLanguage
Invoke-Command -Session $mySession {"a" -eq "a"; $a = "a"}

Operators and variables are unavailable in NoLanguage mode

Operators and variables – unavailable in NoLanguage mode

The RestrictedLanguage language mode allows the comparison operators -eq (equal), -gt (greater than) and -lt (less than) and the variables $PSCulture, $PSUICulture, $True, $False, and $Null. The ConstrainedLanguage language mode is only supported on Windows RT, which is more or less dead so I’ll spare you the details.

Conclusion ^

I only scratched the surface of session configurations in my three posts. Before you implement your own session configurations, you have to carefully test if the users will be able to perform all their tasks. I am afraid that the complexity of PowerShell endpoints will scare off many admins. The result could be that, in many organizations, standard users who need to do tasks in PowerShell are unnecessarily promoted to administrators. Perhaps a simpler solution, such as the sudoers file in Linux, would improve PowerShell’s security. More information about PowerShell session configurations is available here and here.

  1. John Thayer Jensen 5 years ago

    Michael - I much appreciated your articles.  I am really having trouble enabling non-local-administrators to access the session.  When I try remoting to the machine with the remote session configuration as a local administrator on that machine, it works fine.  When I try as a user in a group to which I have given access (including execute permissions), I get:

    New-PSSession : The following error occurred while loading the extended type data file:

    Microsoft.PowerShell.Core, C:WindowsSystem32WindowsPowerShellv1.0typesv3.ps1xml: The file was skipped because of

    the following validation exception: AuthorizationManager check failed..

    that user can't even open the session.

    Any ideas??


    John Jensen

    Applications Specialist

    University of Auckland Business School


  2. John Thayer Jensen 5 years ago

    What I have done for permissions is to include an Active Directory group called 'BE-Users'.  Here are the permissions on the configuration:

    NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, UOA\BE-Users AccessAllowed

    And the 'server' (actually a Windows 10 workstation) is itself a member of the same AD domain.

    I had read that other article - indeed, all 8 of the articles in that series which helped me a great deal.

    May help to explain what this is about, and why I am trying to give them access to a (my!) workstation:

    -   I have a WakeOnLAN app - our central ITS networking people won't give us a server that can send WOL packets through the switches but my machine can, of course, wake up other machines on the same VLAN

    -   the PSSession configuration has a simple little function in it which takes a MAC address and sends the packet.

    -   We have a Microsoft gateway machine that our staff can use to connect to their desktops from outside the University.  However, we are under pressure by Property Services to save power so we want to shut down machines and let staff wake them up remotely if they want to work from home (about 600 staff I think)

    -   on a server that all our staff will have access to I have a little three-liner:

    New-PSSession -ComputerName bef-4136-d02 -ConfigurationName 'Remote WOL'

    Invoke-Command -Session $s -ScriptBlock {do-WOL $args[0]} -ArgumentList $args[0]

    Remove-PSSession -Session $s

    -   this works fine if I connect as a local admin on my workstation.  But if I try to run it as an ordinary user, a member of UOA\BE-Users but not a local admin on the workstation, I get:

    New-PSSession : The following error occurred while loading the extended type data file:

    Microsoft.PowerShell.Core, C:\Windows\System32\WindowsPowerShell\v1.0\typesv3.ps1xml: The file was skipped because of

    the following validation exception: AuthorizationManager check failed..

    At C:\Remote WOL\Remote WOL.ps1:1 char:6

    + $s = New-PSSession -ComputerName bef-4136-d02 -ConfigurationName 'Remote WOL' #  ...

    +      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [New-PSSession], RemoteExc


    + FullyQualifiedErrorId : PSSessionOpenFailed

    -   If I can get it to start the session I will, no doubt, still have issues running the function - may have to pass in various assemblies (well, it just uses and system.convert), etc.  But I can't get it to allow the user to start the session!

    If you have time to wade through all that, thank you very much for your attention!



  3. John Thayer Jensen 5 years ago

    Drat!  Just saw that I forgot to include the assignment of the session to $s in my code above!  Full code is:

    $s = New-PSSession -ComputerName bef-4136-d02 -ConfigurationName 'Remote WOL'

    Invoke-Command -Session $s -ScriptBlock {do-WOL $args[0]} -ArgumentList $args[0]

    Remove-PSSession -Session $s

    In case you noticed it and said, "well, mate, you forgot to assign the session!!" 🙂



  4. Author

    Did you try to add the AD group to a local group that is allowed to use PowerShell Remoting on the machine (for instance BUILTIN\Remote Management Users) .


  5. John Thayer Jensen 5 years ago

    Yes, did try that - also tried creating a local group and adding the AD group to it.  At the moment, I have removed UOA\BE-Users from any local group on my machine since it didn't seem to help.



  6. John Thayer Jensen 5 years ago

    The alternative I have considered is having the remote script run as a service account that is a local admin on my machine.  That would work - but it does mean I would have to put the password somewhere.  Unfortunately, unlike VB, Powershell doesn't seem to have any way of including an encrypted password in the script.  I have thought of a couple of ways, but have to work them out.  Anyway, it seems to me as though I shouldn't have to do that.



  7. Author

    John, I just tried it now and it worked. I added the AD group Domain Users to the local group Remote Management Users on a Windows 10 machine and then I was able to establish a remote PowerShell session with a standard user from another Windows 10 machine in the domain.

    In your comment above it appears you removed the group Remote Management Users from the session configuration. With this command you can check which groups are allowed to establish remote PowerShell sessions:

    (Get-PSSessionConfiguration -Name Microsoft.PowerShell).Permission


  8. John Thayer Jensen 5 years ago

    Michael - yes, I know that command.  Remember that I am not trying to give them access to one of the standard endpoints.  Your command above is for the Microsoft.PowerShell endpoint.  I have created my own endpoint, called 'Remote WOL'.  When I look at permissions for that, my AD group is claimed to have permission.  I run:

    (Get-PSSessionConfiguration -Name 'Remote WOL').Permission

    The result is:

    NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, UOA\BE-Users AccessAllowed

    It is that group 'UOA\BE-Users' that is supposed to be able to connect to the session.  I have been afraid of giving the group access to one of the standard endpoints, for fear of security issues, but I will try that to see if it works.  If it does, then there must be something about the endpoint I created that is the problem.

    OK, I tried giving the group access to the standard 'Microsoft.Powershell' and it claims it has permissions but a user in that group cannot open a session.  Permission shows it should:

    (Get-PSSessionConfiguration 'Microsoft.Powershell').Permission

    NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAll

    owed, UOA\BE-Users AccessAllowed

    This time, instead of the error about the types file, it just says access denied:

    By the way, I did restart WinRM on the target machine.

    If I put that user in as a local administrator on the target machine, it works fine.  I don't understand what the problem could be.  It can't be firewall, because local admins can access it.

    I do so appreciate your attention to this - alas, I am beginning to fear the problem may be insoluble!



  9. Author

    Your permission settings show that you directly added UOA\BE-Users to the endpoint. I wouldn't do that. Instead I would give BUILTIN\Remote Management Users access to the endpoint and then add UOA\BE-Users to BUILTIN\Remote Management Users.


  10. John Thayer Jensen 5 years ago

    OK, trying that now.




  11. John Thayer Jensen 5 years ago

    Still a problem, though with a difference.  I put 'UOA\BE-Users' into the BUILTIN\Remote Management Users:

    net localgroup 'remote management users'

    Alias name     remote management users



    Permissions show as available for both endpoints:

    (Get-PSSessionConfiguration 'Microsoft.Powershell').Permission

    NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed

    (Get-PSSessionConfiguration -Name 'Remote WOL').Permission

    NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed

    The difference is now that for *both* endpoints it complains about the types file.  I am a bit nervous about changing permissions for that file as when I try, the 'Add' button is greyed out.  Users have access.  Maybe I should add 'Remote Management Users' to the local Users group?



  12. John Thayer Jensen 5 years ago

    Oh, of course, I can't add remote management users to users because I can't add a local group to a local group 🙂  And there seems little point in adding uoa\be-users since uoa\domain users is already a member.



  13. John Thayer Jensen 5 years ago

    Tried giving my test user direct permissions (and adding to local remote management users) - same deal:

    NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed, UOA\jjen009test AccessAllowed

    The test user is jjen009test


  14. John Thayer Jensen 5 years ago

    Grasping at straws time - I logged in directly to the target machine using the test account to see if it could, in fact, read those types files. It can 🙁



  15. Author

    What is the exact error message you get with this new configuration when you try to establish a remote PowerShell connection?


  16. John Thayer Jensen 5 years ago

    (after about a 30-second wait):
    New-PSSession : The following error occurred while loading the extended type data file:
    Microsoft.PowerShell.Core, C:\Windows\System32\WindowsPowerShell\v1.0\typesv3.ps1xml: The file was skipped because of
    the following validation exception: AuthorizationManager check failed..
    At line:1 char:6
    + $s = New-PSSession -ComputerName bef-4136-d02 -ConfigurationName 'Remote WOL' -C ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [New-PSSession], RemoteExc
    + FullyQualifiedErrorId : PSSessionOpenFailed



  17. Author

    The error message looks odd. Did you set the execution policy to unrestricted?


  18. John Jensen 5 years ago

    Yes, I tried unrestricted, remote signed, and restricted.  No difference.  It's never getting to the session, so I suppose the policy doesn't have a chance to affect it.


    • Author

      Hard to say what your problem is. I suggest that you use a test computer with a freshly installed Windows without any third-party software installed, with the default configuration (don't apply any Group Policy) and try to give a standard user remote access to the the default PowerShell session as described in the article. If this works, do the same with your own session configuration. If this works too, you know that you configured PowerShell correctly and that it is a problem with your original computer. Then you have to remove every difference from the original computer step by step until it works.


  19. John Thayer Jensen 5 years ago

    Thanks so much for your attention, Michael.  I have, for now, at least, thrown in the towel - I am just going to do a -runas with a service account that is a local administrator.  That works.  I had hoped to avoid it because I just didn't like the idea of ordinary users running as administrators on my machine.  Not as bad as it could be, though, since they are only running on my machine, not on a server (or, Heaven forbid! a domain controller).

    Sometime when I get time I'll try what you said because it has puzzled me - but I have to deal with another overriding factor: the length of the boss's patience 🙂



  20. Peter Mueller 5 years ago


    I am trying to run cmdlets from WebAdministration via Remote PowerShell. I created a configuration file, imported the Module WebAdministration and added 2-3 cmdlets from that module as visible cmdlets.

    SchemaVersion = ''
    GUID = '96e91185-5858-4cd9-a090-c0f957d17e20'
    Author = ''
    SessionType = 'RestrictedRemoteServer'
    ModulesToImport = 'WebAdministration','ActiveDirectory'
    VisibleCmdlets = 'Get-Website', 'Get-WebAppPoolState', 'Restart-WebAppPool', 'Get-AdUser'

    Now, I register the config:
    Register-PSSessionConfiguration -Name TestConfigFile -Path D:\SessionConfig.pssc -Force -ShowSecurityDescriptorUI

    In the Sec UI, I added a non-admin account with Full Control Rights.

    When I try to connect as non admin from a different machine, I get the error:

    Process should have elevated status to access IIS configuration data.

    I then, added the RunAsCredential parameter for the Register-PsSessionConfiguration cmdlet and added a local admin. Then, I am able to load the remote session and I can do a Get-Website. However, I am unable to run ie. Get-WebAppPoolState

    Cannot find a provider with the name 'Variable'.
        + CategoryInfo          : ObjectNotFound: (Variable:String) [Get-WebAppPoolState], ProviderNotFoundException
        + FullyQualifiedErrorId : ProviderNotFound,Microsoft.IIs.PowerShell.Provider.GetAppPoolStateCommand

    Any Idea what the problem could be?



  21. Debugger 4 years ago

    Regarding the error "AuthorizationManager check failed":

    After some debugging, I found the cause:

    If a user who is not a local admin tries to connect via a custom session configuration, some ExecutionPolicy Checks (you can test this by running Get-ExecutionPolicy) trigger a exception in the shouldRun function because there is a remote WMI permission missing.

    The solution is: On the powershell target computer, open compmgmt.msc, select Services and Applications and Right-Click on WMI Control and select Properties. On the security Tab select a WMI Path like Root\CIMV2, Click on Security, add the desired group and give it the Remote Enable Permission. After that you should be able to process the extended type data files.


Leave a reply

Please enclose code in pre tags

Your email address will not be published. Required fields are marked *


© 4sysops 2006 - 2021


Please ask IT administration questions in the forums. Any other messages are welcome.


Log in with your credentials


Forgot your details?

Create Account