要在域中的所有计算机上运行的Powershell脚本-等待计算机联机

要在域中的所有计算机上运行的Powershell脚本-等待计算机联机,powershell,active-directory,offline,Powershell,Active Directory,Offline,我拼凑了以下PowerShell脚本,该脚本从我们域上OU中每台计算机的公共桌面上删除一个文件,然后将替换文件复制回以替换它。它工作得很好,除了离线的机器。一旦脚本上线,让它在机器上运行的最佳方式是什么?我的最佳猜测是让它将任何脱机机器放入列表中,然后在几个小时后重新运行该列表中的计算机。有更好的办法吗 $DESTINATION = "c$\Users\Public\Desktop" $REMOVE = "ComputerName" $strFilter = "computer" $objDo

我拼凑了以下PowerShell脚本,该脚本从我们域上OU中每台计算机的公共桌面上删除一个文件,然后将替换文件复制回以替换它。它工作得很好,除了离线的机器。一旦脚本上线,让它在机器上运行的最佳方式是什么?我的最佳猜测是让它将任何脱机机器放入列表中,然后在几个小时后重新运行该列表中的计算机。有更好的办法吗

$DESTINATION = "c$\Users\Public\Desktop"
$REMOVE = "ComputerName"
$strFilter = "computer"

$objDomain = New-Object System.DirectoryServices.DirectoryEntry

$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = "LDAP://OU=MyOU,DC=Domain,DC=com"
$objSearcher.SearchScope = "Subtree" 
$objSearcher.PageSize = 1000 

$objSearcher.Filter = "(objectCategory=$strFilter)"
$colResults = $objSearcher.FindAll()

foreach ($i in $colResults) 
    {
        $objComputer = $i.GetDirectoryEntry()
        $REMOVE = $objComputer.Name
        #Ping system to see if it's on
        $rtn = Test-Connection -CN $REMOVE -Count 2 -BufferSize 16 -Quiet

        IF($rtn -match 'True') {

            Remove-Item "\\$REMOVE\$DESTINATION\SparksNET.url" -Recurse
            Copy-Item "\\spd3\PD IT stuff\Software\Desktop Icons\mySparks.website" "\\$REMOVE\$DESTINATION"   
        }
        ELSE { 
        }

    }

每个人都是100%正确的,你应该通过GPO做到这一点。然而,如果你疯狂地想通过PowerShell来实现,你可以按照我下面概述的方式来实现。我把你的代码扔进去了,所以可能有点乱

从列出个人电脑列表开始,然后将它们全部发送到工作中

if(Test-Path "c:\LogPath"){
}else {
mkdir "c:\LogPath"
}

$time=Get-Date -Format s
$date=Get-Date -Format F

"LOG FILE CREATED - $date" | Add-Content $log

$objDomain = New-Object System.DirectoryServices.DirectoryEntry

$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = "LDAP://OU=MyOU,DC=Domain,DC=com"
$objSearcher.SearchScope = "Subtree" 
$objSearcher.PageSize = 1000 

$objSearcher.Filter = "(objectCategory=$strFilter)"
$colResults = $objSearcher.FindAll()

foreach($Obj in $colResults){ 

        $objComputer = $Obj.GetDirectoryEntry()
        $remotePC = $objComputer.Name


    #Imports all functions used in script
    . "C:\PathToYourJobScript.ps1"



    #Creating Jobs
    $jobs = (get-job -state running | Measure-Object).count 
        Get-job -State Completed | Remove-Job
            while($jobs -ge 5)    
               {
                  #get currently running jobs after restart

            get-job -state running | %{write-host $_.PSBeginTime} | ?{($_.PSBeginTime - $(Get-Date)).Minutes -gt 10} | Remove-Job
            Write-host "Currently running maximum threads at: $jobs `n Sleeping 5 seconds"  -ForegroundColor DarkYellow

            start-sleep -seconds 5

            $jobs = (get-job -state running | Measure-Object).count 
               }

    Write-host "`t`tCreating Thread for $remotePC" -ForegroundColor Yellow

    start-job $DeleteFile -ArgumentList $remotePC -Name $remotePC 
    Receive-Job $remotePC

    "$remotePC; Starting Job at; $time" | Add-Content $log
    }
