• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 499
  • Last Modified:

Have a list of computer names - need to copy a file to a location on each one

Hi,
I have a list of ~150 computers.  I need to copy a file from one location (on a server) to each of their hard drives.  The location of the file will be the same across every computer, and every platform (on the root of the drive).

How do I go about doing that?  I have all the computers names, and I have access to (for instance)
\\computer-name\c$\pathoffolder\
so I can manually put the file in each location, but would be nice if there was some sort of batch that would do all of them.

Also, in the event one of the computers are turned off, I don't want the entire thing to fail.  I would like it to just move on to the next computer, etc.

However, I would also like, at the end, to be able to see which clients failed.
0
Mystical_Ice
Asked:
Mystical_Ice
  • 11
  • 7
  • 5
2 Solutions
 
Bill PrewCommented:
This can be done in a BAT script, or do you require VBS?

~bp
0
 
Bill PrewCommented:
Okay, here's a VBS approach that should get you started.  Adjust the strings near the top to your file and folder names.

On Error Resume Next

' Define needed constants
Const ForReading = 1
Const ForWriting = 2
Const TriStateUseDefault = -2

' Define file related paths and templates
strPcFile = "c:\ee\EE27421424\pc.txt"
strLogFile = "c:\ee\EE27421424\log.txt"
strFromFile = "\\servername\share\folder\template.txt"
strToFolder = "folder\subfolder\"
 
' Open PC list and split into array 
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objPcFile = objFSO.OpenTextFile(strPcFile, ForReading, False, TriStateUseDefault)
arrPC = Split(objPcFile.ReadAll, vbNewLine)
objFile.Close

' Open log file
Set objLogFile = objFSO.OpenTextFile(strLogFile, ForWriting, True)

' Process each PC
for Each strPC In arrPC
    If strPC <> "" Then
        ' See if PC is online
        If Ping(strPC) = True Then
            ' Create destination folder if needed
            strFolder = "\\" & strPC & "\C$\" & strToFolder
            If Not objFSO.FolderExists(strFolder) Then
                objFSO.CreateFolder strFolder
            End If
            Err.Clear
            objFSO.CopyFile strFromFile, strFolder, True 
            If Err.Number = 0 Then
                objLogFile.WriteLine strPC & " - file copied."
            Else
                objLogFile.WriteLine strPC & " - copy failed [" & Err.Number & "]."
            End If
        Else
            objLogFile.WriteLine strPC & " - offline."
        End If
    End If
Next

' Close log file
objLogFile.Close

Function Ping(strComputer)
    Dim objShell, boolCode
    Set objShell = CreateObject("WScript.Shell")
    boolCode = objShell.Run("Ping -n 1 -w 300 " & strComputer, 0, True)
    If boolCode = 0 Then
        Ping = True
    Else
        Ping = False
    End If
End Function

Open in new window

~bp
0
 
Steve KnightIT ConsultancyCommented:
Have you got a login script running for all of them - you could just add a copy line to that?

Otherwise if you did want a batch file, and I' not jumping on Bill's solution by offering one I would have suggested doing:

for Loop down you text list.  Look for "failed.txt" first, if not "all.txt"
 ping each host
 if it responds (assuming your firewalls will allow internally)
   copy the file
   if it responds then add to a "done" text file
   if it fails add to a "failed" text file

If you re-run it will try again on the failed ones from failed.txt

Only (slight) advantage over what I think you have there with Bill's (as it stands at the mo) is you can just re-run it the next day say and pickup some more

I guess a couple of dozen lines of batch would you say Bill?

Actually what the hell... someone will be along in a minute with a "proper" solution anyway so here goes.... not tested yet, typed straight in here..

If you want to go batch way can elaborate...

Steve
@echo off
setlocal enabledelayedexpansion

set pclist="pclist.txt"
set destpath=c$\pathoffolder
set sourcepath="\\server\share\somefile.txt"
set failed="failed.txt"
set done="done.txt"
set log="log.txt"

