【问题标题】:Powershell ForEach loop with embedded IF statements带有嵌入式 IF 语句的 Powershell ForEach 循环
【发布时间】:2015-07-20 20:39:09
【问题描述】:

开始编写 powershell 脚本(非常新),因为 SCCM 倾向于更好地响应它们(客户端和服务器) 因此,上述内容是我的第一个脚本:

#Changes the 'ProvisioningMode' Key in the registry to False
$ProvisiongMode = New-ItemProperty -Path Registry::HKLM\SOFTWARE\Microsoft\CCM\CcmExec -Name ProvisioningMode -Value False -Force
#Clears or 'nulls' the SystemTaskExcludes key in the registry
$SystemTaskExludes = New-ItemProperty -Path Registry::HKLM\SOFTRWARE\Microsoft\CCM\CcmExec -Name SystemTaskExcludes - Value "" - Force
#----------------------------------------------------------------------------------------------
$Success = "C:\Path\to.log"
$Failure = "C:\Path\to.log"
$Computers = Import-Csv "C:\Path\to.csv"
$SearchStr = Get-ItemProperty -Path Registry::HKLM\SOFTWARE\Microsoft\CCM\CcmExec | select-object ProvisioningMode
$Online = Test-Conntection -Computername $ComputerName -Count 1 -Quiet

ForEach ($ComputerName in $Computers)
if ($Online -eq 'False')
{
    Write-Output $ComputerName`t'Connection Failed'  >> $Failure
}
Else
{
    if ($SearchStr -eq True)
     {
        $ProvisioningMode
        $SystemTaskExcludes 
     }

}

#Second Check
if ($SearchStr -eq 'False')
{
    Write-Output $ComputerName`t'Registry has been changed' >> $Success
}

有问题的是$Online 变量。我想看看计算机是否对 ping 有响应,如果是,则继续运行 $ProvisioningMode$SystemTaskExclude。 然后另一个问题是查询该键以查看它是否已更改。那个问题是$SearchStr = Get-ItemProperty -Path Registry::HKLM\SOFTWARE\Microsoft\CCM\CcmExec | select-object ProvisioningMode返回

 ProvisionMode
 -----------------
 False

我不能只获取false 数据。 就像我说的那样;在 powershell 上非常新,写一些我将使用的东西可以帮助我学习。

编辑:我尝试过的是

ForEach ($Name in $Computers) 
{
Test-Connection -BufferSize 2 -Computername $Name.ComputerName -Count 1 -Quiet | Write-Output $Online
}

if ($Online -eq 'True') {Write-Output $Name`t'Computer is online' >> C:\Online.txt}

以及同一事物的许多变体。

 Test-Connection -BufferSize 2 -Computername $Name.ComputerName -Count 1 -Quiet 

返回数据,这是我想要的,但我需要将其输入到 If 语句中,并且仍然为 $StringStr 和日志文件保留 $Name

你们中的一些人想知道,这会使客户端在运行 OSD 时退出配置模式。它修复了“无自签名证书”问题。

【问题讨论】:

  • 阅读“嵌入式”标签的描述
  • 哈哈嗯,它应该是“嵌入的 if 语句”。我的错,奥拉夫。

标签: powershell if-statement foreach


【解决方案1】:

尽管 PowerShell 中布尔值的字符串表示形式是 TrueFalse,但比较此类值的正确方法是使用 $true$false 变量。

此外,将Test-Connection 的结果分配给$Online=

$Online = Test-Connection -BufferSize 2 -Computername $Name.ComputerName -Count 1 -Quiet

if($Online -eq $true){
    # Machine responds to ping, do stuff!
}

但实际上没有必要进行比较。如果$Online 已经等于$frue$false,您可以在if 语句中单独使用它:

if($Online){
    # Machine responds to ping, do stuff!
}

我假设$ProvisionMode$SystemTaskExcludes$SearchStr 都是您要在远程机器上执行的语句,而不是在 SCCM 服务器本身上。

为此,您需要连接到机器并指示它执行 *-ItemProperty 语句。

# Enclosing statements in {} creates a ScriptBlock - a piece of code that can be invoked later!
$ProvisionMode = { 
    #Changes the 'ProvisioningMode' Key in the registry to False
    New-ItemProperty  -Path Registry::HKLM\SOFTWARE\Microsoft\CCM\CcmExec -Name ProvisioningMode -Value False -Force 
}

$SystemTaskExludes = { 
    #Clears or 'nulls' the SystemTaskExcludes key in the registry
    New-ItemProperty -Path Registry::HKLM\SOFTRWARE\Microsoft\CCM\CcmExec -Name SystemTaskExcludes - Value "" - Force 
}

$SearchStr = { 
    Get-ItemProperty -Path Registry::HKLM\SOFTWARE\Microsoft\CCM\CcmExec | Select-Object -ExpandProperty ProvisioningMode
}

#----------------------------------------------------------------------------------------------
$LogFilePath = "C:\Path\to.log"

$Computers = Import-Csv "C:\Path\to.csv"


foreach($Computer in $Computers){

    $Online = Test-Connection -Computername $Computer.Name -Count 1 -Quiet

    if(-not $Online)
    {
        "$ComputerName`t'Connection Failed'" | Out-File -FilePath $LogFilePath -Append
    }
    else
    {
        $SearchResult = Invoke-Command -ComputerName $Computer.Name -ScriptBlock $SearchStr
        if ($SearchResult)
        {
            # The call operator (&) invokes the scriptblock
            Invoke-Command -ComputerName $Computer.Name -ScriptBlock $ProvisionMode
            Invoke-Command -ComputerName $Computer.Name -ScriptBlock $SystemTaskExludes
        }
        else # SearchStr must be $false, or non-existing
        {
            "$ComputerName`t'Registry has been changed'" | Out-File -FilePath $LogFilePath -Append
        }
    }
}

为简单起见,我将Invoke-Command-ComputerName 参数一起使用,但在实际情况中,我将使用New-PSSession 设置一个PSSession,并将其重新用于与Invoke-Command -Session 的连接

【讨论】:

  • 所以脚本块允许在 PC 上远程执行(是的,不是服务器),哦,我知道你在用 $SearchResult 做什么。如果它为真,则运行块,否则什么也不做(预期结果为“假”)。我花了一分钟来破译,但我现在明白了。这比我预期的要简单得多。谢谢马蒂亚斯!!为什么选择 Out-File 而不是 Write-Output?
  • Write-Output 是隐含的,它也可能并不意味着你的想法。它不写入文件或变量,而是获取一个或多个对象并通过管道发送它们
  • ScriptBlocks 只是“可移植代码”,您也可以使用 & $ProvisionMode 在本地调用它,但是是的,它们非常适合远程执行
猜你喜欢
  • 2017-01-13
  • 1970-01-01
  • 2021-11-09
  • 2012-06-22
  • 1970-01-01
  • 2019-12-12
  • 2021-12-13
  • 2012-06-20
  • 2019-09-13
相关资源
最近更新 更多