在实际的作业脚本PS1中,将上面的代码包装成一个函数

$DeleteFile={Param(
     [Parameter(Mandatory=$true)]
    [string]$remotePC
    ) 
<#
.SYNOPSIS 

.DESCRIPTION 

.NOTES 


#>

##Globals
$DESTINATION = "c$\Users\Public\Desktop"
$REMOVE = "ComputerName"
$strFilter = "computer"

        #Ping system to see if it's on


        if(Test-Connection -ComputerName $remotePC -Count 2  -BufferSize 16 -ErrorAction SilentlyContinue){
            Remove-Item "\\$REMOVE\$DESTINATION\SparksNET.url" -Recurse
            Copy-Item "\\spd3\PD IT stuff\Software\Desktop Icons\mySparks.website" "\\$REMOVE\$DESTINATION" 
            "$remotePC; Removal Complete; $time" | Add-Content $log  
            }
            ELSE 
            { 
            do {Start-Sleep -Seconds 300;  "$remotePC; Ping Fail; $time" | Add-Content $log}
            until (Test-Connection -ComputerName $remotePC -Count 2  -BufferSize 16 -ErrorAction SilentlyContinue)
            Remove-Item "\\$REMOVE\$DESTINATION\SparksNET.url" -Recurse
            Copy-Item "\\spd3\PD IT stuff\Software\Desktop Icons\mySparks.website" "\\$REMOVE\$DESTINATION" 
            "$remotePC; Removal Complete; $time" | Add-Content $log  
            }
}
$DeleteFile={Param(
[参数(必需=$true)]
[字符串]$remotePC
) 
##全球的
$DESTINATION=“c$\Users\Public\Desktop”
$REMOVE=“ComputerName”
$strFilter=“计算机”
#Ping系统以查看它是否打开
if(测试连接-计算机名$remotePC-计数2-缓冲区大小16-错误操作SilentlyContinue){
删除项目“\\$Remove\$DESTINATION\SparksNET.url”-递归
复制项目“\\spd3\PD IT stuff\Software\Desktop Icons\mySparks.website”“\\$REMOVE\$DESTINATION”
“$remotePC;删除完成;$time”|添加内容$log
}
其他的
{ 
执行{启动睡眠-300秒;“$remotePC;Ping失败;$time”|添加内容$log}
直到(测试连接-计算机名$remotePC-计数2-缓冲区大小16-错误操作SilentlyContinue)
删除项目“\\$Remove\$DESTINATION\SparksNET.url”-递归
复制项目“\\spd3\PD IT stuff\Software\Desktop Icons\mySparks.website”“\\$REMOVE\$DESTINATION”
“$remotePC;删除完成;$time”|添加内容$log
}
}

这将每5分钟检查一次电脑是否在线,并等待收到响应后继续。一旦将项目放入作业中,您就失去了其进度的站点,并希望相应地进行日志记录,以便了解其位置。

为什么不将其作为组策略来执行呢?通过该路径更新文件很容易。部分原因是我想学习PowerShell,部分原因是我不知道GPO是什么。哈哈。主要是因为我想学习powershell。学习工具的一部分是在它不是最合适的解决方案时学习@MarcB是正确的,通过GPO做这件事会更好。不是想让你气馁,但是使用GPO可以消除你遇到的问题。太棒了。我想我会采纳你的建议,使用GPO来完成这项工作。但我有一个问题:如果我使用GPO,这不会增加每台计算机的GPO处理时间,即使它们已经完成了任务?我试图将我拥有的GPO数量限制在绝对必要的数量。我对GPO不太精通,但我知道运行脚本和离线机器的麻烦。如果您只想尝试一次,并且不会有太多人离线,那么PowerShell可能还可以。如果您有很多机器,并且很多机器将处于脱机状态,那么您可能希望查看GPO或SCCM以进行删除。至于处理时间,你最终还是会删除GPO的。@MattDryden所以我刚和我们的GPO人员谈过——影响非常小。如果你有机器在现场连接,可能需要更长的时间,但它是如此之短以至于不被注意到。它应该被绑定到一个已经创建的对象中,如果该组存在一个对象的话。很好的信息。谢谢你,罗伯特!我用GPO推了一下,效果很好。不过我会保留这个脚本以备将来使用。谢谢