aardio - 为了便于发布调试,升级改造publish.aardio

文章介绍了一个在Aardio编程环境中遇到的问题,即调试和发布运行时因默认目录不同导致的效果差异。作者提出了两种解决方案,并分享了一段代码,用于自动化处理发布后将EXE复制到主目录并运行。这段代码可以自定义是否复制文件和运行发布后的EXE,简化工作流程。
摘要由CSDN通过智能技术生成

经常遇到这么一个问题:

调试运行时,程序默认目录为程序主目录。

发布后运行时,因为发布文件在dist目录,所以默认目录在dist目录。

这就导致可能会因为配置文件或其他依赖文件不同,导致调试运行和发布后运行效果不一样。

解决办法:

1、将依赖文件在主目录和dist目录都复制一份,保持相同。

2、将发布后的dist目录中的exe复制到主目录运行。

有时候觉得较麻烦。

干脆升级改造一下publish.aardio,增加以下功能:

1、发布完成后,可以自动复制exe到主目录一份,便于测试。

2、发布完成后,可以自动运行发布的exe或复制的exe(如果选择了复制功能)。

  代码仅供有相同需求的朋友参考,不建议直接修改使用。同时,aardio升级会恢复该文件。

import fsys;
import config;
import process;
import ide;
import win.ui;
/*DSG{{*/
var winform = win.form(text="aardio-  已生成EXE文件";right=545;bottom=277;max=false;parent=...)
winform.add(
btnClose={cls="button";text="关闭(ESC)";left=410;top=230;right=512;bottom=260;db=1;dr=1;z=2};
btnEvb={cls="button";text="转换为独立 EXE";left=290;top=230;right=400;bottom=260;db=1;dr=1;z=12};
btnExplorer={cls="button";text="打开发布目录(Enter)";left=30;top=230;right=160;bottom=260;db=1;dr=1;z=1};
btnRun={cls="button";text="运行EXE文件(F5)";left=350;top=190;right=510;bottom=220;db=1;dr=1;z=3};
buttonMakeUpdater={cls="button";text="制作升级包";left=170;top=230;right=280;bottom=260;db=1;dr=1;z=11};
chkBuildNumInc={cls="checkbox";text="版本号自增";left=270;top=110;right=370;bottom=128;ah=1;aw=1;z=8};
chkCopy={cls="checkbox";text="复制文件到工程目录";left=380;top=110;right=530;bottom=128;ah=1;aw=1;z=13};
chkLostFocusClose={cls="checkbox";text="失去焦点自动关闭";left=30;top=110;right=168;bottom=129;ah=1;aw=1;checked=1;z=6};
chkRun={cls="checkbox";text="编译后立即运行";left=30;top=140;right=160;bottom=158;ah=1;aw=1;z=14};
chkUpxCompress={cls="checkbox";text="UPX压缩";left=180;top=110;right=260;bottom=130;ah=1;aw=1;z=7};
editCmdLine={cls="edit";left=100;top=190;right=347;bottom=218;db=1;dl=1;dr=1;edge=1;z=9};
editPublishPath={cls="edit";left=33;top=71;right=513;bottom=100;dl=1;dr=1;edge=1;readonly=1;z=4};
lbCmd={cls="static";text="启动参数:";left=30;top=190;right=100;bottom=216;center=1;db=1;dl=1;font=LOGFONT(h=-14);transparent=1;z=10};
lbTitle={cls="syslink";left=33;top=9;right=519;bottom=65;ah=1;dl=1;dr=1;dt=1;z=5}
)
/*}}*/

winform.lbTitle.text = '<a href="https://api.aardio.com/v10/pages/pub-help">
解除误报教程:基于服务端白名单进行云查杀的安全软件(或某些软件在后台运行的安全模块)会误报未知EXE、
或阻止您的软件启动(可能无任何提示),也有可能您生成EXE时一切正常,但发布给别人使用一段时间后被误报或拦截。</a>'
winform.lbTitle.onHyperlinkClick = function(nmSysLink,url,id){ 
    process.openUrl(url);	
}
 
win.setOwner(winform.hwnd,ide.getMainHwnd()); //避免窗口跑到IDE后面
win.setForeground(winform.hwnd);
 
