【问题标题】:PowerShell mass copy to domain computers with multiple checksPowerShell 批量复制到具有多项检查的域计算机
【发布时间】:2016-12-12 15:34:46
【问题描述】:

我正在尝试将许可证文件复制到所有加入域的计算机, 而且我只能使用 PowerShell。 GPO 甚至 (GPO) 计划任务是不可行的,因为在 Server 2003 环境中这些似乎还不可能。 与此相关的应用程序已安装,只需覆盖许可文件。

我希望实现: - 检查是否在线,否则跳过 - 检查 32b 文件夹位置,如果存在,复制,否则跳过 - 检查 64b 文件夹位置,如果存在副本,则跳过 - 将每台计算机的结果写入日志文件,以便修剪成功

第一次尝试;

我目前拥有的代码:

$computers = gc "c:\temp\computers.txt"
$source = "c:\temp\almmodule.lic"
$dest32b = 'c$\program files (x86)\ALM - Automatic Login Module'
$dest64b = 'c$\program files\ALM - Automatic Login Module'
$TestPath32 = Test-Path -path "\\$computer\$dest32b\*"
$TestPath64 = Test-Path -path "\\$computer\$dest64b\*"
foreach ($computer in $computers) {
      if (test-Connection -Cn $computer -quiet) {
      IF (!$TestPath32) {
      Copy-Item $source -Destination "\\$computer\$dest32b" -recurse -force -verbose}
  ELSE {
  "$computer' 32b folder not found. Skipping"}
  IF (!$TestPath64) {
      Copy-Item $source -Destination "\\$computer\$dest64b" -recurse -force -verbose}
  ELSE 
  {"$computer 64b folder not found. Skipping"}
   ELSE {
  "$computer is not online"
  }
}
}

我尝试了一些小的变化,但我似乎无处可去。 还需要创建日志记录。

以我自己为测试目标,运行以上变量,并使用单个命令;

$TestPath32 = 测试路径-路径“\$computer\$dest32b*”

返回:真

复制项目 $source -Destination "\$computer\$dest32b" -recurse -force -verbose

成功,复制文件

此时运行 PowerShell 抱怨最后一个 ELSE 语句。

但大多数时候它无法识别我没有 64b 文件夹,它要么给出错误,要么放置一个文件,以目录作为文件名。

我很茫然,现在已经尝试了很多东西,我害怕制动我所拥有的那一点东西。


第二次尝试;

我已经编辑了代码并注释掉了一些部分,只是为了让 > 模型能够从那里取得进展。