REM If failed file exists copy over pclist.txt so make sure you have a copy of each if needed!
if exist %failed% (
 copy /y %failed% %pclist%
 del %failed% 2>NUL
)

for /f "usebackq delims= " %%C in (%pclist%) do (
  ping -n 1 -w 500 %%C
  if errorlevel 1 (
    echo PING fail for %%C - !errorlevel! >> %log%
    (echo %%C)>> %failed%
  ) ELSE (
    md \\%%C\%destpath% 2>NUL
    copy %sourcepath% \\%%C\%destpath%
    if errorlevel 1 (
      echo COPY fail for %%C - !errorlevel! >> %log%
      echo %%C >> %failed%
    ) ELSE (
      echo COPY OK for %%C >> %log%
      echo %%C >> %done%
    )
  )
)

Open in new window

0
Cloud Class® Course: Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

 
Bill PrewCommented:
@Steve,

If I didn't know better I'd say you had a VBS to BAT conversion tool running over there. :-)

~bp
0
 
Mystical_IceAuthor Commented:
Wow i really appreciate all the help - those scripts look awesome. Thanks so much :)

Unfortunately, I know nothing about scripting :(  If i give you the parameters, could you please, please, enter them in the right places in your script(s) so I make sure they're set up correctly before running?

if i have a file called "computers.txt" in the same folder as the script file I'm going to run, with the computer in this order:

computer1-name
computer2-name
nameofcomputer3
4thcomputername

etc

The file i want to copy is here:
\\fileserver\data\database\newdatabase.xls

The location i want to copy the file to is here: (note it will never have to create a folder, or overwrite anything else in the folder EXCEPT the file that it's copying.  it does need to overwrite the file that's there though):
c:\databasefiles\

That should be all :)

Thanks again so much - really appreciate it.
0
 
Steve KnightIT ConsultancyCommented:
OK, here you go.  Made one small change.  Put your computers.txt in the same directory as the "docopies.cmd" or whatever and launch it from explorer.  It will leave you a "failed.txt" and "done.txt" and "log.txt" in the same directory.  If you run it again it will use the list of computers in "failed.txt" until there are none left.

I haven't run a full test through on this script so if it doesn't work to plan just ask.

hth

Steve
@echo off
setlocal enabledelayedexpansion

set pclist="pclist.txt"
set destpath=c$\databasefiles
set sourcepath="\\fileserver\data\database\newdatabase.xls"
set failed="failed.txt"
set done="done.txt"
set log="log.txt"


if exist %failed% (
 copy /y %failed% %pclist%
 del %failed% 2>NUL
) ELSE (
  copy /Y computers.txt %pclist%
)

for /f "usebackq delims= " %%C in (%pclist%) do (
  ping -n 1 -w 500 %%C
  if errorlevel 1 (
    echo PING fail for %%C - !errorlevel! >> %log%
    (echo %%C)>> %failed%
  ) ELSE (
    md \\%%C\%destpath% 2>NUL
    copy %sourcepath% \\%%C\%destpath%
    if errorlevel 1 (
      echo COPY fail for %%C - !errorlevel! >> %log%
      echo %%C >> %failed%
    ) ELSE (
      echo COPY OK for %%C >> %log%
      echo %%C >> %done%
    )
  )
)

Open in new window

0
 
Bill PrewCommented:
Here are the changes to the VBS approach I posted, based on your files.

On Error Resume Next

' Define needed constants
Const ForReading = 1
Const ForWriting = 2
Const TriStateUseDefault = -2

' Define file related paths and templates
strPcFile = "computers.txt"
strLogFile = "log.txt"
strFromFile = "\\fileserver\data\database\newdatabase.xls"
strToFolder = "databasefiles\"
 
