If you used to query Active Directory properties like TerminalServicesProfilePath, TerminalServicesHomeDrive and TerminalServicesHomeDirectory on Windows Server 2003, you may have realized already that those properties are not available on Windows Server 2008 and later. If you investigate a bit, you may find some properties which are supposed to be their substitutes: msTSProfilePath, msTSHomeDrive and msTSHomeDirectory. But if you try to query them with a code like the following, it won’t work. You will get empty strings for those properties.
Dim myUser = New DirectoryEntry(myPath)
' This works fine on Win2003, but fails on Win2008, as expected
Catch ex As Exception
' This fails on Win2003 as expected, but returns an empty string on Win2008
Catch ex As Exception
It turns out that those properties are implemented and meant to be used to store that information, but we neither use them nor do we store the info in those properties (yet).
That information is written into the userParameters datablob which is readable through Tsuserex.dll exports. The recommended approach would be to build an app that will cover future scenarios: check for the new properties as shown above, and if empty, use Tsuserex.dll exports.
This is the interface we need to use:
And some info on the Tsuserex.dll library that implements it:
These are the properties which correspond to msTSProfilePath, msTSHomeDrive or msTSHomeDirectory:
Now, I couldn’t find any official sample from MS, only this C++ sample copied from MSDN (note I couldn’t find the original web page where they copied this from, so the info is likely to be a bit old):
And here is the translation of that sample to C#:
Converting this sample to VB.NET should be quite straightforward.
Now, I tried to create a VB.NET sample on my Windows 7, but I couldn’t find the Tsuserex.dll library. But I found that that library is in the server versions of Windows.
So I copied the dll from my Windows Server 2008 R2 to my Windows 7, I registered with regsvr32, and added it as a reference to my sample project.
Then I created this sample code:
Dim rootLDAPpath As String = "LDAP://OU=...,DC=com"
Dim root As DirectoryEntry = New DirectoryEntry(rootLDAPpath)
Dim searcher As New DirectorySearcher(root)
Dim adUser As SearchResult
searcher.Filter() = "(&(objectCategory=user)(samAccountName=alejacma))"
adUser = searcher.FindOne
Dim myUser = New DirectoryEntry(adUser.Path)
' Get the properties
Dim tsUser = CType(myUser.NativeObject, IADsTSUserEx)
' Set the properties
tsUser.TerminalServicesHomeDirectory = ...
Taking this code as a base we werer able to both read and modify those properties.
I hope this helps.
Alex (Alejandro Campos Magencio)