登录 立即注册
查看: 11179|回复: 2

用c++写的一个控制逍遥的模块,包含获取模拟器列表和模拟器信息

[复制链接]

1

主题

0

帖子

10

积分

注册会员

Rank: 2

积分
10

逍遥新人资格章

发表于 2015-9-17 22:44:33 | 显示全部楼层 |阅读模式
小弟不才,最近在用逍遥模拟器,看了论坛里各种命令,就自己写了个控制模拟器的模块,代码使用c++编写.
功能并未全部完善,一些命令也正在捉摸中,先将写好的代码分享出来.
直接上代码.
=====定义模拟器运行状态
const int XIAOYAO_STATUS_INIT = 0; //找不到模拟器
const int XIAOYAO_STATUS_NOT_RUNNING = 1;// 未运行
const int XIAOYAO_STATUS_START = 2; //启动中
const int XIAOYAO_STATUS_RUNNING = 3; //运行中
const int XIAOYAO_STATUS_ERROR = 4;//出错 包括无法启动 卡死


==命令
const std::string sManagerExe = "D:\\Program Files\\Microvirt\\MEmuHyperv\\MEmuManage.exe";
const std::string sManagerConsole = "D:\\Program Files\\Microvirt\\MEmu\\MEmuConsole.exe";
const std::string sMemuPath = "D:\\Program Files\\Microvirt\\MEmu\\MEmu.exe";


==== class XiaoYao 主要存储模拟器的相关属性。
class XiaoYao {
private:
        std::string name; //模拟器名字
        int index; //模拟器编号
        int status; //模拟器状态 仅仅作为状态使用 不作为是否被正常使用的标示
        int runTime = 0; //运行时间单位秒
        std::string cfgFile;
        std::string uuid;
        int memSize = 1024; //内存大小 单位M
        int cpuNum = 1; //CPU 数目
        std::string macAddr1;
        std::string macAddr2;


        // 一次启动逍遥模拟器 会新增三个进程
        int iMemuExePid; //MEmu.exe进程ID
        int iMemuHeadLessPid; //MEmuHeadLess.exe  进程ID
        int iadbPid; //adb.exe进程ID

        int windHand; //窗口ID

        //启动失败次数
        int failNum = 0; //在总初始化的时候重置
        int bCanUser = true; //是否能使用 没被使用过的可以被使用 正在使用的无法被使用 为false

        //function
        bool getVmInfo(); //调用 MEmuManager.exe showvminfo 获取vm信息


public:

        ~XiaoYao();
        XiaoYao(const std::string& name);
        XiaoYao();
        //XiaoYao(XiaoYao xiaoyao);
        std::string getName() { return name; };
        int getIndex() { return index; };

        int getStatus() { return status; }; //获取模拟器当前状态

        std::string getCfgFile() { return cfgFile; }; //获取模拟器配置文件全路径

        int getRunTime() { return runTime; }; //获取运行时间

        int getMemSize() { return memSize; };
        int getCpuNum() { return cpuNum; };
        std::string getMacAddr1() { return macAddr1; };
        std::string getMacAddr2() { return macAddr2; };
        std::string getUUID() { return uuid; };

        void setStatus(int status) { this->status = status; };
        void setRunTime(int time) { this->runTime = time; };
        void setCfgFile(std::string cfg) { this->cfgFile = cfg; };
        void setMemSize(int memSize) { this->memSize = memSize; };
        void setCpuNum(int cpuNum) { this->cpuNum = cpuNum; };
        void setMacAddr1(std::string addr) { this->macAddr1 = addr; };
        void setMacAddr2(std::string addr) { this->macAddr2 = addr; }
        void setUUID(std::string uuid) { this->uuid = uuid; };
        void setWindHand(int hand) { windHand = hand; };
        void setAttr(std::map<std::string, std::string> attr);
        bool operator==(XiaoYao* other) {
                if (other == NULL) {
                        return false;
                }
                if (this->name == other->name) {
                        return true;
                }
                return false;
        };

        bool operator=(XiaoYao xiaoyao) {
                this->macAddr1 = xiaoyao.getMacAddr1();
                this->macAddr2 = xiaoyao.getMacAddr2();
                this->index = xiaoyao.getIndex();
                this->name = xiaoyao.getName();
                this->uuid = xiaoyao.getUUID();
                this->memSize = xiaoyao.getMemSize();
                this->cpuNum = xiaoyao.getCpuNum();
                this->cfgFile = xiaoyao.getCfgFile();
        };
        /*
        bool operator==(XiaoYao& other) {
                if (this->name == other.getName()) {
                        return true;
                }
                return false;
        };
        */

        int getFailNum() { return failNum; };
        void failed() { failNum++; };
        void signUsed() { bCanUser = false; }
        bool canUser() { return bCanUser; };
}; //类定义完毕


