使用AAUTO语言开发的云桌面登录客户端
AAUTO是一个国产小众语言,和lua算是近亲,官方网站 www.aau.cn。
使用aauto的优点我认为对于我来说最主要的有以下两点:
1.无需臃肿的框架类似.NET FRAMEWORK、Adobe AIR等便可开发出小巧而实用的windows程序
2.支持HTMLLAYOUT,对于原来熟悉html+css的web开发者来说是个福音,降低了学习成本
废话不多说了,下面开始介绍下我使用aauto这个短小精悍的语言所开发的访问使用CloudStack所创建的虚拟机的云桌面访问客户端。
界面演示

实现功能
该客户端在输入用户名密码验证登录成功后
1.屏蔽了windows,ALT+F4 以禁止用户返回原生桌面或关闭当前程序(其实屏蔽ALT+F4)
架构详解
下图是该项目的全部文件目录树。

该客户端仅有一个主窗体文件main.aau,界面演示图中的效果是有layout中的index.html实现。sys.ini中配置保存的用户名及登录验证服务网址.
代码详解
main.aau中核心代码如下:
import win.ui;
import win.ui.menu;
import win.ui.atom;
import win.timer;
import inet.whttp;
import web.layout;
import web.layout.behavior.windowCommand;
import fsys.ini;
import sys;
import win.reg;
import key;
import crypt.des;
import crypt.bin;
_ver = "1.1.0 build 20141017"
//常量定义
_APP_NAME="clouddesktop"
mainForm = win.form(text="云桌面登录客户端";right=0;bottom=0;border="none";max=false;min=false;maxmize=1)
var debug =(_STUDIO_INVOKED ? true:false)
var des = crypt.des();
des.setPassword("huiyou");
if(!debug){
win.setTopmost(mainForm.hwnd)
}
/*------------------ 公用函数 -------------------*/
function decrypt(str){
var rtn = crypt.bin.decodeBase64(str);
return des.decrypt(rtn);
}
function encrypt(str) {
var rtn = des.encrypt(str);
return crypt.bin.encodeBase64(rtn);
}
/*------------------ 公用函数 END -------------------*/
//win.setTopmost(mainForm.hwnd)
var atom,hwnd/*冲突窗口的句柄,该函数会自动激活此窗口*/ = mainForm.atom("BB84EAAE-004C-4AF7-8087-98550285C32E");
if(!atom){
/*为窗口设置原子值可以避免一个程序重复运行多个实例*/
win.quitMessage();
return;
}
var ini = fsys.ini("/sys.ini")
//1.禁用任务管理器
var reg = win.reg("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\System")
reg.setDwValue("DisableTaskMgr",1)
var binpath = io._exepath;
var displayname = "云桌面客户端"
var description = "云桌面客户端"
/*自动启动*/
reg = win.reg("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run")
reg.setSzValue(_APP_NAME, binpath)
//reg.delKeyTree("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run\clouddesktop")
//禁用运行
reg = win.reg("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer")
reg.setDwValue("DisallowRun",1)
wbLayout = web.layout(mainForm)
//禁止窗体绘制默认背景,避免不必要的闪烁
mainForm.onEraseBkgnd = function(hwnd,message,wParam,lParam){
return 0;
}
wbLayout.go("/layout/index.html");
//----------------屏蔽按键
import key.hook;
hk = key.hook()
hk.proc = function(msg,vkcode,scancode,injected,flags,timeStamp,extraInfo){
if( injected ) return;
var kn = key.getName( vkcode );
select(msg) {
case 0x100/*_WM_KEYDOWN*/ ,0x104/*_WM_SYSKEYDOWN*/{
if(kn=="LWIN" || kn=="RWIN"
|| ((flags & 0x20/*_LLKHF_ALTDOWN*/)!=0 && kn=="F4")
)
{
return true
}
elseif( kn == "0" && key.getStateX("CTRL")){
reg.close();win.quitMessage();
}
}
}
}
//----------------屏蔽按键END
timer=win.timer( mainForm);
quit = function(){hk.close();timer.disable();reg.close();win.quitMessage();}
_section_AutoLogin="autologin"
var isAutoLogin=false;
if(ini.readKeys(_section_AutoLogin)){
sec = ini.getSection(_section_AutoLogin)
rememberUserName=sec.rememberUserName//记住用户名
//autoLogin=sec.autoLogin
}
if(rememberUserName=="1"){
wbLayout.getEle("cbxRemember").value=true
wbLayout.getEle("username").value= decrypt(sec.userName)
}
/*
if(autoLogin=="1"){
isAutoLogin=true;
wbLayout.getEle("userpass").value = sec.userPass;
wbLayout.getEle("cbxAutoLogin").value = true
wbLayout.getEle("btnSmt").click()
}
*/
var http = inet.whttp();
//请求服务baseurl,可用用户名
var serverBaseUrl=ini.read("server","url","http://140.28.22.122:8080/admin/getvm");
if(false == string.startWith(serverBaseUrl,"http://")){
serverBaseUrl = decrypt(serverBaseUrl);
}
wbLayout.onButtonClick = function (ltTarget,ltEle,reason,behaviorParams) {
if( ltEle.id == "btnSmt"){
var username=wbLayout.getEle("username").value;
var password=wbLayout.getEle("password").value;
rememberUserName=wbLayout.getEle("cbxRemember").value;
//autoLogin=wbLayout.getEle("cbxAutoLogin").value;
if(username=="用户名")username="t1"
if(!#password || password=="密码")password="t1"
if(!#username){mainForm.msgbox("请输入用户名")return;}
if(!#password){mainForm.msgbox("请输入密码")return;}
var url=string.concat(serverBaseUrl,"?command=getsvm&username=",username,"&password=",password);
var str;
try{str = http.get(url)}
catch(e){mainForm.msgbox("无法连接到远程服务,请检查远程服务是否可访问");return;}
if( null ==str || !#str){mainForm.msgbox("登录失败,请检查网络连接情况并稍后再试");return}
if(str=="1"){mainForm.msgbox("登录失败,请检查用户名密码是否正确");return}
//------------ 保存用户名密码等到配置文件
/*保存用户名密码等到配置文件{{*/
ini.write(_section_AutoLogin,"rememberUserName",rememberUserName?1:0)
//ini.write(_section_AutoLogin,"autoLogin",autoLogin?1:0)
if(rememberUserName){
var sUserName = des.encrypt(username);
ini.write(_section_AutoLogin,"userName",crypt.bin.encodeBase64(sUserName));
}
/*
if(autoLogin){
ini.write(_section_AutoLogin,"userPass",password)
}
*/
/*}}*/
//------------ 保存用户名密码等到配置文件 END
if(isAutoLogin){
ltEle.value="登陆中...";
}
var arr= string.split(str,'$')
userid=arr[1];
var serverip=arr[2];
var port = arr[3];
var vmUserName=arr[4];
var vmpwd = arr[5];
var desktopUrl=arr[6];
//-------------- 远程连接start
import com.lite;
rdpClient = com.lite("MsTscAx.dll").createEmbed(mainForm,"{7cacbd7b-0d99-468f-ac33-22e495c0afe5}")
msTscAx = rdpClient._object;//获取控件对象
//响应远程桌面事件
rdpClient.OnDisconnected = function(discReason){
//mainForm.msgbox(discReason)
select (discReason) {
case 1,2{
quit();
if(!debug)sys.shutdown();
}
}
}
//设置远程登录参数
msTscAx.Server = serverip;
msTscAx.UserName = vmUserName;
msTscAx.AdvancedSettings2.ClearTextPassword = vmpwd;
msTscAx.AdvancedSettings2.RDPPort = port; //端口
msTscAx.AdvancedSettings2.RedirectPrinters = true; //共享打印
msTscAx.AdvancedSettings2.RedirectDrives = true; //允许共享磁盘
msTscAx.AdvancedSettings2.RedirectDynamicDrives =true;
msTscAx.AdvancedSettings2.SmartSizing = true; //自动调整大小
msTscAx.AdvancedSettings2.DisplayConnectionBar=true;
msTscAx.AdvancedSettings2.DisableCtrlAltDel = 1;
msTscAx.AdvancedSettings2.EnableWindowsKey = 0;
//msTscAx.AdvancedSettings.Compress=1;
//msTscAx.AdvancedSettings.BitmapPeristence = 1;// 将位图缓存到磁盘
//msTscAx.SecuredSettings2.StartProgram = "c:\browser.exe "++ desktopUrl;
msTscAx.FullScreen = false;//是否全
msTscAx.FullScreenTitle = mainForm.text;//全屏标题
msTscAx.ColorDepth = 32;//32位颜色
msTscAx.ConnectingText = "欢迎使用云桌面,正在连接,请稍候......"
msTscAx.Connect(); //连接
//-------------- 远程连接 END
//加载计时器
timer.enable();
timer.setInterval(120000)//2分钟发送一次heartbeat
}
}
var elePwd = wbLayout.getEle("userpass")
elePwd.onKeyUp = function( ltTarget,ltOwner,keyCode, altState, ltKeyParams ) {
if(ltOwner.id == "userpass" && keyCode==13){wbLayout.getEle("btnSmt").click()}
}
elePwd.attachEventHandler()
//发送heartbeat
timer.onTimer = function(hwnd,msg,id,tick){
if(!userid || !#userid) return;
var url=string.concat(serverBaseUrl,"?command=heartbeat&userid=",userid);
http.get(url);
}
mainForm.onClose = function(hwnd,message,wParam,lParam){
return false;
if(#userid){
var url=string.concat(serverBaseUrl,"?command=logout&userid=",userid);
http.get(url);
http.close()
}
process.kill("mstsc.exe")
quit();
collectgarbage("collect");//内存回收,确保完全退出
if(!debug)sys.shutdown();
}
//响应窗口事件
mainForm.wndproc = function(hwnd, message,wparam,lparam){
select(message) {//判断消息类型
case 0x10/*_WM_CLOSE*/{
return true;//阻止关闭
};
case 0x282
{
import winex;
var winHwnd,ch,tid,pid = winex.findExists("<云桌面登录客户端>","","<AAU_FORM[\S+]>","<ATL:\w+>")
if(ch!=null){
rdpClient._host.doObjectVerb( -5)
}
};
}
}//endproc
mainForm.show()
//import cloudDesktop.common;
//cloudDesktop.common.checkUpdate();
win.loopMessage();
sys.ini中内容
[autologin]
userName=7JB75wW03kA=
rememberUserName=1
[server]
url=http://xxxxxx/admin/getvm
使用AAUTO语言开发的云桌面登录客户端的更多相关文章
- 基于Hadoop开发网络云盘系统客户端界面设计初稿
基于Hadoop开发网络云盘系统客户端界面设计初稿 前言: 本文是<基于Hadoop开发网络云盘系统架构设计方案>的第二篇,针对界面原型原本考虑有两个方案:1.类windows模式,文件夹 ...
- 开源前夕先给大家欣赏一下我用C语言开发的云贴吧 网站自动兼容-移动、手机、PC自动兼容云贴吧
开源前夕先给大家欣赏一下我用C语言开发的移动.手机.PC自动兼容云贴吧 - 涨知识属马超懒散,属虎太倔强.十二生肖全了!-转自云寻觅贴吧 转: 涨知识属马超懒散,属虎太倔强.十二生肖全了! -转自云寻 ...
- 开源前夕先给大家赞赏一下我用C语言开发的云贴吧 站点自己主动兼容-移动、手机、PC自己主动兼容云贴吧
开源前夕先给大家赞赏一下我用C语言开发的移动.手机.PC自己主动兼容云贴吧 - 涨知识属马超懒散,属虎太倔强.十二生肖全了!-转自云寻觅贴吧 转: 涨知识属马超懒散,属虎太倔强.十二生肖全了! -转自 ...
- OpenStack虚拟云桌面在携程呼叫中心的应用
编者:本文为刘科在第六期[携程技术微分享]中的分享内容.在携程技术中心(微信号ctriptech)微信后台回复[云桌面],可加入微信交流群,和关注云桌面的小伙伴一起玩耍~ 刘科,携程系统研发云平台桌面 ...
- 黄聪:远程序桌面登录的.NET(C#)开发
MSTSCLib.dll和MsTscAxWrapper.dll下载:LibDll.rar 远程序桌面登录的.NET开发,可以使用MSTSCLib.dll和MsTscAxWrapper.dll两个转换过 ...
- 【Linux 操作系统】阿里云服务器 操作实战 部署C语言开发环境(vim配置,gcc) 部署J2EE网站(jdk,tomcat)
. 作者 :万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/18964835 . 博客总结 : 设置SecureCRT ...
- 阿里云服务器 操作实战 部署C语言开发环境(vim配置,gcc) 部署J2EE网站(jdk,tomcat)
. 作者 :万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/18964835 . 博客总结 : 设置SecureCRT ...
- Go语言开发环境配置
一.我为什么要学习go语言 当今已经是移动和云计算时代,Go出现在了工业向云计算转型的时刻,简单.高效.内 置并发原语和现代的标准库让Go语言尤其适合云端软件开发(毕竟它就是为此而设计的).到2014 ...
- (转载)Go语言开发环境配置
一.我为什么要学习go语言 当今已经是移动和云计算时代,Go出现在了工业向云计算转型的时刻,简单.高效.内 置并发原语和现代的标准库让Go语言尤其适合云端软件开发(毕竟它就是为此而设计的).到2014 ...
随机推荐
- c#笔记整理 关于继承与多态等
[ 塔 · 第 二 条 约 定 ] c#面向对象基础 整理private.protected.public.abstract等的异同 public 公有访问.不受任何限制. private 私有访问. ...
- 对编码内容多次UrlDecode
对编码内容多次UrlDecode,并不会影响最终结果. 尝试阅读了微软的源代码,不过不容易读懂. 网址:https://referencesource.microsoft.com/#System/ne ...
- iOS- 利用UIImageView自己整了个不会说话的汤姆猫
1.实现思路 先说说我实现它的主要思路,很简单,主要利用UIImageView连续动画播放,和按钮的点击事件,就可以完成了这么一个简单的不会说话的汤姆猫. 2.实现细节 2.1.加载本地字典里保存的本 ...
- Python实现FTP服务功能
本文从以下三个方面, 阐述Python如何搭建FTP服务器 一. Python搭建FTP服务器 二. FTP函数释义 三. 查看目录结构 四. 上传下载程序 一. Python搭建FTP服务器 1. ...
- 导入导出SQL数据库
在需要导出的数据库名上右键,选择转储SQL-数据和结构 在需要导入的连接中新建相同名称的数据库,右键选择运行SQL文件,即可将数据库数据转储到新的数据库中
- 为什么 MongoDB (索引)使用B-树而 Mysql 使用 B+树
B-树由来 定义:B-树是一类树,包括B-树.B+树.B*树等,是一棵自平衡的搜索树,它类似普通的平衡二叉树,不同的一点是B-树允许每个节点有更多的子节点.B-树是专门为外部存储器设计的,如磁盘,它对 ...
- hdu3625-Rooms
题目 有\(n\)个房间,\(n\)个钥匙,每个钥匙随机出现在一个房间里,一个房间里有且仅有一个钥匙.我们现在手上没有钥匙,但我们要搜索所有的房间,所以我们有\(k\)次机会把一个房间炸开.一号房间里 ...
- Devc++编译系统分配给int多少字节
我看的是<C语言程序设计>..谭浩强的PDF版 里面只讲了VC和TC 的,没有Devc++的..(我的是5.10版) 还有这是什么意思? 经过查阅我进行了这样的测试: 得到了这样的结果: ...
- Tensorflow框架初尝试————搭建卷积神经网络做MNIST问题
Tensorflow是一个非常好用的deep learning框架 学完了cs231n,大概就可以写一个CNN做一下MNIST了 tensorflow具体原理可以参见它的官方文档 然后CNN的原理可以 ...
- POJ2728:Desert King——题解
http://poj.org/problem?id=2728 题目大意:求一棵生成树使得路费用和/路长之和最小(路的费用是两端点的高度差) 最小比率生成树. 我们还是01分数规划的思想将边权变为路费用 ...