2012-06-22 25 views
6

Tengo un script de JScript que se ejecuta con cscript.exe. Crea un acceso directo en el escritorio (y en el menú de inicio) que ejecuta cscript.exe con parámetros para ejecutar otro script de JScript. Se ve, en la parte pertinente, así:¿Cómo puedo usar JScript para crear un acceso directo que utiliza "Ejecutar como administrador"

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

que se llama así create_shortcut_at(desktop_folder, script_folder).

Y eso funciona, hasta donde llega. Crea el ícono de escritorio, apuntando correctamente al guión y lo ejecuta al hacer doble clic. El problema es que realmente necesita ejecutar el script "como administrador".

Y la secuencia de comandos realmente necesita ejecutar "como administrador" - instala las aplicaciones (para todos los usuarios) y reinicia la computadora. (Para aquellos interesados, la secuencia de comandos es wpkg.js. No es deseable modificarla para autoevaluarse.)

Dado que el destino del atajo es realmente "cscript.exe", no puedo usar un manifiesto para la escalada . Probablemente podría instalar un cscript.exe.manifest en el directorio de Windows, pero incluso si eso funcionara, sería una idea terrible por razones que son obvias.

También preferiría no utilizar una secuencia de comandos ficticia, ya que es un archivo adicional para tratar y hay otra solución, aparentemente razonable, a mano: marque la casilla "Ejecutar como administrador" en el acceso directo.

Treinta segundos de investigación revelan que el objeto WScript.Shell ActiveX no tiene las interfaces necesarias para esto. La investigación adicional sugiere que IShellLinkDataList sí lo hace. Sin embargo, IShellLinkDataList es una interfaz COM genérica. Veo varios ejemplos en Internet, la mayoría vinculando here. Sin embargo, todos los ejemplos lo hacen en código compilado (C++, C#, incluso JScript.NET). De manera significativa, prefiero poder hacerlo directamente en JScript, ejecutándose desde cscript.exe.

Dicho esto, estoy a favor de ideas que no contemplé u otras soluciones.

Respuesta

4

La forma oficial de marcar un archivo de acceso directo que requiere elevación es a través de IShellLinkDataList. Es difícil usar esa interfaz desde un entorno de automatización.

Pero, si está contento con un truco, puede hacerlo en secuencia de comandos, simplemente volteando un poco en el archivo .lnk.

Cuando marca la casilla "Ejecutar como administrador" en la ficha Avanzado del cuadro de Propiedades del shell, o cuando use IShellLinkDataList to set the flags para incluir SLDF_RUNAS_USER, básicamente está configurando un bit en el archivo.

Puede hacerlo "manualmente" sin pasar por la interfaz COM. Es el byte 21, y necesita configurar el bit de 0x20.

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

para ayudar a personas que necesitan futuros esta solución, se especifica aquí el formato .lnk: http://msdn.microsoft.com/en-us/library/dd871305 (v = prot.13). En particular, esto utiliza el http://msdn.microsoft.com/en-us/library/dd891314(v=prot.13). Solución muy inteligente, gracias! – alficles

Cuestiones relacionadas