1

How to get the path of a shell folder like "Local Settings" or "Local Appdata" for a specific user other than the current user?

harini
  • 11
  • 1
  • 3

1 Answers1

1

While there are methods for getting special folder paths in Windows Script Host — WshShell.SpecialFolders and Shell.NameSpace — they return paths for the current user only. Getting other users' special folder paths is a bit tricky.

The proper way to do this is to use the Windows API SHGetKnownFolderPath function (or SHGetFolderPath on Windows versions prior to Vista). But the problem is, Windows Script Host doesn't support calling WinAPI functions, so to make use of these functions in your script you'll have to expose them via a custom-written COM component.

Another possible but undocumented solution is to read the special folder paths from that user's registry hive, specifically, the HKEY_USERS\<user_SID>\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders key.

The paths in the User Shell Folders key are typically specified using the %USERPROFILE% environment variable; so to get fully-qualified paths you'll have to substitute this variable with the ProfileImagePath value from the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\<user_SID> key.

Also, the HKEY_USERS\<user_SID> key is only available when the corresponding user is currently logged on. For a general solution, you would have to load the user's hive (<UserProfile>\ntuser.dat) into a temporary registry key (say, HKEY_USERS\Temp) and read values from this key instead.

Below is sample JScript code that demonstrates how your task can be accomplished. On Windows 7 and Vista, you may need to run the script as Administrator depending on your UAC settings.

NOTE: This method is discouraged, as Raymond Chen explains in his article The long and sad story of the Shell Folders key. There's no guarantee it will keep working in future versions of Windows.

var strUser = "foo";
var strDomain = "bar";
// If the account is local, domain name = computer name:
// var strDomain = getComputerName();

var strSID = getSID(strUser, strDomain);
var strProfilePath = getProfilePath(strSID);

// Load the user's registry hive into the HKEY_USERS\Temp key
var strTempKey = "Temp";
loadHKUHive(strTempKey, strProfilePath + "\\ntuser.dat");

// Get unexpanded path, e.g. %USERPROFILE%\AppData\Roaming
//var strAppData = getAppData(strSID);
var strAppData = getAppData(strTempKey);
WScript.Echo(strAppData);

// Expand the previous value to a fully-qualified path, e.g. C:\Users\foo\AppData\Roaming
strAppData = strAppData.replace(/%USERPROFILE%/i, strProfilePath);
WScript.Echo(strAppData);

// Unload the user's registry hive
unloadHKUHive(strTempKey);


function getComputerName() {
   var oShell = new ActiveXObject("WScript.Shell");
   return oShell.ExpandEnvironmentStrings("%COMPUTERNAME%");
}

function getSID(strUser, strDomain) {
    var oAccount = GetObject("winmgmts:root/cimv2:Win32_UserAccount.Name='" + strUser + "',Domain='" + strDomain + "'");
    return oAccount.SID;
}

function getProfilePath(strSID) {
    var oShell = new ActiveXObject("WScript.Shell");
    var strValue = oShell.RegRead("HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\" + strSID + "\\ProfileImagePath");
    return strValue;
}

function getAppData(strSID) {
    var oShell = new ActiveXObject("WScript.Shell");
    var strValue = oShell.RegRead("HKEY_USERS\\" + strSID + "\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\\AppData");
    return strValue;
}

function loadHKUHive(strKeyName, strHiveFile) {
    var oShell = new ActiveXObject("WScript.Shell");
    oShell.Run("reg load HKU\\" + strKeyName + " " + strHiveFile, 0, true);
}

function unloadHKUHive(strKeyName) {
    var oShell = new ActiveXObject("WScript.Shell");
    oShell.Run("reg unload HKU\\" + strKeyName, 0, true);
}
Helen
  • 87,344
  • 17
  • 243
  • 314
  • @Helen - this answer is irrelevant and somewhat misleading, OP asks about client-side in-browser scripting, so advising him on using a server-side language is wrong and might cause confusion. – Andrey Apr 07 '11 at 13:03
  • 1
    @Andrey: My answer is actually relevant and correct. The OP answered in a comment to your post that he/she means NOT JavaScript and browser scripting, but JScript - Microsoft's ECMAScript flavor for Windows shell scripting (like PowerShell and VBScript). – Helen Apr 07 '11 at 13:41
  • @Helen - if they are talking abotu JScript shell scripting, it's still possible to use to access local file system - you just use ActiveXObject (I think class is FileSystemObject or smth like that) for that. – Andrey Apr 07 '11 at 15:26
  • 1
    Hmm... it seems to me that the question was "how to get the path", and not "how to access files on disk". So, Helen's answer is just what is needed. So, Andrey, your answer actually answers a different question :) – Alex May 16 '11 at 12:56
  • 1
    Thanks Helen.. But for other user, you need to load the registry hive for that user under HKEY_USERS. Without that the getAppData(strSID) may not work unless the user's hive u loaded elsewhere already. anyway, this is a great help. – harini May 17 '11 at 09:42
  • @harini: Yes, you're right. I've updated the answer and the script. – Helen May 19 '11 at 11:11
  • 1
    +1, a very detailed answer that deserves more up votes. @Andrey: using `FileSystemObject` would be very complicated and potentially unreliable. – Andy E Aug 09 '11 at 21:13