Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
358 views
in Technique[技术] by (71.8m points)

com - How can I use JScript to create a shortcut that uses "Run as Administrator"

I have a JScript script that runs using cscript.exe. It creates a shortcut on the desktop (and in the start menu) that runs cscript.exe with parameters to run another JScript script. It looks, in relevant part, like this:

function create_shortcut_at(folder, target_script_folder)
{
    var shell = new ActiveXObject("WScript.Shell");
    var shortcut = shell.CreateShortcut(folder + "\Run The Script.lnk");
    shortcut.TargetPath = "cscript";
    shortcut.Arguments = """+target_script_folder+"\script.js" /aParam /orTwo";
    shortcut.IconLocation = target_script_folder+"\icon.ico";
    shortcut.Save();
}

It gets called like create_shortcut_at(desktop_folder, script_folder).

And that works, as far as it goes. It creates the desktop icon, pointing properly to the script and runs it when double-clicked. The problem is that it really needs to run the script "as administrator".

And the script really does need to run "as administrator" -- it installs applications (for all users) and reboots the computer. (For those interested, the script is wpkg.js. Modifying it to self-elevate is undesirable.)

Since the target of the shortcut is actually "cscript.exe", I can't use a manifest for the escalation. I could probably theoretically install a cscript.exe.manifest in the windows directory, but even if that worked, it would be a terrible idea for reasons that are obvious.

I'd also prefer not to use a dummy script, since that is an extra file to deal with and there's another, seemingly reasonable, solution at hand: check the "Run as administrator" box on the shortcut.

Thirty-seconds of investigation reveals that the WScript.Shell ActiveX Object does not have the interfaces required for this. Additional investigation suggests that IShellLinkDataList does. However, IShellLinkDataList is a generic COM Interface. I see several examples around the Internet, most linking here. However, all the examples do it in compiled code (C++, C#, even JScript.NET). I significantly prefer to be able to do it directly in JScript, running from cscript.exe.

That said, I'm all for ideas I didn't contemplate or other solutions.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The official way to mark a shortcut file as requiring elevation is via IShellLinkDataList. It's difficult to use that interface from an automation environment.

But, if you are happy with a hack, you can do it in script, just by flipping a bit in the .lnk file.

When you tick the "run as administrator" box in the Advanced tab of the Shell Properties box, or when you use IShellLinkDataList to set the flags to include SLDF_RUNAS_USER, you're basically just setting one bit in the file.

You can do that "manually" without going through the COM interface. It's byte 21, and you need to set the 0x20 bit on.

(function(globalScope) {
    'use strict';
    var fso = new ActiveXObject("Scripting.FileSystemObject"),
        path = "c:\path\goes\here\Shortcut2.lnk",
        shortPath = path.split('\').pop(),
        newPath = "new-" + shortPath;

    function readAllBytes(path) {
        var ts = fso.OpenTextFile(path, 1), a = [];
        while (!ts.AtEndOfStream)
            a.push(ts.Read(1).charCodeAt(0));
        ts.Close();
        return a;
    }

    function writeBytes(path, data) {
        var ts = fso.CreateTextFile(path, true),
            i=0, L = data.length;
        for (; i<L; i++) {
            ts.Write(String.fromCharCode(data[i]));
        }
        ts.Close();
    }

    function makeLnkRunAs(path, newPath) {
        var a = readAllBytes(path);
        a[0x15] |= 0x20; // flip the bit. 
        writeBytes(newPath, a);
    }

    makeLnkRunAs(path, newPath);

}(this));

ps:

function createShortcut(targetFolder, sourceFolder){
    var shell = new ActiveXObject("WScript.Shell"),
        shortcut = shell.CreateShortcut(targetFolder + "\Run The Script.lnk"),
        fso = new ActiveXObject("Scripting.FileSystemObject"),
        windir = fso.GetSpecialFolder(specialFolders.windowsFolder);

    shortcut.TargetPath = fso.BuildPath(windir,"system32\cscript.exe");
    shortcut.Arguments = """ + sourceFolder + "\script.js" /aParam /orTwo";
    shortcut.IconLocation = sourceFolder + "\icon.ico";
    shortcut.Save();
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...