【问题标题】:Testing if a user exist locally always return false测试用户是否本地存在总是返回 false
【发布时间】:2022-02-28 19:43:19
【问题描述】:

我正在尝试编写一个自定义的 powershell 脚本,如果不存在具有指定名称的用户,它将创建一个本地用户。

我有这个脚本:

function Ensure-LocalUser
{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [string] $userName,
        [Parameter(Mandatory=$true)]
        [string] $passWord
    )
    process{

        $objOu = [ADSI]"WinNT://${env:Computername}"
        $localUsers = $objOu.Children | where {$_.SchemaClassName -eq 'user'}  | Select {$_.name[0].ToString()} 

        if($localUsers -NotContains $userName)
        {
            $objUser = $objOU.Create("User", $userName)
            $objUser.setpassword($password)
            $objUser.SetInfo()
            $objUser.description = "CMM Test user"
            $objUser.SetInfo()

            return $true
        }
        else
        {
            return $false
        }

    }
}

与创建用户相关的部分有效,但是我的-NotContains验证总是返回false。这会导致创建用户的尝试失败,因为该用户已经存在。使用调试器,我可以看到 $localusers 实际上包含我要查找的用户名。

如何更正我的脚本以达到我的目标?

【问题讨论】:

    标签: powershell


    【解决方案1】:

    改变这一行

    localUsers = $objOu.Children | where {$_.SchemaClassName -eq 'user'}  | Select {$_.name[0].ToString()} 
    

    $localUsers = $objOu.Children | where {$_.SchemaClassName -eq 'user'}  | % {$_.name[0].ToString()}
    

    【讨论】:

    • 这解决了我的问题。但是我不明白其中的区别。 Select-Object 命令不是投影脚本块的结果吗?当我在 PowerShell ISE 的直接窗口中键入 $localUsers 时,我可以看到 System.Array 中的值。
    • @x0n 是如何写的:你的 $localUsers 是一个 PscustomObject。要使用 -contains,您需要一个字符串数组来与 $username 之类的字符串进行比较。
    • @Christian 从技术上讲 - 包含适用于任何对象,而不仅仅是字符串 - 它只是 他的 用法需要字符串,因为右值操作数是一个字符串。
    • @x0n。是的,我知道,我的英语不好... 'with a string like $username' 我的意思是你在说什么!
    【解决方案2】:

    你做错了;)你真的想要这个(这将创建一个字符串数组):

    $ou.Children | where {$_.SchemaClassName -eq 'user'}  | foreach {
          $_.name[0].tostring() }
    

    您的代码正在创建一个具有名为“$_.name[0].ToString()”的属性的自定义对象

    【讨论】:

    • 感谢实际有效的答案。我将标记 Christian 的人,因为他是第一个提出解决方案的人。
    【解决方案3】:

    在 PowerShell 5.1(在 Windows 10 中可用)及更高版本中,我们可以使用两个 cmdlet 来检查本地用户的存在和创建新的本地用户:Get-LocalUserNew-LocalUser。 所以我们可以用更紧凑的方式重写上面的函数:

    function Ensure-LocalUser
    {
        [CmdletBinding()]
        param(
            [Parameter(Mandatory=$true)]
            [string] $userName,
            [Parameter(Mandatory=$true)]
            [string] $passWord
        )
        process{
            $out = Get-LocalUser -Name $userName -ErrorAction SilentlyContinue
            if($out -eq $null)
            {
                $passEnc = ConvertTo-SecureString -String $passWord -AsPlainText -Force
                New-LocalUser -Name $userName -Password $passEnc -AccountNeverExpires -PasswordNeverExpires
                return $true
            }
            else
            {
                write-host ("User '"+ $userName + "' already exists")
                return $false
            }
        }
    }
    

    然后像这样调用函数:

    Ensure-LocalUser "john" "p@ssw0rd"

    【讨论】:

      【解决方案4】:

      我知道我迟到了,但这里有一个简单的方法可以找到本地用户并输出他们的当前状态。

      # Find User Account to change
      $usercheck = Get-WmiObject Win32_UserAccount -Filter "LocalAccount='true' and Name='Administrator'"
      
      if($usercheck.disabled -eq $false){write-host "Account has been found"}
      elseif($usercheck.disabled -eq $true){write-host "Account has been found, but disabled"}
      else{write-host "Account has not been found."}
      

      【讨论】:

      • 永远不会太晚 :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-20
      • 1970-01-01
      • 2013-03-26
      相关资源
      最近更新 更多