SOLVED
Home

Invoke-Command on multiple sessions - Accessing session-specific values within a HashTable

%3CLINGO-SUB%20id%3D%22lingo-sub-1196265%22%20slang%3D%22en-US%22%3EInvoke-Command%20on%20multiple%20sessions%20-%20Accessing%20session-specific%20values%20within%20a%20HashTable%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1196265%22%20slang%3D%22en-US%22%3E%3CP%3EHi%2C%3C%2FP%3E%3CP%3Ewe%20need%20to%20execute%20a%20script%20block%20on%20multiple%20servers%20(eg%20%22S1%22%2C%20%22S2%22%20and%20%22S3%22).%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EThe%20logic%20is%20exactly%20the%20same%20on%20all%20servers%20(Create%20dirs%2C%20copy%20%2F%20move%2F%20rename%20files%2C%20etc.)...%20But%2C%20for%20example%2C%20our%20%22BasePath%22%20can%20differ%20from%20one%20server%20to%20another.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EOur%20implementation%20looks%20like%20this%3A%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CPRE%20class%3D%22lia-code-sample%20language-markup%22%3E%3CCODE%3E%24myConfig%20%3D%20%40%7B%22S1%22%3D%20%40%7BBasePath%3D%22c%3A%5CsomeDir%22%7D%3B%20%22S2%22%3D%20%40%7BBasePath%3D%22c%3A%5CsomeOtherdir%22%7D%3B%20%22S3%22%3D%20%40%7BBasePath%3D%22D%3A%5CyetAnotherDir%22%7D%20%7D%0A%0A%24s%20%3D%20new-PSSession%20-ComputerName%20%22S1%22%2C%22S2%22%2C%22S3%22%0AInvoke-Command%20-Session%20%24s%20-ScriptBlock%20%7B%20%0A%20%20%20%20%24serverName%20%3D%20%24env%3ACOMPUTERNAME%0A%20%20%20%20%24c%20%3D%20%24using%3AmyConfig%0A%20%20%20%20%24serverConfig%20%3D%20%24c%5B%24serverName%5D%0A%20%20%20%20%0A%20%20%20%20%23Do%20something%20with%20%24serverConfig.BasePath%0A%20%20%20%20%24serverConfig.BasePath%0A%7D%3C%2FCODE%3E%3C%2FPRE%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EA%20hashTable%20is%20initialized%20with%20various%20parameters.%26nbsp%3B%20Keys%20are%20set%20to%20the%20same%20values%20as%20the%20-ComputerName%20parameter%20of%20the%20%22New-PSSession%22%20commandlet.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EWithin%20the%20script%20block%20(Invoke-Command)%2C%20we%20use%20the%20hashTable%20to%20retrieve%20the%20server-specific%20value%20based%20on%20the%20%22%24env%3ACOMPUTERNAME%22%20value.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EHere%2C%20the%20code%20assumes%20that%20the%20supplied%20name%20of%20the%20server%20will%20be%20the%20same%20as%20the%20value%20of%20%22%24env%3ACOMPUTERNAME%22....%20For%20example%2C%20if%20someone%20pass%20the%20fully%20qulified%20name%20of%20the%20server%2C%20our%20code%20will%20not%20work.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EWhen%20a%20session%20is%20created%2C%20a%20session%20ID%20is%20assigned.%26nbsp%3B%20We%20could%20use%20the%20%22session%20ID%22%20to%20create%20a%20link%20between%20the%20session%20and%20our%20server-specific%20configuration%20entry.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EIs%20there%20a%20way%20to%20retrieve%20the%20%22Session%20ID%22%20of%20the%20%22current%20session%22%20within%20the%20%22Invoke-Command%22.%26nbsp%3B%20So%20our%20code%20could%20look%20like%20thie%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CPRE%20class%3D%22lia-code-sample%20language-markup%22%3E%3CCODE%3EInvoke-Command%20-Session%20%24s%20-ScriptBlock%20%7B%20%0A%20%20%20%20%24sessionID%20%3D%20%5BGet%20current%20Session%20ID%5D%20%26lt%3B%26lt%3B%26lt%3B-------%0A%20%20%20%20%24c%20%3D%20%24using%3AmyConfig%0A%20%20%20%20%24serverConfig%20%3D%20%24c%5B%24sessionID%5D%0A%20%20%20%20%0A%20%20%20%20%23Do%20something%20with%20%24serverConfig.BasePath%0A%20%20%20%20%24serverConfig.BasePath%0A%7D%3C%2FCODE%3E%3C%2FPRE%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EThanks.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-LABS%20id%3D%22lingo-labs-1196265%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3EWindows%20PowerShell%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1202221%22%20slang%3D%22en-US%22%3ERe%3A%20Invoke-Command%20on%20multiple%20sessions%20-%20Accessing%20session-specific%20values%20within%20a%20HashTable%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1202221%22%20slang%3D%22en-US%22%3E%3CP%3EHey%26nbsp%3B%3CA%20href%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fuser%2Fviewprofilepage%2Fuser-id%2F568628%22%20target%3D%22_blank%22%3E%40michelloubier%3C%2FA%3E%2C%20short%20answer%20is%20to%20check%20out%20the%20%24PSSenderInfo%20variable.%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3ELonger%20answer%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%24PSSenderInfo%20is%20an%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-nz%2Fpowershell%2Fmodule%2Fmicrosoft.powershell.core%2Fabout%2Fabout_automatic_variables%3Fview%3Dpowershell-5.1%23pssenderinfo%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3Eautomatic%20variable%3C%2FA%3E%20that%20only%20exists%20inside%20a%20PSSession%20and%20gives%20you%20a%20bunch%20of%20info%20about%20the%20session%20and%20the%20originating%20connection%20source.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThe%20property%20inside%20that%20variable%20that%20will%20be%20of%20the%20most%20help%20is%20the%20Connection%20String%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%3E%24PSSenderInfo.ConnectionString%3C%2FPRE%3E%0A%3CP%3EThis%20tells%20you%20a%20lot%20about%20the%20connection%2C%20including%20the%20port%20used%2C%20but%20the%20key%20here%20is%20that%20the%20host%20name%20matches%20the%20name%20supplied%20when%20opening%20the%20connection.%20As%20an%20example%20here's%20the%20output%20and%20how%20it%20changes%20when%20connecting%20to%20my%20home%20server%20by%20name%20vs%20by%20IP%20address%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%3Ehttp%3A%2F%2Flocalserver%3A5985%2Fwsman%3FPSVersion%3D5.1.18362.628%3C%2FPRE%3E%0A%3CPRE%3Ehttp%3A%2F%2F192.168.1.50%3A5985%2Fwsman%3FPSVersion%3D5.1.18362.628%26nbsp%3B%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3BYou%20could%20muck%20around%20with%20string%20manipulation...%20but%20it'll%20be%20a%20lot%20easier%20to%20turn%20it%20into%20an%26nbsp%3B%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fdotnet%2Fapi%2Fsystem.uri%3Fview%3Dnetframework-4.8%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3ESystem.Uri%3C%2FA%3E%20object%20and%20just%20pull%20out%20the%20host%20property%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%3E(%5BUri%5D%20%24PSSenderInfo.ConnectionString).Host%3C%2FPRE%3E%0A%3CP%3EBringing%20this%20back%20around%20to%20your%20example%2C%20assign%20that%20host%20property%20to%20your%20%24serverName%20variable%20and%20you%20should%20be%20good%20to%20go.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1206619%22%20slang%3D%22en-US%22%3ERe%3A%20Invoke-Command%20on%20multiple%20sessions%20-%20Accessing%20session-specific%20values%20within%20a%20HashTable%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1206619%22%20slang%3D%22en-US%22%3E%3CP%3E%3CA%20href%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fuser%2Fviewprofilepage%2Fuser-id%2F62408%22%20target%3D%22_blank%22%3E%40Joshua%20King%3C%2FA%3E%26nbsp%3B%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EThis%20is%20exactly%20what%20I%20was%20looking%20for!%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EThanks%20a%20lot.%20%3A)%3C%2Fimg%3E%3C%2FP%3E%3C%2FLINGO-BODY%3E
New Contributor