/*abortDialog{{*/
abortDialog = function(errCode){ 
var frmBuildWarning = ..win.form( text="aardio生成EXE失败 错误代码:"+errCode;bottom=169;parent=ide.getMainHwnd();right=496;border="dialog frame";max=false;exmode="toolwindow";mode="popup" )
frmBuildWarning.add( 
btnHelp={ bottom=159;text="安全认证教程";left=117;top=124;z=2;right=237;cls="button" };
static={ bottom=127;right=488;left=12;top=23;transparent=1;z=1;text="生成EXE失败,
部分安全软件会阻止生成未知EXE,或对未知EXE错误报警。
请关闭文件监控类软件再试!
EXE文件生成以后,建议及时提交到主流安全厂商云查杀平台通过安全认证,
即可避免发生误报现象。";cls="static" };
btnBuild={ bottom=159;text="重新生成";left=247;top=124;z=3;right=367;cls="button" };
btnExt={ bottom=159;text="退出";left=377;top=124;z=4;right=478;cls="button" }
)
 
 
import process;
frmBuildWarning.btnHelp.oncommand = function(id,event){
	process.openUrl("https://api.aardio.com/v10/pages/pub-help") 
}
 
import ide;
frmBuildWarning.btnBuild.oncommand = function(id,event){ 
	frmBuildWarning.endModal()
	::PostMessage( ide.getMainHwnd(),0x111/*_WM_COMMAND*/, 0x8317/*_IDE_ID_BUILD_PUBLISH*/,0);
}
 
 
frmBuildWarning.btnExt.oncommand = function(id,event){ 
	frmBuildWarning.endModal() 
}
 
frmBuildWarning.doModal()
}
/*}}*/ 
 
if( ide.projectIsOpened() ){
	fsys.delete( ide.getPublishPath() )
}
winform.enableDpiScaling();
winform.chkLostFocusClose.checked = config.publish.chkLostFocusClose;
winform.chkUpxCompress.checked = config.publish.chkUpxCompress;
winform.chkCopy.checked = config.publish.chkCopy;
winform.chkRun.checked = config.publish.chkRun;
winform.chkBuildNumInc.checked = ( config.publish.chkBuildNumInc === null ) 
	? true : config.publish.chkBuildNumInc;
 
var publishObj = ide.getPublishObjPath();
var objDataFile;
try{
	objDataFile = ::Kernel32.LoadLibraryExW(publishObj, ,2/*_LOAD_LIBRARY_AS_DATAFILE*/)
}
catch(e){ 
	abortDialog("30001"); 
}
if( !objDataFile ){
	abortDialog("30002"); 
	return;
}
 
import fsys.res; 
var resLibs = {};
fsys.res.enum(
	function(module,resType,resName){
		table.push(resLibs,..string.lower(resName) ) 
		return true;
	},"LIB",topointer(objDataFile)
) 
::Kernel32.FreeLibrary(objDataFile);
 
/*Manifest{{*/
var projectPath = ide.getProjectPath();
var projectFileName = io.splitpath(projectPath).name;
var manifestPath = ..fsys.joinpath( ide.getProjectDir(),".build\" + projectFileName + ".Manifest.xml" );
var manifestData = ..string.load( manifestPath ); 
if( !manifestData ){
	manifestPath = ..fsys.joinpath( ide.getProjectDir(),".build\Manifest.xml" ); //兼容旧版
	manifestData = ..string.load( manifestPath ); 
}
if( (!manifestData) || ( ! ..string.find(manifestData,"8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a" ) ) 
	|| ( ! ..string.find(manifestData,"@</dpiAwareness>" ) )  ){
	import string.template;
	manifestTemplate = string.template();
	manifestTemplate.template = /***
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<assembly 
xmlns="urn:schemas-microsoft-com:asm.v1" 
manifestVersion="1.0">
<assemblyIdentity 
    processorArchitecture="x86" 
    version="5.1.0.0"
    type="win32"
    name="${EXENAME}"/>
    <description>${PROJENAME}</description>
    <dependency>
    <dependentAssembly>
    <assemblyIdentity
        type="win32"
        name="Microsoft.Windows.Common-Controls"
        version="6.0.0.0"
        publicKeyToken="6595b64144ccf1df"
        language="*"
        processorArchitecture="x86"/>
    </dependentAssembly>
    </dependency>
    <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
      <application> 
          <!--Windows Vista -->
          <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
          <!--Windows 7 -->
          <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
		  <!--Windows 8 -->  
		  <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
		  <!-- Windows 8.1 -->             
          <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>   
          <!-- Windows 10, Windows 11 -->              
          <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>    
      </application>
    </compatibility>
    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    	<security>
        	<requestedPrivileges>
			<!-- 
				可任选以下配置之一指定一个进程权限:
				<requestedExecutionLevel level="asInvoker" uiAccess="false" />
				<requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> 
				<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
				
				requireAdministrator 为管理员权限,
				highestAvailable 为可以获取到的最高权限,
				asInvoker 为默认值,即调用进程当前权限,一般不需要显式指定,指定后会禁用虚拟化。
				
				虚拟化指Vista以后系统禁止写 Program File目录,启用虚拟化则重定向到%localappdata%\VirtualStore目录,
				而注册表 HKEY_LOCAL_MACHINE\Software 则重定向到HKEY_CURRENT_USER\Software\Classes\VirtualStore\MACHINE\Software
			--> 
        	</requestedPrivileges>
    	</security>
	</trustInfo>
	<asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
		<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
				<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
				<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
		</asmv3:windowsSettings>
	</asmv3:application>
</assembly>
***/ 
	manifestData = manifestTemplate.format(
		EXENAME = ide.getPublishName();
		PROJENAME = ide.getProjectProperty("name")
	);
	
	var manifestPath = ..io.joinpath( ide.getProjectDir(),".build\" + projectFileName + ".Manifest.xml" );
	string.save(manifestPath,manifestData ) ;
}
 
var fileMain = io.open(ide.getProjectMainFile(),"rb"); 
if( fileMain ){
	var tag = fileMain.read(9);
	if( tag == "//RUNAS//" ){
		manifestData = ..string.replace(manifestData,"\<requestedPrivileges\>.+?\<\/requestedPrivileges\>"
			,"<requestedPrivileges><requestedExecutionLevel level=""requireAdministrator"" uiAccess=""false"" /> </requestedPrivileges>")
		
		var manifestPath = ..io.joinpath( ide.getProjectDir(),".build\" + projectFileName + ".Manifest.xml" );
		string.save(manifestPath,manifestData ) ;
	}
	fileMain.close();
}
var resFile = fsys.res.open( publishObj )
resFile.update(24,1,manifestData,0 ) 
resFile.close();
/*}}*/
 
var publishFile = ide.getPublishPath();
io.rename(publishObj,publishFile)
if(!io.exist(publishFile)){ 
	abortDialog("30003");
	return;
}
var publisDir = ide.getPublisDir();
for(k,resName in resLibs){
	var customBuild = fiber.create(
		function(resName){
			var libPath,libDir = io.libpath(resName);
			if(libDir && libPath && ..string.endWith(libPath,"_.aardio",true) ){
				var builder = fsys.joinpath(libDir,".build\main.aardio");
				if( io.exist( builder ) ){
					var tHnd,tId = thread.create(builder)
					if(tHnd){
						::User32.AttachThreadInput( ..thread.getId(),tId,true); 
						thread.waitOne(tHnd);
						raw.closehandle(tHnd);
					}
				}
			}	
		}, ide.getProjectDir() /*使用工程目录下的用户库*/
	)
	fiber.resume (customBuild,resName);	
}
var projectPath = ide.getProjectPath();
var projectFileName = io.splitpath(projectPath).name;
var builder = fsys.joinpath(ide.getProjectDir(),".build\" + projectFileName + ".main.aardio");
if( io.exist( builder ) ){  
	var tHnd,tId  = thread.create(builder)
	if(tHnd){
		::User32.AttachThreadInput( ..thread.getId(),tId,true);
		thread.waitOne(tHnd);
		raw.closehandle(tHnd);
	}
}
else { 
	var code =/*
//此触发器在生成EXE以后执行
import ide;
import fsys; 
//获取生成的EXE文件路径
var publishFile = ide.getPublishPath();
*/
	var builder = fsys.joinpath(ide.getProjectDir(),".build\" + projectFileName + ".main.aardio");
	..string.save(builder,code)  
}
/*自增版本号{{*/
if( winform.chkBuildNumInc.checked ){
	import fsys.version;
	
	var fileVersion = ide.getProjectProperty("FileVersion"); 
	if( fileVersion ){
		var verInfo = fsys.version(fileVersion);
		
		verInfo.revision++;
		if( verInfo.revision >=  1000 ){
			verInfo.revision = 0;
			verInfo.build++;
		}
		if( verInfo.build >=  1000 ){
			verInfo.build = 0;
			verInfo.minor++;
		}
		if( verInfo.minor >=  100 ){
			verInfo.minor = 0;
			verInfo.major++;
		}
		ide.setProjectProperty("FileVersion",tostring(verInfo));
	}
	
	var productVersion = ide.getProjectProperty("ProductVersion");
	if(productVersion){
		var verInfo = fsys.version(productVersion);
		
		verInfo.revision++;
		if( verInfo.revision >=  1000 ){
			verInfo.revision = 0;
			verInfo.build++;
		}
		if( verInfo.build >=  1000 ){
			verInfo.build = 0;
			verInfo.minor++;
		}
		if( verInfo.minor >=  100 ){
			verInfo.minor = 0;
			verInfo.major++;
		}
		ide.setProjectProperty("ProductVersion",tostring(verInfo));
	}
} 
winform.editPublishPath.text = ide.getPublishPath();
winform.show();
/*}}*/
upxCompress = function(){
	if( winform.chkUpxCompress.checked ){
		winform.text = "aardio-  正在使用UPX压缩EXE文件"
		winform.btnRun.disabled = true;
		thread.invokeAndWait(
			function(publishFile){
				import ide.upx;
				ide.upx.compress(publishFile);
			},ide.getPublishPath()
		) 
		winform.btnRun.disabled = false;
		winform.text = "aardio-  已生成EXE文件"
	}
}
upxCompress();
winform.chkUpxCompress.oncommand = function(id,event){
	upxCompress();
}
winform.btnClose.oncommand = function(id,event){
	winform.close()
}
var cmdStorePath = ..fsys.joinpath( ide.getProjectDir(),".build\cmdline.txt" );
winform.editCmdLine.text = string.load(cmdStorePath) : "";
winform.btnRun.oncommand = function(id,event){
	winform.btnRun.text = "请稍候..."
	winform.btnRun.disabled = true;
	process.execute(winform.editPublishPath.text,winform.editCmdLine.text);
	if(#winform.editCmdLine.text){
		string.save(cmdStorePath,winform.editCmdLine.text)
	}
	winform.close();
}
 
winform.btnExplorer.oncommand = function(id,event){
	winform.btnExplorer.text = "请稍候..."
	winform.btnExplorer.disabled = true;
	process.explore_select( winform.editPublishPath.text )
	winform.close();
}
winform.wndproc = function(hwnd,message,wParam,lParam){
	select( message ) { 
		case 0x1C/*_WM_ACTIVATEAPP*/ {
			if(!wParam){
				if( winform.chkLostFocusClose.checked and !hold){
					winform.close();
				}
			}
		} 
		case 0x100/*_WM_KEYDOWN*/{
			if( wParam = 0x74/*_VK_F5*/ ){
				winform.btnRun.oncommand();
			}
		}
	} 
}
winform.onClose = function(hwnd,message,wParam,lParam){
    config.publish.chkLostFocusClose = winform.chkLostFocusClose.checked
    config.publish.chkUpxCompress = winform.chkUpxCompress.checked;
    config.publish.chkCopy = winform.chkCopy.checked;
    config.publish.chkRun = winform.chkRun.checked;
    config.publish.chkBuildNumInc = winform.chkBuildNumInc.checked;
}
winform.buttonMakeUpdater.oncommand = function(id,event){
    winform.close()
    loadcodex("~\tools\3) 编码\1) maker.aardio")
}
winform.btnEvb.oncommand = function(id,event){
	winform.close();
	loadcodex("~\tools\1) 开发环境\evb.aardio")
}
winform.chkCopy.oncommand = function(id,event){
	if winform.chkCopy.checked {
		fsys.copy(publishFile, io.splitpath(projectPath).dir+ io.splitpath(publishFile).file)
	}
}
win.setActive(winform.hwnd);
if winform.chkCopy.checked {
	var dstfile = io.splitpath(projectPath).dir+ io.splitpath(publishFile).file;
	fsys.copy(publishFile, dstfile);
	if winform.chkRun.checked {
		hold = true;
		process.executeWait(dstfile,winform.editCmdLine.text);
		winform.close();
	}
} else {
	if winform.chkRun.checked {
		hold = true;
		process.executeWait(winform.editPublishPath.text,winform.editCmdLine.text);
		winform.close();
	}
}
win.loopMessage();

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卢光庆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值