js笔记九:当运行脚本

来源:互联网 发布:pe系统支持网络功能 编辑:程序博客网 时间:2024/05/17 23:53

说明

在windows下面,现在有powershell,linux下面有bash,也可以用python,但是即然用了node,也就可以用js写脚本了。

apk的版本号

这里提供一个简单例子,就是读取apk的版本号,运行环境是windows下面的node 6.x
下面这个这个xutils.js提供了读取apk版号的所有功能

//xutils.jsconst util = require('util');const exec = require('child_process');const fs = require('fs');class xutils {    /**     * 判断对象是否为null或undefined     * @param {object} paramObject      */    static isObjectNull(paramObject) {        return paramObject === null || paramObject === undefined;    }    /**     *      * @param {String} paramStr      * @param {String} paramFindStr      * @returns boolean 返回结果     */    static isContains(paramStr, paramFindStr) {        if (!util.isString(paramStr)) return false;        if (!util.isString(paramFindStr)) return false;        return paramStr.indexOf(paramFindStr) >= 0;    }    /**     * 取apk的版本号     * simple: package: name='com.xxx.yyyy' versionCode='1611' versionName='1.2.43' platformBuildVersionName='8.0.0'     * @param {string} paramLine 存在版本号的那一行     * @param {map} paramResultMap 保存结果的map     */    static ReadAPKVersionToMap(paramLine, paramResultMap) {        if (!util.isString(paramLine)) return;        let s = paramLine.split(' ');        for (let i = 0; i < s.length; i++) {            let item = s[i].trim();            let itemKV = item.split('=');            if (itemKV.length === 2) {                let k = itemKV[0].trim();                let v = itemKV[1].trim().replace(/['"]/g, '');                paramResultMap.set(k, v);            }        }    }    /**     * 读取sdk版本号 如:sdkVersion:'19'     * @param {string} paramLine      * @param {map} paramResultMap      */    static ReadSDKVersionToMap(paramLine, paramResultMap) {        if (!util.isString(paramLine)) return;        let s = paramLine.split(':');        if (s.length === 2) {            let k = s[0].trim();            let v = s[1].trim().replace(/['"]/g, '');            paramResultMap.set(k, v);        }    }    /**     * 读取权限     * simple:uses-permission: name='android.permission.READ_PHONE_STATE'     * @param {string} paramLine      * @param {Array<String>} paramList      */    static ReadAPKPermission(paramLine, paramList) {        if (!util.isString(paramLine)) return;        let s = paramLine.split('=');        if (s.length === 2) {            paramList.push(s[1].replace(/['"]/g, ''));        }    }    /**     *      * @param {String} paramExec aapt的全路径名称     * @param {String} paramAPKName 要分析的名称     * @param {String} paramCWD exec工作路径     */    static GetAPKVersion(paramExec, paramAPKName, paramCWD) {        let option = {};        let cmdArgs = ['d', 'badging', paramAPKName];        let ret = { err: -1, errMsg: '' };        if (!this.isObjectNull(paramCWD)) {            option.cwd = paramCWD;        }        let strOut = null;        try {            //这里是调用android的工具 aapt.exe ,它所在的位置,从配置中读取。            let stdoutresult = exec.execFileSync(paramExec, cmdArgs, option).toString();            strOut = stdoutresult;            ret.version = new Map();            ret.permission = [];            ret.err = 0;            let arrayLine = strOut.split('\n');            for (let i = 0; i < arrayLine.length; i++) {                let line = arrayLine[i].trim();                if (this.isContains(line, 'package:')) {                    this.ReadAPKVersionToMap(line, ret.version);                }                else if (this.isContains(line, 'sdkVersion:') || this.isContains(line, 'targetSdkVersion:')) {                    this.ReadSDKVersionToMap(line, ret.version);                }                else if (this.isContains(line, 'uses-permission:')) {                    this.ReadAPKPermission(line, ret.permission);                }                else {                    //其它的信息                }            }        } catch (e) {            ret.err = -1;            ret.errMsg = "has exception:" + e.toString();            console.log(ret.errMsg);        }        return ret;    }}exports.xutils = xutils;

调用

//main.js

const exec = require('child_process');const {xutils} = require('./xutils');let args = process.argv.splice(2); //注意,这里需要读取一个参数,也就是配置jsondo{    if(!Array.isArray(args) || args.length !== 1)    {        console.log('usage: you_config.json');        break;    }    let config = require(args[0]); //加载配置    console.log("当前配置:");    console.log(config);    let cfg = config.config;    let strSrcAPK = cfg.apk_src;    let str_aapt  = cfg.aapt;    let r = xutils.GetAPKVersion(str_aapt, strSrcAPK);    if(r.err !== 0) {        console.log("get apk version fail:" + r.err + "," + r.errMsg);        break;    }    console.log(r); //显示处理后的结果,不需要,可以删除        let ver = r.version.get('versionName');    console.log(ver);}while(false);process.exit(0);

配置文件

这个是在运行参数中指定的 main.json

{    "title":"本地环境配置",    "config": {        "aapt":"D:\\tools\\androidtools\\aapt.exe",        "apk_src":"D:\\work\\app\\build\\outputs\\apk\\app-debug.apk"    }}

调用的批处理

为了方便使用,在main.js目录下,建一个main.bat,来调用这个js

node main.js ./main.jsonpause

这里,就可以实现显示指定的apk版本号的功能了

遇到的一些问题

  • 发现,像dos下的copy,del,等命令不能通过child_process来调用,因为这些是dos的内部命令,后来,发现child_process可以调用*.bat文件,于是就可以把dos内部命令,通过bat文件来调用,这样就解决了问题了。如果是linux下面,应该就不会有这样的问题了。
const exec = require('child_process');//这里是调用Bat文件的例子/** * 复制文件 * @param {String} paramSrc  * @param {String} paramDest  */function CopyFile(paramSrc, paramDest) {    try{        console.log("copy file:" + paramSrc + "==>" + paramDest);        exec.execFileSync("cp.bat", [paramSrc, paramDest], {cwd:process.cwd()}).toString();        console.log("copy OK!");    }catch(e) {        console.log("copy file fail:" + e.toString());    }}

这里是cp.bat

rem 直接调用dos命令copy %1 %2
  • 关于child-process这里的函数,可以去官网查看api
    execFileSync这个同步执行命令,并返回运行结果。一般情况下,要指定当前路径。

最后

通过使用execFileSync,我们就可以用js写一些高级处理运行脚本