Получение специального пути к папке для данного пользователя в Jscript

Как получить путь к папке оболочки, такой как «Локальные настройки» или «Локальные данные приложения», для определенного пользователя, отличного от текущего пользователя?


person harini    schedule 06.04.2011    source источник
comment
Вы имеете в виду JavaScript, используемый на веб-страницах, или JScript, используемый в Windows Script Host?   -  person Helen    schedule 06.04.2011


Ответы (1)


Хотя существуют методы получения специальных путей к папкам на узле сценариев Windows WshShell.SpecialFolders и Shell.NameSpace они возвращают пути только для текущего пользователя. Получить специальные пути к папкам других пользователей немного сложно.

Правильный способ сделать это — использовать Windows API SHGetKnownFolderPath (или SHGetFolderPath в версиях Windows до Vista ). Но проблема в том, что Windows Script Host не поддерживает вызов функций WinAPI, поэтому, чтобы использовать эти функции в своем сценарии, вам придется предоставлять их через специально написанный COM-компонент.

Другим возможным, но недокументированным решением является чтение путей к специальным папкам из куста реестра этого пользователя, в частности, ключа HKEY_USERS\<user_SID>\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders.

Пути в ключе User Shell Folders обычно указываются с помощью переменной среды %USERPROFILE%; поэтому, чтобы получить полные пути, вам придется заменить эту переменную значением ProfileImagePath из ключа HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\<user_SID>.

Кроме того, клавиша HKEY_USERS\<user_SID> доступна только тогда, когда соответствующий пользователь в данный момент находится в системе. В качестве общего решения вам придется загрузить куст пользователя (‹UserProfile›\ntuser.dat) во временный раздел реестра (скажем, HKEY_USERS\Temp) и вместо этого прочитать значения из этого раздела.

Ниже приведен пример кода JScript, который демонстрирует, как можно выполнить вашу задачу. В Windows 7 и Vista вам может потребоваться запустить скрипт от имени администратора в зависимости от ваших настроек UAC.

ПРИМЕЧАНИЕ. Этот метод не рекомендуется, как объясняет Рэймонд Чен в своей статье Долгая и печальная история ключа Shell Folders. Нет никакой гарантии, что он продолжит работать в будущих версиях 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);
}
person Helen    schedule 06.04.2011
comment
@Helen - этот ответ не имеет отношения к делу и несколько вводит в заблуждение, OP спрашивает о сценариях на стороне клиента в браузере, поэтому советовать ему использовать язык на стороне сервера неправильно и может вызвать путаницу. - person Andrey; 07.04.2011
comment
@Andrey: Мой ответ действительно актуален и верен. ОП ответил в комментарии к вашему сообщению, что он / она имеет в виду НЕ JavaScript и сценарии браузера, а JScript - вариант Microsoft ECMAScript для сценариев оболочки Windows (например, PowerShell и VBScript). - person Helen; 07.04.2011
comment
@Helen - если они говорят о сценариях оболочки JScript, их все еще можно использовать для доступа к локальной файловой системе - для этого вы просто используете ActiveXObject (я думаю, что класс - это FileSystemObject или что-то в этом роде). - person Andrey; 07.04.2011
comment
Хм... мне кажется, что вопрос был в том, как получить путь, а не в том, как получить доступ к файлам на диске. Итак, ответ Хелен - это то, что нужно. Итак, Андрей, ваш ответ на самом деле отвечает на другой вопрос :) - person Alex; 16.05.2011
comment
Спасибо, Хелен. Но для другого пользователя вам нужно загрузить куст реестра для этого пользователя в разделе HKEY_USERS. Без этого getAppData(strSID) может не работать, если куст пользователя уже не загружен в другом месте. в любом случае, это большая помощь. - person harini; 17.05.2011
comment
@harini: Да, ты прав. Я обновил ответ и сценарий. - person Helen; 19.05.2011
comment
+1, очень подробный ответ, который заслуживает большего количества голосов. @Andrey: использование FileSystemObject было бы очень сложным и потенциально ненадежным. - person Andy E; 10.08.2011