====XiaoYao实现 写一些主要的用命令获取数据的方法
1:获取具体的模拟器的各个属性值
bool XiaoYao::getVmInfo() {
        std::string cmd = sManagerExe + " showvminfo " + this->getName() + "  --machinereadable";
        std::string result;
        std::string err;
        char cmdBuf[1024];
        memset(cmdBuf, 0x00, sizeof(cmdBuf));
        strcpy_s(cmdBuf, cmd.c_str());
       //windows下通过管道执行逍遥的命令行 并获取输出
       /*
         命令行输出格式为:
           name="MEmu"
           groups="/"
           ostype="Other Linux (32 bit)"
            UUID="4b2a05dd-4ba4-43bb-a3ff-a9fe52bf19a8"

            。。。。。

          以上结果自动回车换行了,但是程序获取到的结果保存串是没有自动换行的。所以result结果为name="MEmu"\r\ngroups="/"
          程序处理的时候请按回车换行符(\r\n)分割
       */
        if (!callExe(cmdBuf, result, err)) {
                return false;
        }

       //getKeyValue 此函数作用为按照分隔符形成健值对。最后的key_value map中的数据是这样子的:
       // "name" "MEmu"
       // "groups" ""
        map<std::string, std::string> key_value = getKeyValue(result,"=");
       //设置属性
        setAttr(key_value);
        return true;
}


//设置属性 此处我只设置了几个属性大家可以根据自己需要设置。
void XiaoYao::setAttr(map<std::string, std::string> attr) {
        map<std::string, std::string>::iterator iter = attr.begin();
        for (; iter != attr.end(); iter++) {
                if (iter->first == "memory") {
                        this->setMemSize(atoi(iter->second.c_str()));
                }

                if (iter->first == "VMState") {
                        if (iter->second == "poweroff" || iter->second == "aborted") {
                                this->setStatus(XIAOYAO_STATUS_NOT_RUNNING);
                        }
                        else {
                                this->setStatus(XIAOYAO_STATUS_RUNNING);
                        }
                }
                if (iter->first == "macaddress1") {
                        this->setMacAddr1(iter->second);
                }

                if (iter->first == "macaddress2") {
                        this->setMacAddr2(iter->second);
                }
                if (iter->first == "cpus") {
                        this->setCpuNum(atoi(iter->second.c_str()));
                }
                if (iter->first == "UUID") {
                        this->setUUID(iter->second);
                }
        }
}


2:获取VM列表
//XiaoYaoManager 为管理逍遥模拟器的类 主要是获取所有逍遥模拟器和启动 关闭
void XiaoYaoManager::init() {
        //获取所有VM 列表
        std::string cmd = sManagerExe + " list vms";
        char cmdBuf[512];
        memset(cmdBuf, 0x00, sizeof(cmdBuf));
        strcpy_s(cmdBuf, cmd.c_str());
        std::string result;
        std::string err;
        if (!callExe(cmdBuf, result, err)) {
                printf("运行命令失败:%s", cmdBuf);
                return;
        }
        Sleep(DELAY_COMMON_EXE_WAITFOR_TIME_MISEC);
        std::map<std::string, std::string> mKey = getKeyValue(result);
        std::map<std::string, std::string>::iterator iter = mKey.begin();
        for (; iter != mKey.end(); iter++) {
                XiaoYao xiaoyao(iter->first);
                xiaoyao.setUUID(iter->second);
                lAll.push_back(xiaoyao);
        }
}



// 执行exe并获取其输出
bool callExe(char* cmd, std::string& outPut, std::string& errInfo) {
                outPut = "";
                SECURITY_ATTRIBUTES sa;
                HANDLE hRead, hWrite;
                sa.nLength = sizeof(SECURITY_ATTRIBUTES);
                sa.lpSecurityDescriptor = NULL; //使用系统默认的安全描述符  
                sa.bInheritHandle = TRUE; //创建的进程继承句柄  
                int retCode = CreatePipe(&hRead, &hWrite, &sa, 0);
                if (retCode == 0) //创建匿名管道  
                {
                        printf("创建管道失败,错误码:%d\n", GetLastError());
                        errInfo = "创建管道失败,错误码:" + GetLastError();
                        return false;
                }

                STARTUPINFO si;
                PROCESS_INFORMATION pi;

                ZeroMemory(&si, sizeof(STARTUPINFO));

                si.cb = sizeof(STARTUPINFO);
                GetStartupInfo(&si);
                si.hStdError = hWrite;
                si.hStdOutput = hWrite; //新创建进程的标准输出连在写管道一端  
                si.wShowWindow = SW_HIDE; //隐藏窗口  
                si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;



                if (!CreateProcess(NULL, cmd, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi)) //创建子进程  
                {
                        errInfo = "创建CreateProcess失败,错误码:" + GetLastError();
                        return false;
                }
                CloseHandle(hWrite); //关闭管道句柄  

                char buffer[4096] = { 0 };
                DWORD bytesRead;

                while (true)
                {
                        if (ReadFile(hRead, buffer, 4095, &bytesRead, NULL) == NULL) //读取管道  
                                break;
                        outPut += buffer;
                        Sleep(100);
                }
                CloseHandle(hRead);
                return true;

}


===========================================================
今天先发这些,有空再继续发。

评分

参与人数 2贡献 +10 收起 理由
huixia0010 + 5 赞,直接编译成dll放出来好了
心芝雨 + 5 虽然 看不懂 也没有附近 感觉挺给力

查看全部评分

回复

使用道具 举报

0

主题

0

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2016-1-1 17:52:14 | 显示全部楼层
谢谢分享,花了时间和心思的了
回复 支持 反对

使用道具 举报

0

主题

0

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2016-1-1 17:54:39 | 显示全部楼层
只能看懂易语言的
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|模拟器|手机模拟器|手游模拟器|安卓模拟器|( 沪ICP备14046591号 )

GMT+8, 2024-4-30 21:57 , Processed in 0.030828 second(s), 31 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表