通过多次检查将 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
我正在尝试将许可证文件复制到所有加入域的计算机, 而且我只能使用 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