Physical efforts in virtualization and mobility
Hot on the heels of my previous post, I was in a situation where I wanted a safety-net for backing up user profiles. “To the web! >>” I found this which got me on the right path:
I didn’t want to use PowerShell (well I did but we had XP to deal with) so was pretty limited to batch. In the end I took the contents of the script in this article and spiced it up a bit:
The backup script is below:
:: For XP Machines that will not have Robocopy available locally and also no %localappdata% variable if not exist %systemroot%\system32\robocopy.exe ( net use v: \\domain.local\NETLOGON ::Backup Outlook signature files v:\robocopy.exe %appdata%\Microsoft\Signatures %homeshare%\ProfileBackup\Signatures *.* /e ::Backup NK2 cache for Outlook 2003/2007 v:\robocopy.exe %appdata%\Microsoft\Outlook %homeshare%\ProfileBackup\NK2 *.nk2 ::Backup NK2 cache for Outlook 2010/2013 v:\robocopy.exe %userprofile%\Local Settings\Application Data\Microsoft\Outlook\RoamCache %homeshare%\ProfileBackup\Local *.dat ::Backup Internet Explorer Favorites v:\robocopy.exe %userprofile%\Favorites %homeshare%\ProfileBackup\Favorites *.* /e ::Backup all template files in AppData including normal.dot v:\robocopy.exe %appdata%\Microsoft\Templates %homeshare%\ProfileBackup\Templates\*.dot ::Backup customised Quick Access Toolbars in Office v:\robocopy.exe %userprofile%\Local Settings\Application Data\Microsoft\Office %homeshare%\ProfileBackup\Local *.Officeui ::Backup Office auto correct files v:\robocopy.exe %appdata%\Microsoft\Office %homeshare%\ProfileBackup\Roaming *.acl ::Backup custom dictionaries for Office v:\robocopy.exe %appdata%\Microsoft\Uproof %homeshare%\ProfileBackup\Roaming *.dic net use v: /delete ) :: carrying on it Vista or Win7 backup the profile data to the users home drive if exist %systemroot%\system32\robocopy.exe ( ::Backup Outlook signature files Robocopy %appdata%\Microsoft\Signatures %homeshare%\ProfileBackup\Signatures *.* /e ::Backup NK2 cache for Outlook 2003/2007 Robocopy %appdata%\Microsoft\Outlook %homeshare%\ProfileBackup\NK2 *.nk2 ::Backup NK2 cache for Outlook 2010/2013 Robocopy %localappdata%\Microsoft\Outlook\RoamCache %homeshare%\ProfileBackup\Local *.dat ::Backup Internet Explorer favorites Robocopy %userprofile%\Favorites %homeshare%\ProfileBackup\Favorites *.* /e ::Backup all template files in AppData including normal.dot Robocopy %appdata%\Microsoft\Templates %homeshare%\ProfileBackup\Templates\ *.dot ::Backup customised Quick Access Toolbars in Office Robocopy %localappdata%\Microsoft\Office %homeshare%\ProfileBackup\Local *.Officeui ::Backup Office autocorrect files Robocopy %appdata%\Microsoft\Office %homeshare%\ProfileBackup\Roaming *.acl ::Backup custom dictionaries for Office Robocopy %appdata%\Microsoft\Uproof %homeshare%\ProfileBackup\Roaming *.dic ) :: copy the restore script to the users home drive so they can run a restore if required copy \\domain.local\NETLOGON\RestoreProf.bat %homeshare%\ProfileBackup\ /y :: output the logging on users to text file for reference to see what desktops they are logging on echo %username%,%computername%,%date%,%time% \\domain.local\dfs\profiles\LiveLogonInfo.txt
Next create a RestoreProf.bat like this
@Echo off :: Set log files variable, each line appends to the respective log file SET LOGW7VISTA=%homeshare%\ProfileBackup\ProfileRestoreW7Vista.log SET LOGXP=%homeshare%\ProfileBackup\ProfileRestoreXP.log :: For XP Machines that will not have Robocopy available locally and also no %localappdata% variable if not exist %systemroot%\system32\robocopy.exe ( net use v: \\domain.local\NETLOGON ::Restore Outlook signature files v:\robocopy.exe %homeshare%\ProfileBackup\signatures %appdata%\Microsoft\Signatures *.* /e /NC /NS /NP %LOGXP% ::Restore NK2 cache for Outlook 2003/2007 v:\robocopy.exe %homeshare%\ProfileBackup\NK2 %appdata%\Microsoft\Outlook *.* /e /NC /NS /NP %LOGXP% ::Restore NK2 cache for Outlook 2010/2013 v:\robocopy.exe %homeshare%\ProfileBackup\Local %userprofile%\Local Settings\Application Data\Microsoft\Outlook\RoamCache *.* ::Restore Internet Explorer Favorites v:\robocopy.exe %homeshare%\ProfileBackup\Favorites %userprofile%\Favorites *.* /e ::Restore all Template files in AppData including normal.dot v:\robocopy.exe %homeshare%\ProfileBackup\Templates %appdata%\Microsoft\Templates *.* /e /NC /NS /NP %LOGXP% ::Restore customised Quick Access Toolbars in Office v:\robocopy.exe %homeshare%\ProfileBackup\Local %userprofile%\Local Settings\Application Data\Microsoft\Office *.Officeui /e /NC /NS /NP %LOGXP% ::Restore Office autocorrect files v:\robocopy.exe %homeshare%\ProfileBackup\Roaming %appdata%\Microsoft\Office *.acl /e /NC /NS /NP %LOGXP% ::Restore custom dictionaries for Office v:\robocopy.exe %homeshare%\ProfileBackup\Roaming %appdata%\Microsoft\Uproof *.dic /e /NC /NS /NP %LOGXP% net use v: /delete ) :: carrying on if Vista or Win7 restore the profile data to the users local profile for upload at logoff if exist %systemroot%\system32\robocopy.exe ( ::Restore Outlook signature files Robocopy %homeshare%\ProfileBackup\Signatures %appdata%\Microsoft\Signatures *.* /e /NC /NS /NP %LOGW7VISTA% ::Restore NK2 cache for Outlook 2003/2007 Robocopy %homeshare%\ProfileBackup\NK2 %appdata%\Microsoft\Outlook *.* /e /NC /NS /NP %LOGW7VISTA% ::Restore NK2 cache for Outlook 2010/2013 Robocopy %homeshare%\ProfileBackup\Local %localappdata%\Microsoft\Outlook\RoamCache *.* /e /NC /NS /NP %LOGW7VISTA% ::Restore Internet Explorer Favorites Robocopy %homeshare%\ProfileBackup\Favorites %userprofile%\Favorites *.* /e ::Restore all Template files in AppData including normal.dot Robocopy %homeshare%\ProfileBackup\Templates %appdata%\Microsoft\Templates *.* /e /NC /NS /NP %LOGW7VISTA% ::Restore customised Quick Access Toolbars in Office Robocopy %homeshare%\ProfileBackup\Local %localappdata%\Microsoft\Office *.Officeui /e /NC /NS /NP %LOGW7VISTA% ::Restore Office autocorrect files Robocopy %homeshare%\ProfileBackup\Roaming %appdata%\Microsoft\Office *.acl /e /NC /NS /NP %LOGW7VISTA% ::Restore custom dictionaries for Office Robocopy %homeshare%\ProfileBackup\Roaming %appdata%\Microsoft\Uproof *.dic /e /NC /NS /NP %LOGW7VISTA% ) @Echo profile settings restored Pause
This will be copied to the users home drives from the logon script (so long as you put it in the right place) and will create a folder structure like this
So the idea here is that if there is an issue, the user can manually run the batch file, which may be a problem if you restrict the running of these file types. I see this as a useful tool though to be used as a matter of course. If everyone’s profiles are backup in such a way and you have a service desk with a penchant for flushing user profiles this will make the process easier because if the login script runs at every logon, the folder will always be up-to-date. After a profile flush the service desk can either insruct the user to run the file or they can run it as admin to drop all of the files in the correct place.
I have only found one slight issue with the restore method so far in that the signature file is somewhat orphaned. It’s there in Outlook, it just needs assigning as per screenshot below:
I was recently engaged in a project for a large organisation using physical desktops which were a mixture of Windows XP, Vista and 7 (Oddly, Vista took the lions share by a considerable margin). Roaming profiles were in use and users did indeed roam between workstations. Sadly for them, this meant that they also roamed between the three generations of operating system with the same profile – As you can imagine, profile corruption was a common occurrence; as was calls into the service desk where and profile resets and users having to setup their environment again. A Windows 7 rollout was in progress but was slow going, partially due to the myriad of different applications in use. It would be complete but probably not for eighteen months plus.
Option 1: Bin roaming profiles, this would make life considerably easier for support teams and is a viable solution as it would also in some respects make life easier for the end users. Yes users would have a more stable environment but would have a lack of flexibility. In a scenario whereby users only roam to a few machines and it’s the same ones each time, they only need to go through the pain of setting up their profile once per first time logon of each workstation. If users constantly move around an organisation, to different sites within and a hot desking strategy is in use, the limitations grow further. I have come across a number of organisations that have taken this easy way out and just decided to switch off roaming and move to local profiles.
Option 2: Implement a third party profile management solution such as AppSense Desktop now (Environment Manager/Personalization server). This would enable full cross platform support hiving off personalization into a central SQL database resulting in a consistent look and feel and slick logon times. This preferred and the Rolls Royce Solution, the trouble with is it comes with a Rolls Royce price tag for the number of users and endpoints concerned (a few hundred k).
Option 3: A more dynamic approach to standard Windows roaming profiles, this is where each of the three OS types in use is tied to a profile relevant to it. In the scenario where an end user logs onto XP, Vista and 7 over a given period this will result in them having three separate profiles and yes they would need to set it up three times for each initial login (…but maybe not, more on that later) but they will be able to roam freely with a significantly reduced risk of profile corruption.
Dynamic OS Profiles
Now as you may have guessed we went with Option 3 (although option 1 was popular within IT). Before finding out how to facilitate this solution, I did think about how profiles could be tied to an OS but it wasn’t my own so I’m not making any claims to this idea, it is explained in this blog which I found:
I’m going to go through the implementation of this in a real world scenario though as it sounds great in theory. Basically as described in the above blog it relies upon an environment variable to be on each desktop in the organisation, and remember it really does need to be all of them as potentially any all users within AD will end up with a generic user profile path. The variable is referenced in the profile path so the target workstation must be able to understand what that variable is, otherwise it will not direct users to the correct directory on the file server. You will end up with a directory called %variablename% containing the profiles of users that logged onto machines that don’t have the variable set. As a side note we decided to take the added opportunity to move the profiles to a new file server.
I have described one of the pitfalls above, so it is key that we get that variable set, what we used was:
%OSVer% = WinXP
%OSVer% = WinVista
%OSVer% = Win7
So for this, as described we wanted to use on policy harnessing Group Policy Preferences (GPP) and item level targeting to point to the OS specific for that particular variable. But there was a stumbling block, only the Windows 7 workstations could process the policy because both XP and Vista require the Group Policy Client Side Extensions pack (KB943729). Now there’s a couple of points I would like to make here:
Oh well rant over, so Windows 7 desktops would be fine in this case but they only made up about 40% of the estate, we have another 8,000 or so machines to deal with. Well, it’s quite simple really as WSUS was up and running so we pushed it out. This leads to another issue though in that WSUS hit rate is by no means 100% so we needed to cover ourselves. Enter one of my own ideas (something new!)
ADM Template to set environment variable
So to handle legacy clients that do not have the CSE’s installed I created an ADM template (old school) so the variable by can be added via classic policy instead of preferences. It uses the registry location for where variables are stored and enters it there with a free text field.
<pre> CATEGORY "Operating System Identifier" KEYNAME "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" POLICY "OSVer" PART "OSVer" EDITTEXT DEFAULT "WinXP" VALUENAME "OSVer" END PART END POLICY END CATEGORY CLASS MACHINE
It looks like this:
Of course this is only part of the solution, clearly we need three independent policies; one for each OS but we need to make sure the correct policy applies to the relevant OS. This is where WMI filters come in.
The Windows 7 policy may as well use the GPP method, there is no point in using the classic ADM file method for that. At some point once all of the legacy clients are replaced this will be the only policy in use and it can be used to cover profile variations for Windows 7, 8, 8.1 and 10. So that leaves two WMI queries to create which are below:
Under the root\CIMv2 namespace
Description: Checks if the OS is Windows XP
Query: select * from Win32_OperatingSystem where Version like “5.1%” and ProductType = “1”
Description: Checks if the OS is Windows Vista
Query: select * from Win32_OperatingSystem WHERE Version like “6.0%” AND ProductType=”1″
Then in the Scope section for the policy in the previous screenshot assign the filter:
Pushing the Go button
Now this is complete we can change all users to point to a single common profile path in their AD account:
Pro tip: Do yourself a favour and use a dfs namespace for this, it will make your life easier in the long-run
So say we have thousands of users that we want to change the profile path on, what’s the best approach for achieving this? Run a script to update the path perhaps? Yes this would work, if you are going for a big bang approach but I prefer staged migrations. Start with say 10, review, then based upon results, increase to 20 then 50, peaking at no more than 100 per day. What this results in is a background task that takes a few minutes out of every day.
The method I prefer over scripting in this instance as to use the multiple selection option of Active Directory Objects. You know, hold down Ctrl, scroll down and select type of thing, then go to properties of the multiple objects. Select 50 per day (once past pilot) and what you will end up with is something like this, a reduced set of properties that can be set for all selected objects:
Tick the Profile path: box and input the path detailed above.
We have a solution; it’s all very well having an answer to a problem but pushing the go button is another thing entirely. How do we want to handle this, use it as an opportunity to refresh everyones profile? Copy the existing ones from and old file server to the new? Well initially I thought the former but then I thought do I really want to deal with the support issues that 10,000 plus users may have setting up their Outlook profiles, complaining they have lost their NK2 cache and signatures etc.? No thanks.
How about copying the profiles as is from one location to another? Not ideal considering they are all currently in one flat and mixed up lump as they need to be in the three separate folders per operating system. It may be possible to move the XP ones out but although we know Vista and 7 profiles are incompatible, I couldn’t any discernible differences from a file system perspective.
What we are left with is only one real option and that is to rely upon the local cached profile. What this means is that if we make the profile path change detailed above, when the user logs on, it will log on no differently to normal. Then at logon time, it will write back to the new location. Of course we are likely to be making the changes when the user is still logged on. This is fine as the change will not take effect until the next subsequent logon.
As a safety net I wrote a backup / restore batch script to protect against any issues that may occur as a result of using these cached profiles. This blog is quite long enough so I’ll cover that in a separate post.
As you can see, this method is a bit of a phaff and I haven’t even explained it all here as it is explained in detail in the linked blog. If you can, you should try and go for Option 2, it is superior to Option 3.
It does work though, and is better than the alternative of sharing incompatible profiles.