Hey, Scripting Guy! I regularly update a file that needs to be copied to all of my servers. How can I write a script that will copy the same file (to the same folder) on multiple computers?
— JU
Hey, JU. It’s Monday, May 14th as we write this column, which mean that Mother’s Day in the US is over. And that’s good. Not that the Scripting Guys have anything against mothers, mind you. It’s just that we agree with Anna Jarvis, the person largely responsible for getting Mother’s Day proclaimed a holiday in the first place. After devoting years of her life to the cause, Jarvis soon came to regret having done so; she actually spent the final years of her life trying to get rid of Mother’s Day. Why? Because she was extremely disappointed that a day set aside to honor mothers quickly became just another reason to sell flowers and greeting cards. She was totally aghast that, in just a few years, her simple little holiday had gone commercial.
As a general rule the Scripting Guys are all for commercialization. (In fact, if anyone from Pepsi is reading this, don’t you think The Pepsi-Cola Bottling Company Presents Hey, Scripting Guy! has a nice ring to it?) However, the combination of Mother’s Day and commercialization can only mean one thing: the Scripting Dad and the Scripting Son have to go out shopping. Together.
The Scripting Dad and the Scripting Son get along incredibly well, and they do a lot of things together. Truth be told, the Scripting Dad has always believed that if they ever had a contest for Father and Son Who Get Along the Best he and the Scripting Son would be a shoe-in … unless, of course, the contest was held at a shopping mall. At that point, all bets would be off.
To give you a hint of what we’re talking about, the two had no sooner walked into the mall when the Scripting Son found the … perfect … present. “Mom has an MP3 player,” he said. “Let’s get her a case for that and then go.”
“Well, we can get her the case,” said the wise and thoughtful Scripting Dad. “But that’s not enough; we’ll have to get her something else as well.”
“Stop yelling at me! Every time we go shopping you end up yelling at me.”
Which, come to think of it, might very well be true.
Believe it or not, the two eventually found a present, bought it, and made it back home safe and sound (a little bruised and battered, but both still alive). Interestingly enough, in addition to buying a present for his mom, the Scripting Son somehow managed to get two new T-shirts and a couple scoops of Double Chocolate frozen yogurt for himself out of the trip as well.
Thank goodness he isn’t spoiled.
Oh, well. The moral of the story? If the Scripting Dad and the Scripting Son can survive a trip to the mall together, copying the same file to multiple computers ought to be a piece of cake:
Const ForReading = 1 Const OverwriteExisting = TRUESet objFSO = CreateObject(“Scripting.FileSystemObject”) Set objFile = objFSO.OpenTextFile(“C:\Scripts\Computers.txt”)
Do Until objFile.AtEndOfStream strComputer = objFile.ReadLine strRemoteFile = “\\” & strComputer & “\C$\Scripts\Test.doc” objFSO.CopyFile “C:\Scripts\Test.doc”, strRemoteFile, OverwriteExisting Loop
Before we go much further we should point out that there are a number of different ways we could approach the issue of copying files to multiple computers. We chose to tackle this task by reading computer names from a text file. (This is known as the Peter Costantini Memorial Approach in honor of the legendary Peter Costantini, who never met a script he couldn’t enhance by having it read computer names from a text file.) Would you rather select computer names from a dialog box, supply computer names as command-line arguments, or maybe grab the names of all the computers in an OU? Then you need to take a look at our Remote/Multiple Computer Scripting Templates, don’t you?
We’re assuming that we have a very simple little text file (C:\Scripts\Computers.txt) containing the names of all the computers we need to copy the file to. That text file should look something like this:
atl-fs-01 atl-fs-02 atl-fs-03 atl-fs-04 atl-fs-05
Note. In case you’re wondering, this is known as the Bob Wells Memorial Text File, in honor of the legendary Bob Wells, who developed the official Scripting Guys computer naming convention back in 1768. Bob hailed from the legendary – and mythical – city of Atlanta, which is why our computer names always start with the letters atl. Like we said, in case you’ve been wondering. |
As you might expect, our plan is to open the text file, read in the computer names, and then copy the file to each of those machines.
To do that we start out by defining a pair of constants, ForReading and OverWriteExisting. We’ll need the ForReading constant to open the text file for reading; we’ll need the OverWriteExisting constant in order to copy over any existing version of the target file that might already be lingering on one of the remote computers.
Note. Yes, there are a lot of nuances involved in copying files, aren’t there? That’s one good reason why you should read this month’s Sesame Script column. What do you mean you need two good reasons before you’ll read the column? Fine; this month you’ll also learn what the word subrogation means. |
With the constants defined we next create an instance of the Scripting.FileSystemObject object, then use the OpenTextFile method to open the file C:\Scripts\Computers.txt (the file containing our list of computer names):
Set objFSO = CreateObject(“Scripting.FileSystemObject”) Set objFile = objFSO.OpenTextFile(“C:\Scripts\Computers.txt”)
With the text file open our next step is to read through the file line-by-line. To do that we set up a Do Until loop designed to run until we’ve reached the end of the file (or, if you prefer, until the file’s AtEndOfStream property is True):
Do Until objFile.AtEndOfStream
The first thing we do inside that loop? We use the ReadLine method to read the initial line of the file (that is, the first computer name) and then store that value in a variable named strComputer:
strComputer = objFile.ReadLine
Now it gets a tiny bit tricky. If you’re a devoted reader of Hey, Scripting Guy! (and you don’t have to answer that; like Santa Claus, we know who’s been bad or good) then you know that we always mention the fact that the FileSystemObject is designed to work against the local computer. And that’s true; that’s exactly what it’s designed for. However, the FileSystemObject can work with UNC paths. That means that we can copy a file to a shared folder on a remote computer (for example, \\atl-fs-01\Public\Shared_Files). It also means that we can copy a file to any folder on a remote computer provided that we use the administrative share (e.g., \\atl-fs-01\C$\Scripts). In our example, we’re going to use the administrative share.
Note. Does that mean that this script will fail if you’ve disconnected the administrative share on a computer? Yes. For better or worse you’ll have to use either an administrative share or a shared folder in order to perform this task. |
In a minute or two we’ll use the CopyFile method to copy the file to the first computer listed in Computers.txt. Before we can do that, however, we need two pieces of information: the complete path to the file we want to copy, and the complete path (including file name) to the location where we want the file copied. Determining the path to the file to be copied is easy; after all, that’s a file stored on our local computer. (In this case, C:\Scripts\Test.doc).
Determining the location on the remote computer is a bit more complciated; that’s because we need to use UNC paths, and one key element of the UNC path – the computer name – will change with each iteration of our loop. Shoot; it is hopeless, isn’t it?
Oh, wait: no it’s not. After all, that’s what this line of code is for:
strRemoteFile = “\\” & strComputer & “\C$\Scripts\Test.doc”
All we’re doing here is constructing a UNC path, substituting the value of the variable strComputer for the computer name. When we’re done combining the various parts of the path we’ll end up with a value like this, which we then assign to the variable strRemoteFile:
\\atl-fs-01\C$\Scripts\Test.doc
And guess what? That value just happens to be the UNC path we need in order to copy the file to the computer atl-fs-01. That’s something we do using this line of code:
objFSO.CopyFile “C:\Scripts\Test.doc”, strRemoteFile, OverwriteExisting
Here, at long last, we call the CopyFile method, passing three parameters:
• |
The path to the local file (C:\Scripts\Test.doc), the file we want copied. |
• |
The UNC path for the remote computer (stashed in the variable strRemoteFile). |
• |
The constant OverWriteExisting (just in case Test.doc already exists in the C:\Scripts folder on atl-fs-01). |
We copy the file, then loop around and repeat the process with the next computer in the list.
And that, as they say in the movie business, is a wrap.
That should get you started, JU. And don’t worry: we wouldn’t let you go without one last Mother’s Day anecdote. When the Scripting Son was a few months old his Scripting Mom went back to work, and the Scripting Son started going to a day care in downtown Seattle. For Mother’s Day the babies all “made” their mothers little ceramic handprints engraved with their names and the date. (Yes, very cute.) When the Scripting Dad went to pick up the Scripting Son the Friday before Father’s Day he assumed he’d get a similar gift. Instead, he got absolutely nothing. He jokingly mentioned this to one of the day care providers, who replied – in all seriousness – “We don’t do anything for Father’s Day. Most children don’t have fathers.”
Obviously the Scripting Dad should have paid more attention in his high school biology class.
0 comments