如何使用Node获取已知的Windows文件夹路径

时间:2018-05-17 12:10:02

标签: node.js windows winapi

我需要访问在Windows上运行的Node应用程序中的每台计算机配置数据。我找到了关于如何找到位置的文档:

Where Should I Store my Data and Configuration Files if I Target Multiple OS Versions?

所以,就我而言,我想获得CSIDL_COMMON_APPDATA(或FOLDERID_ProgramData)的路径。但是,这些示例都在C中,我宁愿不必为此编写C扩展名。

是否还有其他方法可以从Node访问这些路径,还是应该对它们进行硬编码?

1 个答案:

答案 0 :(得分:1)

经过一些研究后,我发现可以调用相关的Windows API proc。 (SHGetKnownFolderPath)获取这些文件夹位置,请参阅文档:https://msdn.microsoft.com/en-us/library/windows/desktop/bb762188(v=vs.85).aspx

我们使用FFI npm模块调用APi:https://www.npmjs.com/package/ffi

可以在此处找到任何已知文件夹的GUID: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx

这是一个查找几个常用文件夹位置的脚本, 一些代码有点hacky,但很容易清理。

const ffi = require('ffi');
const ref = require('ref');

const shell32 = new ffi.Library('Shell32', {
    SHGetKnownFolderPath: ['int', [ ref.refType('void'), 'int', ref.refType('void'), ref.refType(ref.refType("char"))]]
});

function parseGUID(guidStr) {
    var fields = guidStr.split('-');
    var a1 = [];
    for(var i = 0; i < fields.length;  i++) {
        var a2 = [...Buffer.from(fields[i], 'hex')];
        if (i < 3) a2 = a2.reverse();
        a1 = a1.concat(a2);
    }
    return new Buffer(a1);
}

function getWindowsKnownFolderPath(pathGUID) {
    let guidPtr = parseGUID(pathGUID);
    guidPtr.type = ref.types.void;

    let pathPtr = ref.alloc(ref.refType(ref.refType("void")));

    let status = shell32.SHGetKnownFolderPath(guidPtr, 0, ref.NULL, pathPtr);
    if (status !== 0) {
        return "Error occurred getting path: " + status;
    }

    let pathStr = ref.readPointer(pathPtr, 0, 200);
    return pathStr.toString('ucs2').substring(0, (pathStr.indexOf('\0\0') + 1)/2);
}

// See this link for a complete list: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx 
const WindowsKnownFolders = {
   ProgramData: "62AB5D82-FDC1-4DC3-A9DD-070D1D495D97",
   Windows: "F38BF404-1D43-42F2-9305-67DE0B28FC23",
   ProgramFiles: "905E63B6-C1BF-494E-B29C-65B732D3D21A",
   Documents: "FDD39AD0-238F-46AF-ADB4-6C85480369C7"
}

// Enumerate common folders.
for(let [k,v] of Object.entries(WindowsKnownFolders)) {
   console.log(`${k}: `, getWindowsKnownFolderPath(v));   
}