foreach ($computer in $computers) {
$TestPath32 = Test-Path "\\$computer\$dest32b\*"
$TestPath64 = Test-Path "\\$computer\$dest64b\*"
#       if (test-Connection -Cn $computer -quiet) {
      IF (!$TestPath32) {
      Copy-Item $source -Destination "\\$computer\$dest32b\" -recurse -force -verbose}
  ELSE 
      {"$computer' 32b folder not found. Skipping"}
      IF (!$TestPath64) {
      Copy-Item $source -Destination "\\$computer\$dest64b\" -recurse -force -verbose}
  ELSE 
      {"$computer 64b folder not found. Skipping"}
#  ELSE {
# "$computer is not online"
# }
#}
}

现在返回:

PS C:\windows\system32> C:\Temp\ALM 2016 LIC copy.ps1
L2016010' 32b folder not found. Skipping
VERBOSE: Performing operation "Copy File" on Target "Item: C:\temp\almmodule.lic Destination: \\L2016010\c$\program files\ALM - Automatic Login Module\".
Copy-Item : De syntaxis van de bestandsnaam, mapnaam of volumenaam is onjuist.

At C:\Temp\ALM 2016 LIC copy.ps1:14 char:12
+         Copy-Item <<<<  $source -Destination "\\$computer\$dest64b\" -force -verbose}
+ CategoryInfo          : NotSpecified: (:) [Copy-Item], IOException
+ FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.CopyItemCommand

我可以向您保证,我确实拥有 32b 路径。复制项不放置文件。 我显然没有 64b 路径,而且我觉得它会中断,而不是像它应该的那样整齐地返回 $false。

当我弄乱他的路径时(因为我认为这是失败的原因),它有时会在名为“ALM - 自动登录模块”的程序文件中放置一个 文件,它的大小许可证文件。

同样,如果我将行 Copy-Item $source -Destination "\\$computer\$dest32b\" 作为独立运行,它会复制文件。


第三次尝试,现在工作;

$computers = gc "c:\temp\computers.txt"
$source = "c:\temp\almmodule.lic"
$dest32b = 'c$\program files (x86)\ALM - Automatic Login Module'
$dest64b = 'c$\program files\ALM - Automatic Login Module'
foreach ($computer in $computers) {
$TestUp = test-Connection -Cn $computer -quiet
$TestPath32 = Test-Path -pathType container "\\$computer\$dest32b"
$TestPath64 = Test-Path -pathType container "\\$computer\$dest64b"
    IF (!$TestUp) {
        write-host "$computer is not online"
        } ELSE {
        IF (!$TestPath32){
        write-host "$computer' 32b folder not found. Skipping"
    } ELSE {
        Copy-Item $source -Destination "\\$computer\$dest32b\" -force -verbose
        }
        IF (!$TestPath64){
        write-host "$computer 64b folder not found. Skipping"
    } ELSE {
        Copy-Item $source -Destination "\\$computer\$dest64b\" -force -verbose
        }
    }
    }

!$ 的使用完全超出了我的想象,我应该从以下方面工作:

如果不是,那么,否则

现在脚本会跳过不存在的文件夹,还不能测试停机的计算机,但我认为这现在也可以了。

现在我只需要弄清楚,如何以可读格式将输出记录到 1 个日志文件中

【问题讨论】:

  • 为什么不允许 GPO?这似乎是最合适的解决方案,因为您无需在每次新计算机上线(或重建旧计算机等)时手动安装许可证文件。
  • 组策略首选项会是更好的方法,File Item 选项完全符合您的要求,可以过滤以处理 x86/x64。
  • GPO 实际上是不可能的。据我所知,Windows 2003 还不支持那种 GPO。
  • 我已经回滚了 [已解决] 标题黑客,我们不在这里这样做。该问题可能应该进一步回滚 - 它包含问题和答案,但正如您发现的那样,我们有一个单独的答案帖子。您会将其回滚到第一个版本还是中间版本,以最适合该问题?如果您想将任何中间材料转移到正确的答案中,这可能是最好的帮助保存它(在正确的地方)。

标签: powershell if-statement cross-domain copy-item


【解决方案1】:

虽然使用 GPO 或计划任务会更好,或者可能使用 SCCM 进行部署(如果你有的话),在你的限制范围内有一个答案。你的基本想法是正确的,但是将$TestPath32$TestPath64 的分配移到foreach 循环中:

...
foreach ($computer in $computers) {
    if (test-Connection -Cn $computer -quiet) {
      $TestPath32 = Test-Path -path "\\$computer\$dest32b\*"
      $TestPath64 = Test-Path -path "\\$computer\$dest64b\*"
        IF (!$TestPath32) {
...

【讨论】:

  • 我确信这会更好,但目前看来,如果测试路径失败,整个 PS 就会中断,并且不会像我想要的那样行事。我什至注释掉了在线检查,因为它在最后一个 ELSE 语句上一直失败。出于某种原因,我不知道,不可能一个接一个地做超过 1 个 IF 语句。我当然希望我不必求助于 GOTO。我将在我的主要帖子中发布我的新结果的编辑。
【解决方案2】:

我也投票给 GPO,正如 cmets 中所述,您绝对应该考虑这一点。

但是,如果它对您没有帮助, 您的 $TestPath32 和 $TestPath64 变量在您分配您的个人计算机值之前进行评估。我只是为空,因此两者都是 $false。您可以简单地将它们移动到您的 for 循环中,

foreach ($computer in $computers) {    
    if (test-Connection -Cn $computer -quiet) {
       $TestPath32 = Test-Path -path "\\$computer\$dest32b\*"
       $TestPath64 = Test-Path -path "\\$computer\$dest64b\*"
......
} 

另一方面,我希望您已将文件内容格式化为返回一个数组。如果不是,您只需用“,”分隔它并阅读 文件内容:Computer1,Computer2,Computer3

直接将文件作为数组读取

$computers = Get-Content 'c:\temp\computers.txt' # It will read it as an array only. YOu do not need any additional formatting in this case. 

【讨论】:

  • 默认情况下,Get-Content 将文本文件作为数组读取 - 文件中的每一行代表数组中的一个项目。如果每台计算机都在自己的行上,那么您不需要任何额外的格式。
【解决方案3】:

最终版本。 无法像我想要的那样输出文件。

求助于 Start-Transcript。 必须将 Get-Content 放在最后以将输出格式化为可读的内容。

#set-executionpolicy RemoteSigned
$computers = gc "c:\temp\computers.txt"
$source = "c:\temp\almmodule.lic"
$dest32b = 'c$\program files (x86)\ALM - Automatic Login Module'
$dest64b = 'c$\program files\ALM - Automatic Login Module'
Start-Transcript -path C:\temp\ALM-Log.txt -append
foreach ($computer in $computers) { 
$TestUp = test-Connection -Cn $computer -quiet
$TestPath32 = Test-Path -pathType container "\\$computer\$dest32b"
$TestPath64 = Test-Path -pathType container "\\$computer\$dest64b"
    IF (!$TestUp) {
        write-host "$computer is not online`r"
    } ELSE {
        IF (!$TestPath32){
        write-host "$computer' 32b folder not found. Skipping`r"
    } ELSE {
        Copy-Item $source -Destination "\\$computer\$dest32b\" -force -verbose
        }
        IF (!$TestPath64){
        write-host "$computer 64b folder not found. Skipping`r"
    } ELSE {
        Copy-Item $source -Destination "\\$computer\$dest64b\" -force -verbose
        }
    } 
}
Stop-Transcript

$log = Get-Content C:\temp\ALM-Log.txt
$log > c:\temp\ALM-Log.log

关于为什么这有效的实际解决方案 = Test-Path -pathtype container

【讨论】:

    猜你喜欢
    • 2022-11-10
    • 1970-01-01
    • 2011-08-13
    • 1970-01-01
    • 2020-09-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-01
    • 1970-01-01
    相关资源
    最近更新 更多