Hi,

we need to execute a script block on multiple servers (eg "S1", "S2" and "S3").

 

The logic is exactly the same on all servers (Create dirs, copy / move/ rename files, etc.)... But, for example, our "BasePath" can differ from one server to another.

 

Our implementation looks like this:

 

 

 

$myConfig = @{"S1"= @{BasePath="c:\someDir"}; "S2"= @{BasePath="c:\someOtherdir"}; "S3"= @{BasePath="D:\yetAnotherDir"} }

$s = new-PSSession -ComputerName "S1","S2","S3"
Invoke-Command -Session $s -ScriptBlock { 
    $serverName = $env:COMPUTERNAME
    $c = $using:myConfig
    $serverConfig = $c[$serverName]
    
    #Do something with $serverConfig.BasePath
    $serverConfig.BasePath
}

 

 

 

 

A hashTable is initialized with various parameters.  Keys are set to the same values as the -ComputerName parameter of the "New-PSSession" commandlet.

 

Within the script block (Invoke-Command), we use the hashTable to retrieve the server-specific value based on the "$env:COMPUTERNAME" value.

 

Here, the code assumes that the supplied name of the server will be the same as the value of "$env:COMPUTERNAME".... For example, if someone pass the fully qulified name of the server, our code will not work.

 

 

When a session is created, a session ID is assigned.  We could use the "session ID" to create a link between the session and our server-specific configuration entry.

 

Is there a way to retrieve the "Session ID" of the "current session" within the "Invoke-Command".  So our code could look like thie

 

 

Invoke-Command -Session $s -ScriptBlock { 
    $sessionID = [Get current Session ID] <<<-------
    $c = $using:myConfig
    $serverConfig = $c[$sessionID]
    
    #Do something with $serverConfig.BasePath
    $serverConfig.BasePath
}

 

 

 

Thanks.

 

2 Replies
Highlighted
Solution

Hey @michelloubier, short answer is to check out the $PSSenderInfo variable. 

 

Longer answer:

 

$PSSenderInfo is an automatic variable that only exists inside a PSSession and gives you a bunch of info about the session and the originating connection source.

 

The property inside that variable that will be of the most help is the Connection String:

 

$PSSenderInfo.ConnectionString

This tells you a lot about the connection, including the port used, but the key here is that the host name matches the name supplied when opening the connection. As an example here's the output and how it changes when connecting to my home server by name vs by IP address:

 

http://localserver:5985/wsman?PSVersion=5.1.18362.628
http://192.168.1.50:5985/wsman?PSVersion=5.1.18362.628 

 You could muck around with string manipulation... but it'll be a lot easier to turn it into an System.Uri object and just pull out the host property:

 

([Uri] $PSSenderInfo.ConnectionString).Host

Bringing this back around to your example, assign that host property to your $serverName variable and you should be good to go.

 

Highlighted

@Joshua King 

 

This is exactly what I was looking for!

 

Thanks a lot. :)