Search code examples
powershellformattingpowershell-5.0winrminvoke-command

Invoke-Command on remote session returns local values


Question

Should the script block of Invoke-Command, when run with a PSSession, always run on the remote computer?

Context

I ran the below powershell against a list of servers:

Clear-Host
$cred = get-credential 'myDomain\myUsername'
$psSessions = New-PSSession -ComputerName @(1..10 | %{'myServer{0:00}' -f $_}) -Credential $cred
Invoke-Command -Session $psSessions -ScriptBlock {
    Get-Item -Path 'HKLM:\System\CurrentControlSet\Control\Lsa\Kerberos\Parameters' 
} | Sort-Object PSComputerName
# $psSessions  | Remove-PSSession

This returned:

    Hive: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\Kerberos


Name                           Property                   PSComputerName
----                           --------                   --------------
Parameters                     MaxPacketSize : 1          myServer01
                               MaxTokenSize  : 65535
Parameters                     MaxPacketSize : 1          myServer02
                               MaxTokenSize  : 65535
Parameters                     MaxPacketSize : 1          myServer03
                               MaxTokenSize  : 65535
Parameters                     MaxPacketSize : 1          myServer04
                               MaxTokenSize  : 65535
Parameters                     MaxPacketSize : 1          myServer05
                               MaxTokenSize  : 65535
Parameters                     MaxPacketSize : 1          myServer06
                               MaxTokenSize  : 65535
Parameters                     MaxPacketSize : 1          myServer07
                               MaxTokenSize  : 65535
Parameters                     MaxPacketSize : 1          myServer08
                               MaxTokenSize  : 65535
Parameters                     MaxPacketSize : 1          myServer09
                               MaxTokenSize  : 65535
Parameters                     MaxPacketSize : 1          myServer10
                               MaxTokenSize  : 65535

All looks good; onlyl I'd not expected to see these values / I was running this as a quick sense check before setting the values on these servers to ensure I didn't overwrite anything.

I had a quick look at one of the servers using regedit; and found that MaxTokenSize and MaxPacketSize did not exist.

I then amended the command to use Get-ItemProperty instead of Get-Item:

Invoke-Command -Session $psSessions -ScriptBlock {
    Get-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Lsa\Kerberos\Parameters' -Name 'MaxTokenSize'
} | Sort-Object PSComputerName

This time I got 10 errors:

Property MaxTokenSize does not exist at path HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\Kerberos\Parameters.
    + CategoryInfo          : InvalidArgument: (MaxTokenSize:String) [Get-ItemProperty], PSArgumentException
    + FullyQualifiedErrorId : System.Management.Automation.PSArgumentException,Microsoft.PowerShell.Commands.GetItemPropertyCommand
    + PSComputerName        : myServer01
# ... (and the same for the other 9 servers, with only PSComputerName changing)

Regarding where the values that were returned came from... they're from my local machine. Amending my local registry entries and rerunning the original command showed all "servers" as having the new value.

I'm guessing this is a bug; but because I've not played with PSSessions much so far wanted to check here in case it's an issue with my understanding / usage of these commands, or if there are known gotchas to watch out for when using PSSessions.


Solution

  • Pipe it to fl * or ft * so it doesn't use the format file to display the registry keys. The format file runs get-itemproperty locally to try to display the properties.

    From the bottom of $PSHOME\Registry.format.ps1xml for type Microsoft.Win32.RegistryKey:

    <ScriptBlock>
      $result = (Get-ItemProperty -LiteralPath $_.PSPath |
          Select * -Exclude PSPath,PSParentPath,PSChildName,PSDrive,PsProvider |
          Format-List | Out-String | Sort).Trim()
      $result = $result.Substring(0, [Math]::Min($result.Length, 5000) )
      if($result.Length -eq 5000) { $result += "..." }
      $result
    </ScriptBlock>