JScript:确定是否将双引号传递给WSH脚本

时间:2016-10-31 19:50:50

标签: vbscript jscript wsh

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

标准解析函数/对象:

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"'

似乎他们被剥夺了。

1 个答案:

答案 0 :(得分:2)

关注@ 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 无论如何,在部署脚本时,通常无法控制deploy目录。因此,如果有另一个脚本以相同的名称运行,您无法确定哪一个是您的。
另一个不太边缘的情况是当你的脚本有两个或更多实例运行时。

这里的策略是隐藏一些虚拟标准Windows可执行文件(winver.exe),并向其传递一个GUID。通过这种方式,可以安全地通过唯一GUID标识winver.exe命令行,从而将您的脚本标识为winver.exe的父级。
winver.exe不需要参数,但如果你传递一些参数就不会抗议。