【问题标题】:Windows Scripting to call other commands?Windows脚本调用其他命令?
【发布时间】:2012-06-28 00:19:00
【问题描述】:

我正在尝试使用cscriptJavascript 编写Windows shell 脚本。这个想法是采用一个非常长的 Python 命令,我厌倦了一遍又一遍地输入命令行。我想要做的是编写一个更短的脚本,将整个 Python 命令写入 Windows 脚本,然后调用 Windows 脚本,这样输入起来会少很多。我只是不知道如果有意义的话,我将如何调用“命令中的命令”。

这可能是一件容易的事情,但我是这方面的新手,所以请多多包涵!

想法:

原始命令示例:python do <something really complicated with a long filepath>

Windows 脚本:cscript easycommand

 <package id = "easycommand">
      <job id = "main" >
          <script type="text/javascript">
               // WHAT GOES HERE TO CALL python do <something really complicated>
               WScript.Echo("Success!");
          </script>
      </job>
 </package>

感谢您的帮助!

【问题讨论】:

  • 有什么特别的原因你没有使用 Python 或 CMD.EXE 来完成这个任务吗?我认为两者都会更容易......
  • 我想我真正的问题是,如果我在命令提示符下的目录与 Python/CMD.EXE 文件所在的目录不同,我将如何访问该 Python 命令或 CMD.EXE 命令;换句话说,我如何让它通用?
  • @sarnold - 我不同意。在 Windows 上使用 jscript/WSH 编写 sysadmin 脚本没有任何问题。
  • @Cheeso:我很惊讶运行带有参数的 Python 程序被完全交给了不同的工具。当然,这并没有什么,但我喜欢减少任何给定应用程序/解决方案使用的依赖项的数量——即使我知道我会继续维护旧的 Perl 脚本而是用 Ruby 重写整个东西,只是因为我不想在没有充分理由的情况下对人们施加新的依赖。
  • 当然。我可能误会了。如果目标是运行 python 程序,那么......为什么不只运行 python 应用程序呢?但如果目标是编写一般管理任务的脚本,那么 jscript+WSH 似乎是一个合理的选择。干杯。

标签: javascript windows shell command-prompt wsh


【解决方案1】:

这是我用的

function logMessage(msg) {
    if (typeof wantLogging != "undefined" && wantLogging) {
        WScript.Echo(msg);
    }
}

// http://msdn.microsoft.com/en-us/library/d5fk67ky(VS.85).aspx
var windowStyle = {
    hidden    : 0,
    minimized : 1,
    maximized : 2
};

// http://msdn.microsoft.com/en-us/library/a72y2t1c(v=VS.85).aspx
var specialFolders = {
    windowsFolder   : 0,
    systemFolder    : 1,
    temporaryFolder : 2
};

function runShellCmd(command, deleteOutput) {
    deleteOutput = deleteOutput || false;
    logMessage("RunAppCmd("+command+") ENTER");
    var shell = new ActiveXObject("WScript.Shell"),
        fso = new ActiveXObject("Scripting.FileSystemObject"),
        tmpdir = fso.GetSpecialFolder(specialFolders.temporaryFolder),
        tmpFileName = fso.BuildPath(tmpdir, fso.GetTempName()),
        rc;

    logMessage("shell.Run("+command+")");

    // use cmd.exe to redirect the output
    rc = shell.Run("%comspec% /c " + command + "> " + tmpFileName,
                       windowStyle.Hidden, true);
    logMessage("shell.Run rc = "  + rc);

    if (deleteOutput) {
        fso.DeleteFile(tmpFileName);
    }
    return {
        rc : rc,
        outputfile : (deleteOutput) ? null : tmpFileName
    };
}

下面是一个示例,说明如何使用上述方法列出在 IIS 中使用 Appcmd.exe 定义的站点:

var
fso = new ActiveXObject("Scripting.FileSystemObject"),
windir = fso.GetSpecialFolder(specialFolders.WindowsFolder),
r = runShellCmd("%windir%\\system32\\inetsrv\\appcmd.exe list sites");
if (r.rc !== 0) {
    // 0x80004005 == E_FAIL
    throw {error: "ApplicationException",
           message: "shell.run returned nonzero rc ("+r.rc+")",
           code: 0x80004005};
}

// results are in r.outputfile

var
textStream = fso.OpenTextFile(r.outputfile, OpenMode.ForReading),
sites = [], item, 
re = new RegExp('^SITE "([^"]+)" \\((.+)\\) *$'),
parseOneLine = function(oneLine) {
    // each line is like this:  APP "kjsksj" (dkjsdkjd)
    var tokens = re.exec(oneLine), parts;

    if (tokens === null) {
        return null;
    }
    // return the object describing the website
    return {
        name : tokens[1]
    };
};

// Read from the file and parse the results.
while (!textStream.AtEndOfStream) {
    item = parseOneLine(textStream.ReadLine()); // you create this...
    logMessage("  site: " + item.name);
    sites.push(item);
}
textStream.Close();
fso.DeleteFile(r.outputfile);

【讨论】:

    【解决方案2】:

    嗯,基本上:

    1. 获取 shell 句柄,以便执行脚本
    2. 将要执行的命令(参数和所有)创建为字符串
    3. 在 shell 句柄上调用 Run 方法,并确定您想要哪种窗口模式以及是否要等到生成的进程完成(可能)。
    4. 错误处理,因为Run 抛出异常

    此时,如果您需要多次执行此操作,则值得编写大量实用函数:

    // run a command, call: run('C:\Python27\python.exe', 'path/to/script.py', 'arg1', 'arg2') etc.
    function run() {
      try {
        var cmd = "\"" + arguments[0] + "\"";
        var arg;
        for(var i=1; i< arguments.length; ++i) {
          arg = "" + arguments[i];
          if(arg.length > 0) {
        cmd += arg.charAt(0) == "/" ? (" " + arg) : (" \"" + arg + "\"");
          }
        }
        return getShell().Run(cmd, 1, true); // show window, wait until done
      }
      catch(oops) {
        WScript.Echo("Error: unable to execute shell command:\n"+cmd+ 
                 "\nInside directory:\n" + pwd()+
             "\nReason:\n"+err_message(oops)+
             "\nThis script will exit.");
        exit(121);
      }
    }
    
    // utility which makes an attempt at retrieving error messages from JScript exceptions
    function err_message(err_object) {
      if(typeof(err_object.message) != 'undefined') {
        return err_object.message;
      }
      if(typeof(err_object.description) != 'undefined') {
        return err_object.description;
      }
      return err_object.name;
    }
    
    // don't create new Shell objects each time you call run()
    function getShell() {
      var sh = WScript.CreateObject("WScript.Shell");
      getShell = function() {
        return sh;
      };
      return getShell();
    }
    

    对于您的用例,这可能就足够了,但您可能希望使用例程来扩展它以更改工作目录等。

    【讨论】:

      猜你喜欢
      • 2015-04-14
      • 2018-02-27
      • 1970-01-01
      • 1970-01-01
      • 2014-01-05
      • 1970-01-01
      • 2022-11-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多