【问题标题】:Use variable from script inside of scriptblock在脚本块内使用脚本中的变量
【发布时间】:2020-11-11 15:04:41
【问题描述】:

我正在尝试编写一个 Powershell 脚本来注销当前登录的用户。我正在使用Invoke-Command cmdlet 和脚本内的脚本块。

我在脚本中定义了一些我试图传递给脚本块的参数,但我完全可以让它工作。

这是脚本:

param(
    [Parameter()]
    [string]$ComputerName,
    
    [Parameter()]
    [string]$Username
)


$ScriptBlock = {

     $ErrorActionPreference = 'Stop'
     try {
         ## Find all sessions matching the specified username
         $sessions = quser | Where-Object {$_ -match "$args[0]"}
         ## Parse the session IDs from the output
         $sessionIds = ($sessions -split ' +')[2]
         Write-Host "Found $(@($sessionIds).Count) user login(s) on computer."
         ## Loop through each session ID and pass each to the logoff command
         $sessionIds | ForEach-Object {
             Write-Host "Logging off session id [$($_)]..."
             logoff $_
         }
     } catch {
         if ($_.Exception.Message -match 'No user exists') {
             Write-Host "The user is not logged in."
         } else {
             throw $_.Exception.Message
         }
     }
 }


Invoke-Command -ComputerName $ComputerName -Argumentlist $Username -ScriptBlock $ScriptBlock

我正在像这样启动脚本:

.\Logoff-User.ps1 -Computername some_server -Username some_user

现在这确实有效,但它会注销一个随机用户(公平地说,可能不是随机的)。

我的理解是 -ArgumentList 中的 ($Username) 变量被传递给脚本块,它似乎被正确解释了。我可以使用更下方的Write-Host 打印出$args 变量,它会返回正确的用户名。

仅使用 $args 会出错,但指定第一个位置 ($args[0]) 有效,但会断开随机用户的连接。

我显然做错了什么,但我不明白为什么。脚本的行为可能不是我认为的那样。

谢谢!

【问题讨论】:

  • {$_ -match "$args[0]"} 更改为{$_ -match "\b$([regex]::Escape($args[0]))\b"}
  • 当你为$args[0]定义了一个命名参数$Username时,为什么还要使用它?
  • @MathiasR.Jessen 感谢您的回复,我尝试了 sur 建议,但没有成功。该变量似乎不包含用户名,而是输出中列的“标题”(注销会话 id [SESSION])
  • @Noct03 看来您提供的用户名不仅仅是包含用户名的字符串,还可能是对象上格式表的输出。检查您要发送到脚本的内容,它应该是 2 个 strings
  • @Noct03 是的,我知道,但我怀疑您没有发送字符串。检查您在some_user 中的内容。它绝对不仅仅是一个用户名,可能是一个对象或对象的字符串表示形式。

标签: powershell invoke-command


【解决方案1】:

多亏了 Theo,我才弄明白了。我在脚本中使用的$Username 变量未正确传递给脚本块。我必须在脚本块内重新定义一个参数,然后使用Invoke-Command 中的-Argument 将变量作为字符串传递(第一个脚本也没有这样做。

这是最终脚本:

param(
    [Parameter()]
    [string]$ComputerName,
    
    [Parameter()]
    [string]$Username
)

$ScriptBlock = {

     param($User)
     $ErrorActionPreference = 'Stop'
     try  {
         ## Find all sessions matching the specified username
         $sessions = quser | Where-Object {$_ -match $User}
         ## Parse the session IDs from the output
         $sessionIds = ($sessions -split ' +')[2]
         Write-Host "Found $(@($sessionIds).Count) user login(s) on computer."
         ## Loop through each session ID and pass each to the logoff command
         $sessionIds | ForEach-Object {
             Write-Host "Logging off session id [$($_)]..."
             logoff $_
         }
     } catch {
         if ($_.Exception.Message -match 'No user exists') {
             Write-Host "The user is not logged in."
         } else {
             throw $_.Exception.Message
         }
     }
 }

Invoke-Command -ComputerName $ComputerName -Argumentlist $Username -ScriptBlock $ScriptBlock

然后我可以根据需要运行脚本:

.\Logoff-User.ps1 -Computername some_server -Username some_user

感谢 Theo 和其他所有人的帮助!

【讨论】:

    猜你喜欢
    • 2015-06-25
    • 2018-07-09
    • 1970-01-01
    • 2019-01-11
    • 2021-11-04
    • 1970-01-01
    • 2011-06-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多