2

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

halfer
  • 19,824
  • 17
  • 99
  • 186
Sha Gojyo
  • 21
  • 3
  • Why is GPO not allowed? This would seem to be the most appropriate solution, as you wouldn't need to manually install the license file every time a new computer comes online (or old one rebuilt, etc.). – Bill_Stewart Dec 12 '16 at 15:39
  • Group Policy preferences would be a better way to do this, the [File Item](https://technet.microsoft.com/en-us/library/cc772536(v=ws.11).aspx) option doesn exactly what you want and can be filtered to deal with x86/x64. – henrycarteruk Dec 12 '16 at 15:46
  • GPO is actually just impossible. Windows 2003 doesn't support that kind of GPO yet as far as i looked. – Sha Gojyo Dec 13 '16 at 08:10
  • I have rolled back the [solved] title hack, we don't do that here. The question should probably rolled back further - it contains both the question and an answer, but as you have found we have a separate kind of post for answers. Would you roll this back to either the first version, or an intermediate version, as best fits the question? If you want to transfer any of the intermediate material to the answer proper, that may be best in terms of helping to preserve it (in the right place). – halfer Dec 23 '16 at 17:19

3 Answers3

0

I vote for GPO as well, as mentioned in the comments, you should definitely consider that.

However, if it doesn't help you, Your $TestPath32 & $TestPath64 variables are evaluated before you assign your individual computer values. I would simply be null, and hence both will be $false. You can simply move them inside your for-loop,

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

Also in the other hand I hope you have formatted the content of your file to return an array. If not you simply delimit it with "," and read File Content: Computer1,Computer2,Computer3

and read the file as an array directly

$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. 
Prageeth Saravanan
  • 1,053
  • 1
  • 8
  • 24
  • By default `Get-Content` reads a text file as an array - with each line in the file representing an item in the array. If each Computer is on it's own line then you don't need any additional formatting. – henrycarteruk Dec 12 '16 at 16:24
0

While using a GPO or a scheduled task would be better, or possibly deploying with SCCM if you've got it, there is an answer within your constraints. You've got the right basic idea, but move your assignments of $TestPath32 and $TestPath64 into the foreach loop:

...
foreach ($computer in $computers) {
    if (test-Connection -Cn $computer -quiet) {
      $TestPath32 = Test-Path -path "\\$computer\$dest32b\*"
      $TestPath64 = Test-Path -path "\\$computer\$dest64b\*"
        IF (!$TestPath32) {
...
Jeff Zeitlin
  • 9,773
  • 2
  • 21
  • 33
  • I'm sure this is better, but at the moment, it just seems if test-path fails, the entire PS breaks, and doesn't act like i intend it to. I even commented out the online check, because it kept failing on the last ELSE statement. For some reason i'm not aware of, it's impossible to do more then 1 IF statement after another. I sure hope i don't have to resort to GOTO. I will post an edit to my main post with my new results. – Sha Gojyo Dec 13 '16 at 08:41
0

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

Sha Gojyo
  • 21
  • 3