|
Nebula2探秘12-基于Windows命令行的Nebula控制台
happykevins文
“工欲善其事,必先利其器!”
本文创建了一个在命令窗口下的Nebula命令控制台.可以直接执行脚本指令,察看当前Nebula的系统状态,察看NOH树及当前工作对象信息,对于调试和控制Nebula2程序非常实用方便!
本来Nebula2在nGui系统中已经实现了一个叫做nGuiCmdEntry的控件,这个控件就具备即时执行脚本的功能,但我们在实际开发中可能会抛弃nGui而使用其他如CEGUI的界面系统进行替换,所以我们需要一个通用的解决方案:适用Windows控制台作为Nebula控制台的载体,于是就产生了本文的nConConServer。
在nConConServer中借鉴了nGuiCmdEntry中对用户输入脚本指令的处理方式,并加入了几条实用的全局指令,使用”-help”指令查看全局指令帮助,代码如下:
/****************************************************************************/ /* Nebula2 - Tutorial Utils */ /* nConConServer - 控制台下的Nebula2指令控制台 */ /* author: happykevins */ /****************************************************************************/ #pragma once
#include ”kernel/nkernelserver.h” #include ”kernel/nscriptserver.h” #include ”kernel/nautoref.h”
#define KS_USE_STDOUT #include ”nkernelinfo.h” #undef KS_USE_STDOUT
#define LINE_BUF_MAX_SIZE 512 #define GLOBAL_CMD_TOKEN ''-''
class nConConServer : public nRoot { public: /// constructor nConConServer(); /// destructor virtual ~nConConServer(); /// Toggle Mode void ToggleMode(); /// Poll Commands void PollCmd(); /// Execute String void ExecuteCommand(const char* szCmdStr);
protected: /// set edit line buffer void SetEditLine(const char* szCmdBuf); /// execute the current command void ExecuteEditLine(); /// checking the char effect bool CheckingChar(char ch); /// global function check void ExecuteGlobal(); /// add current command to history void AddCommandToHistory(); /// recall next command in history void RecallNextCommand(); /// recall previous command in history void RecallPreVCommand(); /// set local cwd void SetCwd(nRoot* cwd); /// get local cwd (can return 0) nRoot* GetCwd(); /// update the tab completion stuff void UpdateTabComplete(); /// perform a tab completion void DoTabCompletion();
private: nKernelInfoHelper m_info; bool m_bRecvCmd;
size_t m_nLineBufPtr; char m_szLineBuf[LINE_BUF_MAX_SIZE];
nString editLine; nAutoRef<nScriptServer> refScriptServer; nRef<nRoot> refCwd; };
// nconconserver.cpp #pragma warning(push) #pragma warning(disable: 4267 4244)
#include ”nconconserver.h” #include ”nutildefs.h” ///----------------------------------------------------------------------------
/// constructor nConConServer::nConConServer() : m_bRecvCmd(false), refScriptServer(”/sys/servers/script”) { }
/// destructor nConConServer::~nConConServer() { }
/// Toggle Mode void nConConServer::ToggleMode() { m_bRecvCmd = !m_bRecvCmd;
if ( m_bRecvCmd ) { // Welcome Text printf(” ”); printf(”%s ”, ”=========================”); printf(”%s ”, ” ConConServer Welcome :)” ); printf(”%s ”, ”=========================”); } }
/// Poll Commands void nConConServer::PollCmd() { while ( m_bRecvCmd ) { printf(” :>”); memset(m_szLineBuf, 0, LINE_BUF_MAX_SIZE); m_nLineBufPtr = 0; char ch; while ( (ch = getchar()) != '' '' ) { if ( CheckingChar(ch) ) { continue; }
m_szLineBuf[m_nLineBufPtr] = ch; m_nLineBufPtr++; } m_szLineBuf[m_nLineBufPtr] = ''\0'';
ExecuteCommand(m_szLineBuf); } }
/// Execute String void nConConServer::ExecuteCommand(const char* szCmdStr) { SetEditLine(m_szLineBuf); ExecuteEditLine(); }
/// set edit line buffer void nConConServer::SetEditLine(const char* szCmdBuf) { editLine.Set(szCmdBuf); }
/// execute the current command void nConConServer::ExecuteEditLine() { // check and run global function if ( GLOBAL_CMD_TOKEN == editLine[0] ) { ExecuteGlobal(); return; }
// check if script server is ok if ( !refScriptServer.isvalid() ) { printf(”Error: Script Server is not Startup! ”); return; }
nScriptServer* scriptServer = this->refScriptServer.get();
// make local cwd global nKernelServer::Instance()->PushCwd(this->GetCwd());
// and run the command through the script server nString result = 0; bool failOnError = scriptServer->GetFailOnError(); scriptServer->SetFailOnError(false); scriptServer->Run(this->editLine.Get(), result); scriptServer->SetFailOnError(failOnError); if (result.IsValid()) { printf(”%s ”, result.Get()); } this->AddCommandToHistory(); this->editLine.Clear();
// set new local cwd nRoot* newCwd = nKernelServer::Instance()->GetCwd(); if (newCwd != this->GetCwd()) { this->SetCwd(nKernelServer::Instance()->GetCwd()); this->UpdateTabComplete(); }
// restore previous cwd nKernelServer::Instance()->PopCwd(); }
/// checking the char effect bool nConConServer::CheckingChar(char ch) { return false; }
/// global function check void nConConServer::ExecuteGlobal() { char* szRealCmd = m_szLineBuf + 1;
if ( 0 == strcmp(”help”, szRealCmd) ) { printf(”%s ”, ”=========================”); printf(”%s ”, ”ConConServer Help List :)”); printf(”%s ”, ”=========================”); printf(”%s ”, ”*Command List: ”); printf(”%s ”, ” help: Show this Text!”); printf(”%s ”, ” exit: Exit ConConServer Mode.”); printf(”%s ”, ” noh : Display a Tree View of Nebula NOH.”); printf(”%s ”, ” cls : Show Current ReGIStered Class List.”); printf(”%s ”, ” cwd : Show Current Working Object Info.”); printf(”%s ”, ” mtd : Show the Methods that Current Working Object Support.”); } else if ( 0 == strcmp(”exit”, szRealCmd) ) { ToggleMode(); } else if ( 0 == strcmp(”noh”, szRealCmd) ) { m_info.LogNOH(this->GetCwd()->GetFullName().Get()); } else if ( 0 == strcmp(”cls”, szRealCmd) ) { m_info.LogCLS(); } else if ( 0 == strcmp(”cwd”, szRealCmd) ) { printf(”CWD : %s ”, this->GetCwd()->GetFullName().Get() ); printf(”Class : %s ”, this->GetCwd()->GetClass()->GetProperName() ); printf(”Parent: %s ”, this->GetCwd()->GetClass()->GetSuperClass()->GetProperName() ); } else if ( 0 == strcmp(”mtd”, szRealCmd) ) { nHashList* obj = this->GetCwd()->GetClass()->GetCmdList();
nCmdProto* node = (nCmdProto*)obj->GetHead();
do { printf(”%s ”, node->GetProtoDef()); } while ( (node = (nCmdProto*)node->GetSucc()) ); } else { printf(”%s ”, ”Error: ''-'' follows Unkown Globle Command!”); } }
/// add current command to history void nConConServer::AddCommandToHistory() { // empty. } /// recall next command in history void nConConServer::RecallNextCommand() { // empty. } /// recall previous command in history void nConConServer::RecallPrevCommand() { // empty. } /// set local cwd void nConConServer::SetCwd(nRoot* cwd) { this->refCwd = cwd; } /// get local cwd (can return 0) nRoot* nConConServer::GetCwd() { if ( !this->refCwd.isvalid() ) { this->SetCwd(nKernelServer::Instance()->GetCwd()); } return this->refCwd.get(); } /// update the tab completion stuff void nConConServer::UpdateTabComplete() { // ... } /// perform a tab completion void nConConServer::DoTabCompletion() { // ... }
///----------------------------------------------------------------------------
/// 声明为Nebula2脚本支持类 nNebulaScriptModule(nConConServer, nconconserver, ”nroot”);
/// ConConServer开关 static void n_toggle(void* slf, nCmd* cmd); /// 执行控制台指令 static void n_exec(void* slf, nCmd* cmd);
/// Regist Commands void nNebulaScriptInitCmds(nconconserver) (nClass* cl) { cl->BeginCmds(); cl->AddCmd(”v_toggle_v”, ''TOGL'', n_toggle); cl->AddCmd(”v_exec_s”, ''EXEC'', n_exec); cl->EndCmds(); }
/// ToggleMode的脚本支持 static void n_toggle(void* slf, nCmd* cmd) { nConConServer* self = (nConConServer*) slf; self->ToggleMode(); }
/// ExecCommand的脚本支持 static void n_exec(void* slf, nCmd* cmd) { nConConServer* self = (nConConServer*) slf; const char* szCmdStr = cmd->In()->GetS(); self->ExecuteCommand(szCmdStr); }
///---------------------------------------------------------------------------- #pragma warning(pop)
其中ToggleMode()方法是切换到控制台模式的开关,已经加入了对脚本的支持,可以直接通过InputServer映射到一个按键上。
PollCmd()命令用于阻塞接受用户输入的指令。由于是以Windows控制台实现,所以只能以阻塞模式接受用户输入,在执行PollCmd()函数后应用程序会停止运行,直到用户在控制台中输入”-exit”指令,nConConServer才会把控制权释放掉。
下面给出nConConServer的使用事例代码:
/****************************************************************************/ /* Nebula2 - Tutorial 12 */ /* A Console Server for Console */ /* author: happykevins */ /****************************************************************************/
///---------------------------------------------------------------------------- /// +必要头文件
// nebula2 includes #include ”kernel/nkernelserver.h” #include ”script/ntclserver.h”
// ConConServer头文件 #include ”../NebulaUtils/nConConServer.h”
// Tutorial工具库:一些通用的宏定义 #include ”../NebulaUtils/nutildefs.h”
/// -必要头文件 ///----------------------------------------------------------------------------
///---------------------------------------------------------------------------- /// +链接库 #pragma comment(lib, ”wsock32.lib”) #pragma comment(lib, ”d_nkernel.lib”) #pragma comment(lib, ”d_nnebula.lib”) #pragma comment(lib, ”d_microtcl.lib”) /// -链接库 ///----------------------------------------------------------------------------
///---------------------------------------------------------------------------- /// +声明使用的Nebula2 Package&Module nNebulaUseModule(ntclserver); /// -声明使用的Nebula2 Package&Module ///---------------------------------------------------------------------------- nKernelServer* ks = NULL;
///---------------------------------------------------------------------------- /// +初始化环境,创建需要的Server /// bool InitApp() { /// 创建KernelServer ks = n_new(nKernelServer);
///---------------------------------------------------------------------------- /// +向KernelServer中添加Package&Module nNebulaAddModule(ntclserver); /// +向KernelServer中添加Package&Module ///---------------------------------------------------------------------------- ks->New(”ntclserver”, ”/sys/servers/script”);
return true; } /// /// -初始化环境,创建需要的Server ///----------------------------------------------------------------------------
///---------------------------------------------------------------------------- /// +退出程序,清理资源 /// bool CloseApp() { /// 销毁KernelServer n_delete(ks);
return true; } /// /// -退出程序,清理资源 ///----------------------------------------------------------------------------
///---------------------------------------------------------------------------- /// +Application int main(int argc, const char** argv) { /// 初始化Application if ( !InitApp() ) { n_error(”程序初始化失败! ”); return 0; } /// ConConServer nConConServer console;
/// 切出ConConServer console.ToggleMode(); /// 轮训控制台指令,(阻塞模式) console.PollCmd();
/// 释放资源 if ( !CloseApp() ) { n_error(”释放资源失败! ”); return 0; }
return 0; } /// -Application ///----------------------------------------------------------------------------
--The End--
|