如何为当前用户以外的特定用户获取 shell 文件夹的路径,如“本地设置”或“本地 Appdata”?
1 回答
虽然有一些方法可以在 Windows Script Host 中获取特殊文件夹路径,WshShell.SpecialFolders
并且Shell.NameSpace
它们仅返回当前用户的路径。获取其他用户的特殊文件夹路径有点棘手。
执行此操作的正确方法是使用 Windows APISHGetKnownFolderPath
函数(或SHGetFolderPath
在 Vista 之前的 Windows 版本上)。但问题是,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 设置。
注意:不鼓励这种方法,正如 Raymond Chen 在他的文章The long and sad story of the Shell Folders key 中解释的那样。不能保证它会在未来的 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);
}