|
小弟不才,近在用逍遥模拟器,看了论坛里各种命令,就自己写了个控制模拟器的模块,代码使用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;
}
===========================================================
今天先发这些,有空再继续发。
|
评分
-
查看全部评分
|