//temp 自删进程 import fsys; import process; import thread.event; import fsys.mmap; import fsys.fileInfo; import process.batch; namespace process.temp; run = function(main){ if( _STUDIO_INVOKED ) error("生成 EXE 文件才能创建临时进程!"); if( type(main) != type.function )error("参数 @1 必须是回调函数",2); var appId; var isTempProcess = ..fsys.fileInfo.same( ..fsys.getParentDir( ..io.tmpname()), ..fsys.getParentDir( ..io._exedir) ); if( isTempProcess ){ var parentId = ..process.getParentId(); if(!parentId) return false,"自删进程获取父进程 ID 失败"; var prcsParent = ..process(parentId); var parentPath = prcsParent.getPath(); prcsParent.free(); if(!parentPath) return false,"自删进程获取父进程路径失败"; var appid = ..fsys.fileInfo(parentPath).id; if(!appid) return false,"自删进程获取父进程唯一标识失败"; appId = "aardio.process.temp@" + appid; } else{ var appid = ..fsys.fileInfo(..io._exepath).id; if(!appid) return false,"自删进程获取进程唯一标识失败"; appId = "aardio.process.temp@" + appid; } var mmapStartTemp = ..fsys.mmap(,appId+".tempProcessStartInfo",1024 ); var evtStartTemp = ..thread.event( appId+".boot" ); if( !isTempProcess ){ if( evtStartTemp.conflict ) return false,"重复创建自删进程";; var tmpUnisDir = ..io.tmpname(); tmpUnistPath = ..io.joinpath(tmpUnisDir,..io._exefile); ..fsys.copy( ..io._exepath, tmpUnistPath ); mmapStartTemp.writeTable({ pidParent = ..process.getId(); argv=_ARGV; srcExe = ..io._exepath; srcDir = ..io._exedir } ) ; var prcs,err = ..process( tmpUnistPath ,_CMDLINE,{ waitInputTimeout = 0;creationFlag = 0x8/*_DETACHED_PROCESS*/; } ); if(!prcs) error(..string.concat("创建临时进程失败 ",err),2); prcs.free(); evtStartTemp.wait();//等待临时进程启动 return ; }else { self.singletonTemp = ..thread.event(appId+".singletonTemp"); if( singletonTemp.conflict ) { return false,"重复启动自删进程",appId+".singletonTemp"; } } var startInfo = mmapStartTemp.readTable(); var prcsParent = startInfo.pidParent ? ..process(startInfo.pidParent); //再次确认启动父进程是否正确 if( ..process.getParentId() != startInfo.pidParent ) { return false; } evtStartTemp.set();//通知父进程自己已打开 if( prcsParent ){ prcsParent.wait(); //等待父进程关闭 prcsParent.free(); //释放父进程句柄 sleep(10); //等待进程资源彻底释放 } ..subscribe("beforeUnload",function(){ ..process.batch.execute(` @echo off :loop del /q "" if exist "" goto loop :loop rd /s /q "" if exist "" goto loop del %0 `) } ); ..fsys.setCurDir(startInfo.srcDir); var ok,err = ..fiber.resume ( ..fiber.create(main,startInfo.srcDir/*启动目录设为应用程序根目录*/) ,startInfo.srcExe, startInfo.argv ); if(!ok) errput(err); return true; } create = function(name,main){ return run(main); } /**intellisense() process.temp = 创建可删除 EXE 文件自身的临时进程。\n可用于卸载更新等辅助程序。\n\n同一路径同一文件自动阻止重复启动自删进程。\n\nEXE 文件要通过 Defender 检测才能释放到 temp 目录下以创建临时进程。\n开发时生成的 EXE 如果尚未通过检测,建议在开发目录下测试相关功能。\n\n如果只是单纯需要在退出后删除运行时占用的文件。\n可以改用 process.batch.execute 调用批处理实现。\n可以避免上述问题。 process.temp.run( = 创建可删除EXE文件自身的临时进程\n注意同一EXE文件,并且是同一文件名,同一时间只能运行一个实例,\n启动多个实例会忽略不执行并返回false,\n此函数执行成功返回true process.temp.run( 启动应用程序的函数 ) = @.run( \n function( exePath,argv ){\n io.remove(exePath); \n __/*exePath为原EXE文件,可如上直接删除\n当前目录,应用程序目录已设置为exePath的父目录,一般也是你的软件所在目录\n自删进程会保持"/"指向的路径不变,启动原EXE的命令行参数不变*/\n io.print( "原EXE文件所在目录:",io.fullpath("/") );\n io.print( "自删进程EXE文件所在目录:",io.fullpath("~/") );\n }\n) end intellisense**/