node.js - Sådan får du kendskab til Windows-mappebane med Node

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har brug for adgang til konfigurationsdata pr. Maskin i min Node-applikation, der kører på Windows. Jeg har fundet denne dokumentation for, hvordan du finder placeringen:


Hvor skal jeg gemme mine data- og konfigurationsfiler, hvis jeg målretter flere OS versioner? [4]


Så i mit tilfælde vil jeg gerne få stien til CSIDL\_COMMON\_APPDATA (eller FOLDERID\_ProgramData). Eksemplerne er dog alle i C, og jeg foretrækker ikke at skrive en C-udvidelse til dette.


Er der nogen anden måde at få adgang til disse stier fra Node, eller skal jeg bare hardkode dem?

Bedste reference


Efter lidt forskning har jeg fundet ud af at det er muligt at ringe til den relevante Windows API proc. (SHGetKnownFolderPath) for at få disse mappesteder, se docs på: https://msdn.microsoft.com/en-us/library/windows/desktop/bb762188(v=vs.85).aspx.[5]


Vi kalder APi ved hjælp af FFI npm modulet: https://www.npmjs.com/package/ffi. [6]


Det er muligt at finde GUID'erne for en kendt mappe her:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx[7]


Her er et script, der finder placeringen af ​​flere almindelige mapper,
nogle af koden er lidt hektisk, men er let ryddet op.


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('') + 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));   
}