通过多次检查将 PowerShell 批量复制到域计算机

PowerShell mass copy to domain computers with multiple checks

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

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

第一次尝试;

Code i have currently:

$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"
  }
}
}

I've tried some minor variations, but i can't seem to get anywhere. Also the logging needs yet to be created.

Using myself as a test target, having run above variables, and using single commands;

$TestPath32 = Test-Path -path "$computer$dest32b*"

Returns: True

Copy-Item $source -Destination "$computer$dest32b" -recurse -force -verbose

is successful, and copies the file

Running the PowerShell at the moment complains about the last ELSE statement.

But most of the time it failed not recognizing i don't have a 64b folder, and it either gives an error, or places a file, with the directory as the filename.

I'm at a loss and have now tried so many things i'm afraid of braking the little that i've got.


第二次尝试;

I have edited the code and commented out some parts, just to get a working > model to progress from there.

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"
# }
#}
}

Now returns :

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

i can assure you i DO have the 32b path. The copy-item doesn't place the file. i DO NOT have the 64b path obviously, and i feel it breaks on this instead of just neatly returning $false like it should.

When i mess arround with he Path (because i thought that was the reason for the failure), it sometimes places a file in Program Files named "ALM - Automatic Login Module" which is the size of the license file.

Again, if i run the line Copy-Item $source -Destination "\$computer$dest32b\" as stand-alone, it DOES copy the file.


第三次尝试,现在有效;

$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,正如评论中提到的,你一定要考虑一下。

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

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

另一方面,我希望您已将文件内容格式化为 return 数组。如果不是,您只需用“,”分隔它并阅读 文件内容: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. 

虽然使用 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) {
...

最终版本。 无法让 out-file 像我想要的那样工作。

求助于 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