Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to move user files and update the registry.
Hey, Scripting Guy! I need to move a bunch of user files from their local computer to a network share so we can back up the user's data prior to migrating their desktops. I know there are various tools I can use to do this, but our scenario is pretty simple because the user profile data is all located in specific folders. After I have moved their data, I need to update a registry key. That key will be read by another app, and the machines will be wiped before we drop a new image. Needless to say, I need to ensure I do not update the registry before I have moved the data. Can you help me?
—WM
Hello WM,
Microsoft Scripting Guy, Ed Wilson, is here. Well, this is the end of a pretty cool and exciting week. It begin with the Windows PowerShell Summit in Charlotte, and then we had a way cool Windows PowerShell User Group meeting with Lee Holmes and Paul Higinbotham. Here is a picture from the user group meeting:
The Scripting Wife has been busy finalizing the schedule for the guests who will be at the Scripting Guys booth at Ignite. That guest list will be published tomorrow right here on the Hey, Scripting Guy! Blog. If you are one of the lucky ones who were able to get tickets to Ignite, you will want to make sure you add our guests to your schedule, so you do not miss out on a unique opportunity to talk one-on-one with some of the awesome people in the Windows PowerShell community.
Yep, it has been busy and crazy fun.
You know, WM, I am reminded of an incident that happened when I was in consulting many years ago. The IT admin at one of my customer's work sites wrote a script that did the following:
- Copy files from users computers.
- Make connection to network share.
- Copy the files to the network share.
- Delete files from the user's computers.
Unfortunately, steps 2 and 3 failed. More unfortunately, step 4 completed, and so they had the opportunity to test their restore procedures. Luckily, they had good backups—but still, it wasted most of the day, and it actually continued to plague them for several weeks after that.
Set up the environment
The first thing I want to do is to create a few folders, to play with. To do this, I wrote a bit of code that will copy the contents of my scratch folder to three different destinations. Here is the code:
$source = "C:\fso"
$path = "c:\fso1","c:\fso2","c:\fso3"
$path | % { Copy-Item -Path $source -Destination $_ -Force -Recurse}
Next, I wrote a simple two-line bit of code to copy the contents of the three folders to a backup folder. I decided it would be useful to include the computer name under the backup folder, and then have a folder for each of the three folders I created earlier. Here is the code:
$paths = "C:\fso1", "C:\fso2", "C:\fso3"
Copy-Item -Path $paths -Destination "c:\backup\$env:computername" -Force -Recurse –Container
Unfortunately, when I run this little script, the contents of the C:\FSO1 folder ends up in the root, and then I get the folders for the second and the third folder. Here is what this looks like in the file explorer:
Well, that is not what I wanted. What I wanted was three folders under the computer name folder. I talked with Microsoft PFEs extraordinaire and Honorary Scripting Guys, Brian Wilhite and Jason Walker, and they figured out that if I create the first folder, when I do the copy, it will come out correctly. So I played around and came up with the following script.
$paths = "C:\fso1", "C:\fso2", "C:\fso3"
$destination = "c:\backup\$env:computername"
If(!(Test-Path $destination))
{ md -Path ("{0}\{1}" -f $destination, $paths[0].Substring(3))| out-null }
Copy-Item -Path $paths -Destination $destination -Force -Recurse -Container
Here is what the folders look like now:
So now I have my code to copy the folders to a destination. Unfortunately, the Windows PowerShell FileSystem provider does not support transactions, so I cannot start a transaction to move my files. But what I can do is use Try/Catch/Finally, and if no errors occur, then I can delete the files. Here is what that might look like:
$paths = "C:\fso1", "C:\fso2", "C:\fso3"
$destination = "c:\backup\$env:computername"
$ErrorActionPreference = "Stop"
If(!(Test-Path $destination))
{ md -Path ("{0}\{1}" -f $destination, $paths[0].Substring(3))| out-null }
Try {
Copy-Item -Path $paths -Destination $destination -Force -Recurse -Container
get-item -Path $paths | Remove-Item -Recurse -Force
"Backup successful"
}
Catch [System.Exception]
{
"Backup failed"
}
A [System.Exception] is the most generic error. If anything goes wrong with the Copy-Item operation, an error arises, and it moves to the Catch block.
The last thing to do is to add the registry update. To do this, I add it to the Finally block. To know if the backup was successful, I added $success = $true in the Try block and $success = $false in the Catch block. My Finally block writes the success or failure of the backup to the registry. If the backup is successful, it writes the time of the backup, otherwise, it writes that the backup failed. Here is the script:
$paths = "C:\fso1", "C:\fso2", "C:\fso3"
$destination = "c:\backup\$env:computername"
$ErrorActionPreference = "Stop"
If(!(Test-Path $destination))
{ md -Path ("{0}\{1}" -f $destination, $paths[0].Substring(3))| out-null }
Try {
Copy-Item -Path $paths -Destination $destination -Force -Recurse -Container
get-item -Path $paths | Remove-Item -Recurse -Force
$success = $true
"Backup successful"
}
Catch [System.Exception]
{
$success = $false
"Backup failed"
}
Finally {
Start-Transaction
If($success)
{New-Item -Name backup -Path HKCU:\Software\ScriptingGuys -Value `
"Backup $((Get-Date).Tostring())" -UseTransaction -Force}
else
{New-Item -Name backup -Path HKCU:\Software\ScriptingGuys -Value `
"Backup Failed" -UseTransaction -Force}
Complete-Transaction
}
WM, that is all there is to using transactions to update the registry after moving data from one folder to another. This is also the end of Provider Week. Join me tomorrow when Windows PowerShell MVP, Teresa Wilson, will talk about all of the cool guests she has lined up for the Scripting Guys booth at the Ignite Conference in Chicago.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy