Powershell

為什麼在登錄腳本期間環境變數 ClientName 沒有更新?

  • January 22, 2019

在 Windows 2012 R2 伺服器上打開 RDS 會話時,我執行了一個 powershell 登錄腳本。我還在啟動文件夾中執行了一個 powershell 腳本。

  • 在登錄腳本中詢問CLIENTNAME環境變數時,我得到了以前打開的會話客戶端名稱,而不是目前的。如果我在關閉前一個會話之前刪除系統資料庫HKCU\Environment\Clientname屬性,我只會在登錄期間為 ClientName 獲得一個空值。
  • 在會話打開後啟動的腳本中詢問 ClientName 變數時,我得到了目前的客戶端名稱(如預期的那樣)。

我有兩個客戶:

  • TestClient1帶 IP 地址10.100.20.201
  • TestClient2帶 IP 地址10.100.20.202

RDS 伺服器是SRV-XA01.

我還使用了一個名為gettscip.exe獲取客戶端 IP 地址的小實用程序

我登錄TestClient1然後關閉會話。然後我從TestClient2(日期為法語格式dd/mm/YYYY)開始一個會話。

登錄腳本:

29/12/2016 10:57:07 : — SRV-XA01 新會話打開 —

29/12/2016 10:57:07 : * 客戶名稱(來自 env:CLIENTNAME):

29/12/2016 10:57:10 : * IP 地址 : 10.100.20.202

29/12/2016 10:57:11 : * ClientName 來自

$$ Environment $$::GetEnvironmentVariables(“user”).ClientName : TestClient1

29/12/2016 10:57:11 : — 登錄腳本成功結束!—

第二個腳本:

29/12/2016 10:57:25 : — 會話打開後執行的腳本 —

29/12/2016 10:57:25 : * 客戶端名稱(來自 env:CLIENTNAME):TestClient2

29/12/2016 10:57:25 : — 腳本結束 —

在登錄腳本中env:CLIENTNAME返回一個空值,[Environment]::GetEnvironmentVariables("user").ClientName返回以前的客戶端名稱。登錄後,一切正常。

我得到的 IP 地址是來自目前客戶端的好地址。

那麼為什麼在登錄腳本執行時 ClientName 環境變數沒有更新呢?

編輯:腳本程式碼。

登錄腳本:

$DomainName = "domain.fr"

# Nom de l'utilisateur
$UserName = $env:USERNAME

$ScriptsDir = "\\$DomainName\Scripts"
$LogDir = "$ScriptsDir\ScriptsXA7\Logs"
$global:LogFile = "$LogDir\$UserName.log"
Import-Module "$ScriptsDir\Systeme\Modules\Write-Log"

# Serveur Citrix
$ComputerName = $env:COMPUTERNAME
# Poste client
$ClientName = $env:CLIENTNAME

Write-Log "--- New Session opening on $ComputerName ---"
Write-Log "* Client Name (from env:CLIENTNAME) : $ClientName"

$IPExe = "$PSScriptRoot\IP\gettscip.exe"
# On lance l'exécutable qui va remonter l'adresse IP et on la stocke dans la variable `$ip`
$ip = Invoke-Expression $IPExe
$ip = $ip -replace "WTSClientAddress: ",""
#  On place cette adresse IP dans la variable d'environnement `CLIENTIP`
[Environment]::SetEnvironmentVariable("CLIENTIP", $ip, "User")
Write-Log "* IP address : $ip"

Write-Log "* ClientName from [Environment]::GetEnvironmentVariables("user").ClientName : $([Environment]::GetEnvironmentVariables("user").ClientName)"
Write-Log "--- Logon script successfully ended ! ---"

第二個腳本:

$DomainName = "domain.fr"

# Nom de l'utilisateur
$UserName = $env:USERNAME

$ScriptsDir = "\\$DomainName\Scripts"
$LogDir = "$ScriptsDir\ScriptsXA7\Logs"
$global:LogFile = "$LogDir\$UserName.log"

Import-Module "$ScriptsDir\Systeme\Modules\Write-Log"

# Serveur Citrix
$ComputerName = $env:COMPUTERNAME
# Poste client
$ClientName = $env:CLIENTNAME

Write-Log "--- Script running after session is opened ---"
Write-Log "* Client Name (from env:CLIENTNAME) : $ClientName"
Write-Log "--- Script ended ---"

正如 Drifter104 所說,為了獲得 的目前值ClientName,必須從HKCU:\Volatile Environment\<session id>

如果在http://www.out-web.net/?p=1479找到了兩個小的 PS 功能。

要獲取會話 ID:

<#
.SYNOPSIS
Returns the RDS session ID of a given user.

.DESCRIPTION
Leverages query.exe session in order to get the given user's session ID.

.EXAMPLE
Get-RDSSessionId

.EXAMPLE
Get-RDSSessionId -UserName johndoe

.OUTPUTS
System.String
#>
function Get-RDSSessionId
{
 [CmdletBinding()]
 Param
 (
   # Identifies a user name (default: current user)
   [Parameter(ValueFromPipeline = $true)]
   [System.String] 
   $UserName = $env:USERNAME
 )
 $returnValue = $null
 try
 {
   # $pid is powershell's automatic variable for its own pid
   return (Get-Process -pid $pid).SessionId
 }
 catch
 {
   $_.Exception | Write-Error
 }
 New-Object psobject $returnValue
}

要讀取ClientName值:

<#
.SYNOPSIS
Returns the RDS client name

.DESCRIPTION
Returns the value of HKCU:\Volatile Environment\<SessionID>\CLIENTNAME

.EXAMPLE
Get-RDSClientName -SessionId 4

.EXAMPLE
Get-RDSClientName -SessionId Get-RDSSessionId

.OUTPUTS
System.String
#>
function Get-RDSClientName
{
 [CmdletBinding()]
 Param
 (
 # Identifies a RDS session ID
   [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
   [System.String] 
   $SessionId
 )
 $returnValue = $null
 $regKey = 'HKCU:\Volatile Environment\{0}' -f $SessionId
 try
 {
   $ErrorActionPreference = 'Stop'
   $regKeyValues = Get-ItemProperty $regKey
   $sessionName = $regKeyValues | ForEach-Object {$_.SESSIONNAME}
   if ($sessionName -ne 'Console')
   {
     $returnValue = $regKeyValues | ForEach-Object {$_.CLIENTNAME}
   }
   else
   {
     Write-Warning 'Console session'
#     $returnValue = $env:COMPUTERNAME
   }
 }
 catch
 {
   $_.Exception | Write-Error
 }
 New-Object psobject $returnValue
}

採用 :

$ClientName = Get-RDSSessionId | Get-RDSClientName

引用自:https://serverfault.com/questions/823169