Search code examples
powershellif-statementcross-domaincopy-item

PowerShell mass copy to domain computers with multiple checks


I'm trying to copy a license file to all domain joined computers, and i am only able to use PowerShell. GPO or even (GPO) scheduled task is a no-go, because these don't seem to be possible yet within a Server 2003 environment. The application this is regarding is already installed, and only the license file needs to be overwritten.

i am hoping to achieve: - check if online, else skip - check for 32b folder location, if exist, copy, else skip - check for 64b folder location, if exist copy, else skip - write every computers' result to a log file so i can prune successful

1st attempt;

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.


2nd attempt;

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.


3rd attempt, now working;

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

The use of !$ totally went over my head, and i was supposed to work from a point of:

IF NOT, THEN, ELSE

Now the script skips folders not present, havn't been able to test a down computer yet, but i assume this now works also.

Now all i need to figure out, is how to log the output into 1 logfile, in a readable format


Solution

  • Final version. Couldn't get out-file to work like i wanted to.

    Resorted to Start-Transcript. Had to put Get-Content at the end to format the output to something that was readable.

    #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
    

    The actual solution as to why this works = Test-Path -pathtype container