' Open PC list and split into array 
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objPcFile = objFSO.OpenTextFile(strPcFile, ForReading, False, TriStateUseDefault)
arrPC = Split(objPcFile.ReadAll, vbNewLine)
objFile.Close

' Open log file
Set objLogFile = objFSO.OpenTextFile(strLogFile, ForWriting, True)

' Process each PC
for Each strPC In arrPC
    If strPC <> "" Then
        ' See if PC is online
        If Ping(strPC) = True Then
            ' Create destination folder if needed
            strFolder = "\\" & strPC & "\C$\" & strToFolder
            If Not objFSO.FolderExists(strFolder) Then
                objFSO.CreateFolder strFolder
            End If
            Err.Clear
            objFSO.CopyFile strFromFile, strFolder, True 
            If Err.Number = 0 Then
                objLogFile.WriteLine strPC & " - file copied."
            Else
                objLogFile.WriteLine strPC & " - copy failed [" & Err.Number & "]."
            End If
        Else
            objLogFile.WriteLine strPC & " - offline."
        End If
    End If
Next

' Close log file
objLogFile.Close

Function Ping(strComputer)
    Dim objShell, boolCode
    Set objShell = CreateObject("WScript.Shell")
    boolCode = objShell.Run("Ping -n 1 -w 300 " & strComputer, 0, True)
    If boolCode = 0 Then
        Ping = True
    Else
        Ping = False
    End If
End Function

Open in new window

~bp
0
 
Mystical_IceAuthor Commented:
Thanks! Noticed one thing though (and i may not have made this clear enough) - the directory on the computers is going to be, for instance:

\\computername\c$\databasefiles\

It needs to be in unc format with the c hidden share. :(
0
 
Bill PrewCommented:
That is the way I setup the VBS script.

~bp
0
 
Steve KnightIT ConsultancyCommented:
Yup me too!

In the line

copy %sourcepath% \\%%C\%destpath%

%sourcepath% gets replaced by "\\fileserver\data\database\newdatabase.xls"
%%C gets replaced by each computer name in turn from the FOR loop
%destpath% gets replaced by c$\databasefiles

If you have a look at the SET lines at the top you will see where that comes in I hope and can amend if needed.

Steve
0
 
Mystical_IceAuthor Commented:
Thank you both so much!  This worked out excellent.  I ran it today, and no issues!

Was wondering if either (or both) of you are or would be available every so often to do contract script writing for us?  Paid of course.

Let me know - if i could get your email address, that would be great!

I will close this case tomorrow :)

Thanks again!
0
 
Steve KnightIT ConsultancyCommented:
certainly.... Email address and details in my profile - click on dragon-it link above posts.  I believe there is also a 'hire me' link / button that show in there too which sends me a mail too..

Glad it worked and look forward to hearing from you.


Steve
0
 
Bill PrewCommented:
Always open to some work, contact me via LinkedIn on my profile page.

~bp
0
 
Bill PrewCommented:
Or of course via the "Hire Me" button on my profile.

~bp
0
 
Mystical_IceAuthor Commented:
Excellent. I will do that to both of you very soon
Thanks!
0
 
Mystical_IceAuthor Commented:
Thank you both SO much
0
 
Bill PrewCommented:
Welcome, thanks for the feedback.

~bp
0
 
Steve KnightIT ConsultancyCommented:
likewise.... Awaiting that email!

Steve
0
 
Bill PrewCommented:
Shouldn't you be in bed Steve !?

:-)
0
 
Steve KnightIT ConsultancyCommented:
Haha, only midnight, just got #3 in bed and starting on stuff...

Steve
0
 
Steve KnightIT ConsultancyCommented:
@billprew - that 1million mark is getting close, shows you as 974k or so, and I'm 15k behind by the looks... never did get round to checking when the zone stats update.

Steve
0
 
Bill PrewCommented:
Enjoy the "you" time...

~bp
0
 
Bill PrewCommented:
Homestretch baby!

~bp
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 11
  • 7
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now