在 Jscript 中获取给定用户的特殊文件夹路径

发布于 2024-10-30 08:20:42 字数 58 浏览 3 评论 0原文

如何获取当前用户以外的特定用户的 shell 文件夹(例如“本地设置”或“本地应用程序数据”)的路径?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

月隐月明月朦胧 2024-11-06 08:20:42

虽然有一些方法可以在 Windows 脚本宿主中获取特殊文件夹路径 - WshShell。 SpecialFoldersShell.NameSpace — 它们仅返回当前用户的路径。获取其他用户的特殊文件夹路径有点棘手。

执行此操作的正确方法是使用 Windows API SHGetKnownFolderPath 函数(或 SHGetFolderPath(适用于 Vista 之前的 Windows 版本)。但问题是,Windows Script Host 不支持调用 WinAPI 函数,因此要在脚本中使用这些函数,您必须通过自定义编写的 COM 组件公开它们。

另一种可能但未记录的解决方案是从该用户的注册表配置单元读取特殊文件夹路径,特别是 HKEY_USERS\\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell 文件夹 键。

User Shell Folders 键中的路径通常使用 %USERPROFILE% 环境变量指定;因此,要获得完全限定的路径,您必须将此变量替换为 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\ 中的 ProfileImagePath 值代码>键。

此外,HKEY_USERS\ 键仅在相应用户当前登录时才可用。对于一般解决方案,您必须将用户的配置单元 (\ntuser.dat) 加载到临时注册表项(例如 HKEY_USERS\Temp)中,并改为从此键读取值。

下面是示例 JScript 代码,演示了如何完成您的任务。在 Windows 7 和 Vista 上,您可能需要以管理员身份运行脚本,具体取决于您的 UAC 设置。

注意:不鼓励使用这种方法,正如 Raymond Chen 在他的文章 Shell 文件夹键漫长而悲伤的故事。无法保证它会在未来版本的 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);
}

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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文