JScript:识别是否将双引号传递给 WSH 脚本

JScript: identifying whether double quotes are passed to a WSH script

在某些情况下,识别双引号是否作为参数传递给 WSH 脚本很重要。例如,因为它们应该传递给另一个可执行文件 运行.

标准解析functions/objects:

objArgs = WScript.Arguments;
for (i = 0; i < objArgs.length; i++)
{
   WScript.Echo(objArgs(i));
}

不区分:

cscript foo.js  "bar"

cscript foo.js  bar

是否可以使用其他方法?

注意:我还尝试通过多种组合来逃避它们,例如:

cscript foo.js  '"bar"'

看起来它们只是被剥离了。

正在关注@Ekkehard.Horner 建议:

解决方案

// parseArgs.js     
// Parsing jscript script arguments verbatim 

var Shell =  new ActiveXObject("WScript.Shell"),
    wmi  = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2"),
    guid = (new ActiveXObject("Scriptlet.TypeLib")).GUID.substring(0,38),
    windir=Shell.ExpandEnvironmentStrings("%WinDir%"),
    winver="\"" + windir +  "\System32\winver.exe\" " + guid,
    pcol, pid, cmd;


// Run winver.exe hidden and get this script ID as its ParentProcessId 
winver=winver.replace(/\/g, "\\");
Shell.Run("winver " + guid, 0);
pcol = new Enumerator (wmi.ExecQuery( 
  "SELECT * From Win32_Process WHERE CommandLine='"+ winver + "'",
  "WQL", 32));
for (; !pcol.atEnd(); pcol.moveNext()){
  var prc = pcol.item();
  pid=prc.ParentProcessId;
  prc.Terminate;
}


// Get the command line for the found PID 
pcol = new Enumerator (wmi.ExecQuery( 
  "SELECT * From Win32_Process WHERE ProcessID="+ pid,
  "WQL", 32));
for (; !pcol.atEnd(); pcol.moveNext()){
  var prc = pcol.item();
  cmd =prc.CommandLine;
}
WScript.Echo(cmd);

// Parse command line for arguments
var ags,
    parseCmd=function(cmd){// WMI trims initial spaces
      var p = new Object(),
          re =/^"/.test(cmd) ? /"[^"]+" */ : /\S+\s*/;
      p.nxt=re.test(cmd) ? cmd.match(re)[0] : ""; // extract next token
      p.rst=cmd.replace(re, "")                 ; // remainder     
      return(p);
    }


// Strip c/wscript path 
ags=parseCmd(cmd).rst
//WScript.Echo(ags);

// Remove WSH "//xxx" options 
ags=ags.replace(/\/\/\w+ +/g, "")   
//WScript.Echo(ags);

// Strip script name and get arguments
ags=parseCmd(ags).rst
WScript.Echo(ags);

// Loop args and store as an array 
var i=1, aags=[];
while(ags != ""){
  var p =parseCmd(ags);
  ags=p.rst;
  aags.push(p.nxt.replace(/ +$/, ""));
  WScript.Echo(i, p.nxt);
  i++;
}
WScript.Echo(aags);

测试

运行 parseArgs.js 给出:

> cscript //nologo parseArgs.js "hello" world
cscript  //nologo parseArgs.js "hello" world
"hello" world
1 "hello"    
2 world
"hello",world

行:

> parseArgs.js "hello" world

给出相似的结果。

评论

我们需要这么复杂的脚本吗?简短的回答:没有。长:视情况而定。

一般来说,假设您知道脚本的名称,当它是 运行 时,您可以查询 WMI。
无论如何,当您部署脚本时,您通常无法控制部署目录。所以,如果有另一个同名脚本运行ning,你无法确定哪个是你的。
另一个不那么极端的情况是当你的脚本有两个或更多实例时 运行ning.

这里的策略是 运行 隐藏一些虚拟标准 Windows 可执行文件 (winver.exe),并向其传递一个 GUID。这样,通过唯一的 GUID 识别 winver.exe 命令行是安全的,因此您的脚本是 winver.exe.
的父级 winver.exe 不需要参数,但如果你传递一些给它也不会抗议。