//app 执行更新程序 import thread.command; import JSON; namespace fsys.update; class app { ctor(srcDir,dstDir,reusable,removable){ this = ..thread.command(); this[["apply"]] = function(){ if(removable === null){removable = true;} ..thread.invoke( apply ,this._form.hwnd,srcDir,dstDir,reusable,removable ); }; var updateInfo = ..string.load( ..io.joinpath(srcDir,"update-info") ); if(updateInfo){ this[["updateInfo"]] = ..JSON.tryParse(updateInfo); }; }; } namespace app{ apply = function(hCmd,srcDir,dstDir,reusable,removable){ import fsys; import process.file; import thread.command; var send = ..thread.command.send; var sendIdle = ..thread.command.sendIdle; var srcFilesDir = ..io.joinpath(srcDir,"files"); var filesPath = ..io.joinpath(srcDir,"update-files"); var foldersPath = ..io.joinpath(srcDir,"folders"); if( !..io.exist(srcFilesDir) ){ send(hCmd,"onError","错误的更新源目录",srcFilesDir); return; } if( !..io.exist(filesPath,4) ){ send(hCmd,"onError","错误的更新文件列表",filesPath); return; } if( !..io.exist(foldersPath,4) ){ send(hCmd,"onError","错误的更新目录列表",foldersPath); return; } if( !..io.exist(dstDir) ){ send(hCmd,"onError","错误的更新目标程序目录",dstDir); return; } //创建所有目录 for path in io.lines(foldersPath) { var path = ..io.joinpath(dstDir,path); ..fsys.createDir(path); } var totalFiles = 0; for path in ..io.lines(filesPath) { totalFiles++; } var exes = {}; for( path,prcs in ..process.file.each(dstDir) ){ ..table.push( exes,path ); } if( #exes ) if( send(hCmd,"onProcessCheck",exes ) === false ) { send(hCmd,"onEnd",false ); return true; } var count = 0; var srcPath,dstPath; send(hCmd,"onCopyBegin",totalFiles) for path in ..io.lines(filesPath) { srcPath = ..io.joinpath(srcFilesDir,path); dstPath = ..io.joinpath(dstDir,path); count++; if( sendIdle(1000,hCmd,"onCopyFile",path,count) === false ) { send(hCmd,"onEnd",false ); return true; } while( ! ..fsys.copy(srcPath,dstPath) ){ if( ..io.exist(dstPath) ){ if( ..process.isExe(dstPath) ){ if( send(hCmd,"onProcessFailed", { dstPath } ) === false ) { send(hCmd,"onEnd",false ); return true; } sleep(1); if( ..fsys.copy(srcPath,dstPath) ) break; sleep(1000); continue; } } if( send(hCmd,"onCopyFailed",dstPath ) === false ) { send(hCmd,"onEnd",false ); return true; } sleep(1000); } } var checksumPath = ..io.joinpath(srcDir,"checksum"); var logPath = ..io.joinpath(srcDir,"log-files"); var crc32,uncompressedSize,size,path; if( ..io.exist(logPath) && ..io.exist(checksumPath) ){ if(removable){ var validcrc32 = {} for line in ..io.lines(checksumPath) { crc32,uncompressedSize,size,path = ..string.match(line,"(.+?)\|(.+?)\|(.+?)\|(.+)"); path = ..string.lower(path); validcrc32[path] = crc32; } for line in ..io.lines(logPath) { crc32,uncompressedSize,size,path = ..string.match(line,"(.+?)\|(.+?)\|(.+?)\|(.+)"); path = ..string.lower(path); if( validcrc32[path]===null ){ ..fsys.delete( ..io.joinpath(dstDir,path) ); } } } ..fsys.delete(logPath); } fsys.move(checksumPath,logPath); if( !reusable ){ ..fsys.delete(srcFilesDir); ..fsys.delete(filesPath); ..fsys.delete(foldersPath); ..fsys.delete(..io.joinpath(srcDir,"update-info")); } send(hCmd,"onEnd",true) } } /**intellisense() fsys.update.app = 执行更新程序 fsys.update.app(.(更新源,目标目录,是否保留更新补丁,是否允许移除文件) = 创建更新程序,\n如果参数@3为true,则更新后不删除源补丁\n如果参数@4指定为false,则更新时不删除在新版补丁中已移除的旧版本文件。 fsys.update.app() = !fsys_update_app. !fsys_update_app.updateInfo.version = 更新的软件版本号 !fsys_update_app.updateInfo.description = 更新说明 !fsys_update_app.apply() = 创建更新线程,安装更新 !fsys_update_app.onError = @.onError = function(err,filename){ io.print("更新遇到错误:",err,filename__/*导致错误的文件路径或URL\n该值可能为空*/ ) } !fsys_update_app.onCopyBegin = @.onCopyBegin = function(total){ __/*开始复制文件*/ } !fsys_update_app.onCopyFile = @.onCopyFile = function(path,count){ __/*开始复制参数@1指定的文件,返回false取消更新*/ } !fsys_update_app.onProcessCheck = @.onProcessCheck = function(paths){ __/*参数是更新程序所在目录下已运行的进程路径,\n返回false取消更新*/ } !fsys_update_app.onProcessFailed = @.onProcessFailed = function(paths){ __/*更新程序需要退出进程,\n参数是程序启动路径数组\n返回false取消更新*/ } !fsys_update_app.onCopyFailed = @.onCopyFailed = function(path){ __/*文件被占用,返回false取消更新*/ } !fsys_update_app.onEnd = @.onEnd = function(succeeded){ __/*更新操作已全部完成*/ } end intellisense**/