Parsing GPOs for Drive Mappings
One thing that we always have to do (and people often overlook) when planning a VDI project is to understand the user environment and how to gracefully recreate their current desktop environment on the virtual desktop. This is a big challenge, as you can tell from the fact that there are so many tools available to solve it.
In my experience the best solution is usually a combination of purpose built tools, of Group Policy Objects, and of the occasional login script. Before you can even start figuring out which combination of tools and techniques might be most appropriate, you need to understand what currently exists in the environment... and you need a fairly accurate picture of that. If the environment is already sophisticated with heavy use of GPOs for drive mappings, printer mappings, and critical registry settings, transitioning into VDI will be far easier than if new desktops are configured by an IT guy walking over and making all of those things by hand. Of course, most organizations are going to be somewhere between the two extremes of "fully managed user environment" and "manually created user environment" and, it seems like organizations don't always know where they fall on that spectrum.
I recently worked with a customer on exactly this topic, so, today lets talk about Drive Mappings and how I figured out how they're actually being handled. Excepting the situation where one of the aforementioned tools is already in use, I'm aware of three main sources of user drive mappings. Each mapping is either defined locally on the workstation by the user (or by a helpful IT person...), is defined in a GPO, or is defined by some kind of logon script. Note that I said "each mapping" there; that was very intentional, as many environments will have some amount of all three of those categories. So, in order to plan the VDI implementation, you're going to have to look at and understand each of those three sources of drive mappings to make sure that they can all be transitioned smoothly to the new desktops. How do you do it?
Well, script-based drive mappings are both the easiest and the hardest. You're just going to have to look at their logon scripts and check for any drive mappings. Given the variety of logon scripts and possible techniques for creating those mappings, I don't even try to automate that. Fortunately, those logon scripts are usually not too complicated and so it doesn't take long to go through them and identify any drive mappings.
So, what about manually created drive mappings? Well, that's a tough nut to crack. I tried running a WMI query against the win32_mappedLogicalDisk class on each desktop, but it silently failed to return data in too many situations and I couldn't figure out why that was happening. So, I tried remotely querying the registry, first the HKCU and then just HKU (for each user), looking under the Network key for any defined network drives. That's definitely the right place to look, but I ran into too many problems trying to access desktop registries remotely (it's almost like that would be a huge security risk and so the system is built to prevent it or something). So, I ended up cheating. This customer already had a logon script that recorded a bunch of information about the user and their desktop onto a file share, which their help desk used when troubleshooting. Anyone who's tried to walk a normal user through an ipconfig /all knows that pain and certainly understands the value of making that data readily available to the help desk. Well, one of the things that they recorded in those files were their drive mappings, so I ended up ingesting that data and calling it good.
That leaves GPO based drive mappings. Well, due to the nature of GPOs, those are a little more codified than scripted mappings and so are easier to parse through automatically. And that's a good thing, as organizations are likely to have a lot of GPOs and technically, any of them could have drive mapping definitions within them. Rather than expanding every single one of those and looking through them, I put together a quick PowerShell script to do it for me. I based this script on this technet article, which was super handy, except that their examples all failed to cast their variable as XML. So, when getting the GPOReport, the line should read:
[XML]$xml = get-gporeport -name <GPO Name> -ReportType xml
The Get-GPODriveMappings.ps1 script that I wrote is pretty straightforward. It has a single parameter: -GPOName. Just give it the name of the GPO(s) that it should analyze, then it'll parse through each GPO looking under User Configuration\Preferences\Windows Settings\Drive Mappings for any mapped drives (that's how this customer has mapped their drives, so that bit might need to change if you map your drives differently). In order to search through a whole environment (how I used it here), just call it like this:
$results = get-GPODriveMappings.ps1 -GPOName (get-gpo -all).DisplayName
That'll parse through every GPO in the domain and will store its findings in the $results variable, which can then be exported as a CSV or whatever you need to do with it.
As always, this script is posted as is, for educational purposes only, and while it worked for me in this environment, that's no guarantee that it'll work for you in yours. Test thoroughly and ensure that you fully understand any script that you find on the internet before running it on a live system.
It looks like my new formatting must have broken my integration with Gist It, so here's a direct link to my Parse GPO Drive Mappings script.
In my experience the best solution is usually a combination of purpose built tools, of Group Policy Objects, and of the occasional login script. Before you can even start figuring out which combination of tools and techniques might be most appropriate, you need to understand what currently exists in the environment... and you need a fairly accurate picture of that. If the environment is already sophisticated with heavy use of GPOs for drive mappings, printer mappings, and critical registry settings, transitioning into VDI will be far easier than if new desktops are configured by an IT guy walking over and making all of those things by hand. Of course, most organizations are going to be somewhere between the two extremes of "fully managed user environment" and "manually created user environment" and, it seems like organizations don't always know where they fall on that spectrum.
I recently worked with a customer on exactly this topic, so, today lets talk about Drive Mappings and how I figured out how they're actually being handled. Excepting the situation where one of the aforementioned tools is already in use, I'm aware of three main sources of user drive mappings. Each mapping is either defined locally on the workstation by the user (or by a helpful IT person...), is defined in a GPO, or is defined by some kind of logon script. Note that I said "each mapping" there; that was very intentional, as many environments will have some amount of all three of those categories. So, in order to plan the VDI implementation, you're going to have to look at and understand each of those three sources of drive mappings to make sure that they can all be transitioned smoothly to the new desktops. How do you do it?
Well, script-based drive mappings are both the easiest and the hardest. You're just going to have to look at their logon scripts and check for any drive mappings. Given the variety of logon scripts and possible techniques for creating those mappings, I don't even try to automate that. Fortunately, those logon scripts are usually not too complicated and so it doesn't take long to go through them and identify any drive mappings.
So, what about manually created drive mappings? Well, that's a tough nut to crack. I tried running a WMI query against the win32_mappedLogicalDisk class on each desktop, but it silently failed to return data in too many situations and I couldn't figure out why that was happening. So, I tried remotely querying the registry, first the HKCU and then just HKU (for each user), looking under the Network key for any defined network drives. That's definitely the right place to look, but I ran into too many problems trying to access desktop registries remotely (it's almost like that would be a huge security risk and so the system is built to prevent it or something). So, I ended up cheating. This customer already had a logon script that recorded a bunch of information about the user and their desktop onto a file share, which their help desk used when troubleshooting. Anyone who's tried to walk a normal user through an ipconfig /all knows that pain and certainly understands the value of making that data readily available to the help desk. Well, one of the things that they recorded in those files were their drive mappings, so I ended up ingesting that data and calling it good.
That leaves GPO based drive mappings. Well, due to the nature of GPOs, those are a little more codified than scripted mappings and so are easier to parse through automatically. And that's a good thing, as organizations are likely to have a lot of GPOs and technically, any of them could have drive mapping definitions within them. Rather than expanding every single one of those and looking through them, I put together a quick PowerShell script to do it for me. I based this script on this technet article, which was super handy, except that their examples all failed to cast their variable as XML. So, when getting the GPOReport, the line should read:
[XML]$xml = get-gporeport -name <GPO Name> -ReportType xml
The Get-GPODriveMappings.ps1 script that I wrote is pretty straightforward. It has a single parameter: -GPOName. Just give it the name of the GPO(s) that it should analyze, then it'll parse through each GPO looking under User Configuration\Preferences\Windows Settings\Drive Mappings for any mapped drives (that's how this customer has mapped their drives, so that bit might need to change if you map your drives differently). In order to search through a whole environment (how I used it here), just call it like this:
$results = get-GPODriveMappings.ps1 -GPOName (get-gpo -all).DisplayName
That'll parse through every GPO in the domain and will store its findings in the $results variable, which can then be exported as a CSV or whatever you need to do with it.
As always, this script is posted as is, for educational purposes only, and while it worked for me in this environment, that's no guarantee that it'll work for you in yours. Test thoroughly and ensure that you fully understand any script that you find on the internet before running it on a live system.
It looks like my new formatting must have broken my integration with Gist It, so here's a direct link to my Parse GPO Drive Mappings script.
Comments
Post a Comment
Sorry guys, I've been getting a lot of spam recently, so I've had to turn on comment moderation. I'll do my best to moderate them swiftly after they're submitted,