├── .build ├── default.init.aardio ├── default.main.aardio └── default.Manifest.xml ├── app.ico ├── dist └── WinAsar.7z ├── screenshots └── asar.jpg ├── .editorconfig ├── README.md ├── lib └── config.aardio ├── default.aproj ├── LICENSE ├── main.aardio └── forms ├── packer.aardio └── extractor.aardio /.build/default.init.aardio: -------------------------------------------------------------------------------- 1 | //发布前触发 2 | import ide; -------------------------------------------------------------------------------- /app.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aardio/WinAsar/HEAD/app.ico -------------------------------------------------------------------------------- /dist/WinAsar.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aardio/WinAsar/HEAD/dist/WinAsar.7z -------------------------------------------------------------------------------- /screenshots/asar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aardio/WinAsar/HEAD/screenshots/asar.jpg -------------------------------------------------------------------------------- /.build/default.main.aardio: -------------------------------------------------------------------------------- 1 | //此触发器在生成EXE以后执行 2 | import ide; 3 | import fsys; 4 | 5 | //获取生成的EXE文件路径 6 | var publishFile = ide.getPublishPath(); -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | 6 | [*.{aardio,table,aau}] 7 | end_of_line = crlf 8 | charset = utf-8 9 | indent_style = tab 10 | indent_size = 4 11 | 12 | [*.{aau}] 13 | charset = utf-8-bom -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WinAsar 2 | 3 | A Windows GUI utility to handle asar( electron archive ) files. 4 | It is portable and lightweight. [The executable file](./../../raw/master/dist/WinAsar.7z) size is **551 KB** only. 5 | This utility works on any version of Windows, starting from Windows XP and up to Windows 11. Both 32-bit and 64-bit systems are supported. 6 | 7 | ![Screenshot](http://ide.update.aardio.com/log/asar.jpg) 8 | -------------------------------------------------------------------------------- /lib/config.aardio: -------------------------------------------------------------------------------- 1 | //config 配置文件 2 | import fsys.config; 3 | config = fsys.config( fsys.appdata("/aardio/app/") ); 4 | 5 | //不需要序列化的配置名字前请添加下划线 6 | namespace config { 7 | __appName = "我的软件"; 8 | __appVersion = "0.0.0.01"; 9 | __appDescription = "我的软件说明"; 10 | __website = "http://www.aardio.com/"; 11 | } 12 | 13 | /**intellisense(config) 14 | __appName = 应用程序名 15 | __appVersion = 应用程序内部版本号 16 | __appDescription = 程序说明 17 | __website = 官方网站 18 | ? = 配置文件名,\n读写配置并序列化为一个表对象,\n表的成员值可以是支持序列化的普通变量,支持table对象\n配置文件在首次使用时自动加载,退出程序时自动保存\n!fsys_table. 19 | end intellisense**/ -------------------------------------------------------------------------------- /default.aproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 aardio.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /main.aardio: -------------------------------------------------------------------------------- 1 | import fonts.fontAwesome; 2 | import win.ui; 3 | /*DSG{{*/ 4 | mainForm = win.form(text="WinAsar - asar( electron archive ) utility";right=1019;bottom=679;bgcolor=15793151;border="none") 5 | mainForm.add( 6 | caption={cls="bkplus";text="WinAsar - asar( electron archive ) utility ";left=67;top=9;right=723;bottom=27;align="left";color=6052956;dl=1;dt=1;font=LOGFONT(h=-14);z=7}; 7 | custom={cls="custom";left=83;top=40;right=1022;bottom=679;bgcolor=16777215;db=1;dl=1;dr=1;dt=1;z=4}; 8 | logo={cls="bkplus";text='\uF0AD';left=35;top=7;right=64;bottom=32;color=5659105;dl=1;dt=1;font=LOGFONT(h=-18;name='FontAwesome');z=6}; 9 | nav1={cls="plus";text="Pack";left=0;top=48;right=85;bottom=128;bkBottom=3;bkLeft=7;bkRight=8;bkTop=2;border={color=-65536};color=16777215;dl=1;dt=1;font=LOGFONT(h=-15);iconStyle={font=LOGFONT(h=-37;name='FontAwesome');padding={bottom=20}};iconText='\uF0B1';notify=1;textPadding={bottom=10};valign="bottom";x=0.5;y=0.20000000298023;z=3}; 10 | nav2={cls="plus";text="Extract";left=0;top=129;right=85;bottom=209;bkBottom=3;bkLeft=7;bkRight=8;bkTop=2;border={color=-65536};color=16777215;dl=1;dt=1;font=LOGFONT(h=-15);iconStyle={font=LOGFONT(h=-37;name='FontAwesome');padding={bottom=20}};iconText='\uF0E8';notify=1;textPadding={bottom=10};valign="bottom";x=0.5;y=0.20000000298023;z=5}; 11 | navBar={cls="bkplus";left=0;top=37;right=83;bottom=681;bgcolor=9941835;db=1;dl=1;dt=1;z=1}; 12 | titleBar={cls="bkplus";left=0;top=0;right=1022;bottom=38;bgcolor=5659105;dl=1;dr=1;dt=1;forecolor=16777215;linearGradient=180;z=2} 13 | ) 14 | /*}}*/ 15 | 16 | import win.ui.simpleWindow; 17 | win.ui.simpleWindow( mainForm ); 18 | 19 | import win.ui.tabs; 20 | var tbs = win.ui.tabs( 21 | mainForm.nav1, 22 | mainForm.nav2, 23 | ); 24 | 25 | tbs.skin({ 26 | background={ 27 | active=0xFFFFFFFF; 28 | default=0x00FFFFFF; 29 | hover=0x38FFFFFF 30 | }; 31 | color={ 32 | default=0xFFFFFFFF; 33 | }; 34 | checked={ 35 | background={default=0xFFFFFFFF;}; 36 | color={default=0xff4bb397;}; 37 | } 38 | }) 39 | 40 | tbs.loadForm(1,"\forms\packer.aardio"); 41 | tbs.loadForm(2,"\forms\extractor.aardio" ); 42 | 43 | tbs.selIndex = 1; 44 | 45 | mainForm.show(); 46 | return win.loopMessage(); 47 | -------------------------------------------------------------------------------- /.build/default.Manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | WinAsar 11 | 12 | 13 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 52 | 53 | 54 | 55 | 56 | 57 | True/PM 58 | 59 | 60 | -------------------------------------------------------------------------------- /forms/packer.aardio: -------------------------------------------------------------------------------- 1 | import fonts.fontAwesome; 2 | import win.ui; 3 | /*DSG{{*/ 4 | var winform = win.form(text="WinAsar - packer";right=1075;bottom=734;acceptfiles=1;bgcolor=16777215;parent=...) 5 | winform.add( 6 | btnBuild={cls="plus";text="Pack";left=805;top=664;right=910;bottom=701;align="left";db=1;dr=1;font=LOGFONT(h=-15);iconStyle={align="left";font=LOGFONT(name='FontAwesome');padding={left=15}};iconText='\uF090';notify=1;textPadding={left=35};z=3}; 7 | btnClear={cls="plus";text="Clear";left=272;top=8;right=355;bottom=43;align="left";dl=1;dt=1;font=LOGFONT(h=-15);iconStyle={align="left";font=LOGFONT(name='FontAwesome');padding={left=15}};iconText='\uF1F8';textPadding={left=35};z=8}; 8 | btnOpen={cls="plus";text="Add";left=25;top=8;right=129;bottom=43;align="left";dl=1;dt=1;font=LOGFONT(h=-15);iconStyle={align="left";font=LOGFONT(name='FontAwesome');padding={left=15}};iconText='\uF07C';textPadding={left=35};z=5}; 9 | btnRemove={cls="plus";text="Remove";left=135;top=8;right=239;bottom=43;align="left";disabled=1;dl=1;dt=1;font=LOGFONT(h=-15);iconStyle={align="left";font=LOGFONT(name='FontAwesome');padding={left=15}};iconText='\uF08B';textPadding={left=35};z=9}; 10 | editInfo={cls="richedit";left=371;top=8;right=1064;bottom=655;db=1;dl=1;dr=1;dt=1;edge=1;hscroll=1;multiline=1;vscroll=1;z=2}; 11 | editOutPath={cls="edit";left=138;top=666;right=800;bottom=699;db=1;dl=1;dr=1;edge=1;multiline=1;z=6}; 12 | lbTip={cls="plus";text="Drag and drop files on this form to add them";left=382;top=706;right=663;bottom=728;align="right";db=1;dr=1;transparent=1;z=11}; 13 | plusWebSite={cls="plus";text="Star";left=975;top=698;right=1052;bottom=729;align="left";color=-1;db=1;dr=1;font=LOGFONT(h=-15);iconStyle={align="left";font=LOGFONT(h=-19;name='FontAwesome');padding={left=15;top=1}};iconText='\uF09B';notify=1;textPadding={left=35;bottom=1};z=10}; 14 | progress={cls="plus";left=21;top=710;right=1058;bottom=723;bgcolor=6447459;db=1;dl=1;dr=1;forecolor=9959653;hide=1;max=100;min=0;z=4}; 15 | static={cls="static";text="Archive:";left=42;top=672;right=128;bottom=696;align="right";db=1;dl=1;font=LOGFONT(h=-15);transparent=1;z=7}; 16 | treeview={cls="treeview";left=18;top=51;right=364;bottom=658;bgcolor=16777215;db=1;dl=1;dt=1;edge=1;vscroll=1;z=1} 17 | ) 18 | /*}}*/ 19 | 20 | import fsys.asar.writer; 21 | var asarFile = fsys.asar.writer(); 22 | 23 | var showAsarInfo = function(){ 24 | var info,err = asarFile.createInfo(); 25 | if(!info){ 26 | winform.msgboxErr(err) 27 | return; 28 | } 29 | winform.treeview.clear(); 30 | winform.treeview.insertItem(asarFile.treeData()); 31 | winform.editInfo.text = web.json.stringify(asarFile.info,true); 32 | 33 | if( ( !# ( ..string.trim( winform.editOutPath.text )) ) 34 | || (winform.editOutPath.autoPath = winform.editOutPath.text ) ){ 35 | winform.editOutPath.text = fsys.path.removeBackslash(asarFile.rootDirectory) + ".asar"; 36 | winform.editOutPath.autoPath = winform.editOutPath.text; 37 | } 38 | } 39 | 40 | winform.btnClear.oncommand = function(id,event){ 41 | asarFile.clear(); 42 | winform.treeview.clear(); 43 | winform.editInfo.text = ""; 44 | winform.btnRemove.disabled = true; 45 | } 46 | 47 | import fsys.dlg; 48 | winform.btnOpen.oncommand = function(id,event){ 49 | var path = fsys.dlg.open("*.*|*.*||","Browse",,winform.hwnd); 50 | if(#path){ 51 | asarFile.add( path ); 52 | showAsarInfo(); 53 | } 54 | } 55 | 56 | winform.wndproc = { 57 | [0x233/*_WM_DROPFILES*/] = function(hwnd,message,wParam,lParam){ 58 | var files = win.getDropFile(wParam) 59 | if(#files){ 60 | for(i=1;#files;1){ 61 | asarFile.add( files[i] ); 62 | } 63 | 64 | showAsarInfo(); 65 | }; 66 | } 67 | } 68 | 69 | import fsys; 70 | import win.ui.menu; 71 | import process; 72 | winform.treeview.onnotify = function(id,code,ptr){ 73 | 74 | if( code == 0xFFFFFE3D/*_TVN_SELCHANGEDW*/ ){ 75 | var hItem = winform.treeview.getSelection(); 76 | if(hItem){ 77 | winform.btnRemove.disabled = false; 78 | var data = winform.treeview.getItemData(hItem); 79 | var data = table.clone(data); 80 | for(k,v in data){ 81 | if( v[["size"]] ) v.size =..math.size64(v.size).format(); 82 | } 83 | if( data[["size"]] ) data.size =..math.size64(data.size).format(); 84 | 85 | winform.editInfo.text = web.json.stringify(data,true) 86 | } 87 | else { 88 | winform.btnRemove.disabled = true; 89 | } 90 | } 91 | } 92 | 93 | import fsys.dlg; 94 | import process; 95 | winform.btnBuild.oncommand = function(id,event){ 96 | var outpath = winform.editOutPath.text; 97 | if(!#outpath){ 98 | outpath = fsys.dlg.save("*.asar|*.asar||","Browse",,winform.hwnd); 99 | } 100 | 101 | if(!#outpath) return; 102 | if(!..string.endWith(outpath,".asar",true)){ 103 | winform.msgboxErr("An archive path must end with the '.asar'"); 104 | winform.editOutPath.setFocus(); 105 | return; 106 | } 107 | 108 | winform.plusWebSite.hide = true; 109 | 110 | winform.btnBuild.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'} 111 | winform.progress.hide = false; 112 | winform.progress.setProgressRange(1,1000); 113 | for(path,size,progress in asarFile.eachPack(outpath)){ 114 | winform.progress.progressPos = progress * 1000; 115 | win.delay(1) 116 | } 117 | winform.btnBuild.disabledText = null; 118 | 119 | if( asarFile.lasterr ) winform.msgboxErr(asarFile.lasterr) 120 | winform.progress.hide = true; 121 | process.explore_select(outpath) 122 | } 123 | 124 | winform.btnRemove.oncommand = function(id,event){ 125 | var hItem = winform.treeview.getSelection(); 126 | if(hItem){ 127 | var path = winform.treeview.getItemPath(hItem); 128 | if(asarFile.remove(path)){ 129 | winform.treeview.delItem(hItem) 130 | } 131 | } 132 | } 133 | 134 | winform.btnClear.skin({ 135 | background={ 136 | default=0xFF8FB2B0; 137 | hover=0xFF928BB3; 138 | disabled=0xFFCCCCCC; 139 | } 140 | }) 141 | 142 | winform.btnOpen.skin({ 143 | background={ 144 | default=0xFF8FB2B0; 145 | hover=0xFF928BB3; 146 | disabled=0xFFCCCCCC; 147 | } 148 | }) 149 | 150 | winform.btnRemove.skin({ 151 | background={ 152 | default=0xFF8FB2B0; 153 | hover=0xFF928BB3; 154 | disabled=0xFFCCCCCC; 155 | } 156 | }) 157 | 158 | winform.btnBuild.skin({ 159 | background={ 160 | default=0xFF8FB2B0; 161 | hover=0xFF928BB3; 162 | disabled=0xFFCCCCCC; 163 | } 164 | }) 165 | 166 | winform.plusWebSite.skin( 167 | color = { 168 | hover = 0xFFFF0000; 169 | active = 0xFF00FF00; 170 | } 171 | ) 172 | winform.plusWebSite.oncommand = function(id,event){ 173 | import process 174 | process.openUrl("https://github.com/aardio/WinAsar") 175 | } 176 | 177 | winform.enableDpiScaling(); 178 | winform.show(); 179 | 180 | win.loopMessage(); 181 | return winform; -------------------------------------------------------------------------------- /forms/extractor.aardio: -------------------------------------------------------------------------------- 1 | import win.ui; 2 | import fonts.fontAwesome; 3 | /*DSG{{*/ 4 | var winform = win.form(text="WinAsar - extractor";right=1075;bottom=736;acceptfiles=1;bgcolor=16777215;parent=...) 5 | winform.add( 6 | btnExtract={cls="plus";text="Extract";left=805;top=666;right=913;bottom=699;align="left";db=1;dr=1;font=LOGFONT(h=-15);iconStyle={align="left";font=LOGFONT(name='FontAwesome');padding={left=15}};iconText='\uF093';notify=1;textPadding={left=35};z=3}; 7 | btnOpen={cls="plus";text="Open";left=623;top=4;right=868;bottom=37;align="left";dr=1;dt=1;font=LOGFONT(h=-15);iconStyle={align="left";font=LOGFONT(name='FontAwesome');padding={left=15}};iconText='\uF115';notify=1;textPadding={left=35};z=6}; 8 | btnReplace={cls="plus";text="Save";left=888;top=4;right=1047;bottom=37;align="left";disabled=1;dr=1;dt=1;font=LOGFONT(h=-15);iconStyle={align="left";font=LOGFONT(name='FontAwesome');padding={left=15}};iconText='\uF114';textPadding={left=35};z=9}; 9 | editAsarPath={cls="edit";left=19;top=5;right=617;bottom=36;dl=1;dr=1;dt=1;edge=1;multiline=1;z=5}; 10 | editInfo={cls="richedit";left=371;top=42;right=1058;bottom=654;db=1;dl=1;dr=1;dt=1;edge=1;hscroll=1;multiline=1;vscroll=1;z=2}; 11 | editOutDir={cls="edit";left=138;top=666;right=800;bottom=699;acceptfiles=1;db=1;dl=1;dr=1;edge=1;multiline=1;z=7}; 12 | progress={cls="plus";left=21;top=710;right=1058;bottom=723;bgcolor=6447459;db=1;dl=1;dr=1;forecolor=9959653;hide=1;max=100;min=0;z=4}; 13 | static={cls="static";text="Copy to:";left=42;top=672;right=128;bottom=696;align="right";db=1;dl=1;font=LOGFONT(h=-15);transparent=1;z=8}; 14 | treeview={cls="treeview";left=18;top=43;right=364;bottom=658;asel=false;bgcolor=16777215;db=1;dl=1;dt=1;edge=1;vscroll=1;z=1} 15 | ) 16 | /*}}*/ 17 | 18 | import fsys.asar.reader; 19 | var showAsarInfo = function(){ 20 | var unasar,err = fsys.asar.reader(winform.editAsarPath.text); 21 | if(!unasar){ 22 | winform.msgboxErr(..string.concat("Format error: not an asar file or corrupted",err)); 23 | return; 24 | } 25 | 26 | winform.treeview.clear(); 27 | winform.treeview.insertItem(unasar.treeData()); 28 | 29 | winform.editInfo.text = web.json.stringify(unasar.info,true); 30 | 31 | if(winform.unasar) winform.unasar.close(); 32 | winform.unasar = unasar; 33 | winform.asaPath = winform.editAsarPath.text; 34 | 35 | if( ( !# ( ..string.trim( winform.editOutDir.text )) ) 36 | || (winform.editOutDir.autoPath = winform.editOutDir.text ) ){ 37 | winform.editOutDir.text = winform.asaPath + ".unpack"; 38 | winform.editOutDir.autoPath = winform.editOutDir.text ; 39 | } 40 | } 41 | 42 | winform.editAsarPath.oncommand = function(id,event){ 43 | if( event == 0x300/*_EN_CHANGE*/){ 44 | if( ..string.endWith(winform.editAsarPath.text,"*.asar")){ 45 | if( ..io.exist(winform.editAsarPath.text)){ 46 | showAsarInfo(); 47 | }; 48 | } 49 | } 50 | 51 | } 52 | 53 | import fsys.dlg; 54 | winform.btnOpen.oncommand = function(id,event){ 55 | var path = fsys.dlg.open("*.asar|*.asar||","Browse",,winform.hwnd); 56 | if(#path){ 57 | winform.editAsarPath.text = path; 58 | showAsarInfo(); 59 | } 60 | } 61 | 62 | winform.wndproc = { 63 | [0x233/*_WM_DROPFILES*/] = function(hwnd,message,wParam,lParam){ 64 | var files = win.getDropFile(wParam) 65 | if(#files){ 66 | winform.editAsarPath.text = files[1]; 67 | showAsarInfo(); 68 | }; 69 | } 70 | } 71 | 72 | winform.editOutDir.wndproc = { 73 | [0x233/*_WM_DROPFILES*/] = function(hwnd,message,wParam,lParam){ 74 | var files = win.getDropFile(wParam) 75 | if(#files){ 76 | if( fsys.isDir(files[1]) ) 77 | winform.editOutDir.text = files[1]; 78 | }; 79 | } 80 | } 81 | 82 | import fsys; 83 | import win.ui.menu; 84 | import process; 85 | import fsys.mime; 86 | winform.treeview.onnotify = function(id,code,ptr){ 87 | 88 | if( code == 0xFFFFFE3D/*_TVN_SELCHANGEDW*/ ){ 89 | var hItem = winform.treeview.getSelection(); 90 | if(hItem){ 91 | var data = winform.treeview.getItemData(hItem); 92 | if( data[["size"]] && data[["size"]] < 0x10000 93 | && ( ..string.len(winform.unasar.readFile(data.path) ) ) 94 | ){ 95 | winform.editInfo.text = winform.unasar.readFile(data.path); 96 | winform.btnReplace.disabled = false; 97 | } 98 | else { 99 | winform.btnReplace.disabled = true; 100 | winform.editInfo.text = web.json.stringify(data,true) 101 | } 102 | 103 | } 104 | } 105 | elseif(code = 0xFFFFFFFB/*_NM_RCLICK*/){ //鼠标右键单击 106 | var hItem,tvht = winform.treeview.hitTest(); 107 | winform.treeview.setSelected(hItem); 108 | var data = winform.treeview.getItemData(hItem); 109 | if(!data[["size"]]) return; 110 | 111 | var menu = win.ui.popmenu(winform) 112 | menu.add("Copy To...", 113 | function(){ 114 | var dir = fsys.getParentDir(winform.asaPath) 115 | var path = fsys.dlg.save("*.*|*.*||","Copy",dir ,winform.hwnd,,data.text) 116 | 117 | if(path){ 118 | 119 | var file = io.open(path,"w+b") 120 | if(!file) { 121 | winform.msgboxErr("Create File Failed!") 122 | return; 123 | } 124 | 125 | winform.progress.hide = false; 126 | winform.progress.setProgressRange(1,data.size); 127 | 128 | var buf = raw.buffer(0x100000) 129 | for readSize in winform.unasar.eachReadBuffer(buf,data.path) { 130 | file.writeBuffer(buf,readSize); 131 | winform.progress.progressPos = winform.progress.pos + readSize; 132 | } 133 | file.close(); 134 | process.explore(path) 135 | } 136 | } 137 | ) 138 | menu.popup(x,y,true); 139 | } 140 | } 141 | 142 | winform.btnReplace.oncommand = function(id,event){ 143 | hItem = winform.treeview.getSelection(); 144 | var data = winform.treeview.getItemData(hItem); 145 | if(!(data[["size"]] && data[["path"]]) ) { 146 | winform.msgboxErr("Invalid item data"); 147 | return; 148 | } 149 | var ret,err = winform.unasar.replaceText(data[["path"]],winform.editInfo.text) 150 | if(err) return winform.msgboxErr(err); 151 | 152 | winform.btnReplace.disabled = true; 153 | win.delay(1000); 154 | winform.btnReplace.disabled = false; 155 | } 156 | 157 | import fsys.dlg; 158 | import process; 159 | winform.btnExtract.oncommand = function(id,event){ 160 | if(!#winform.asaPath){ 161 | var path = fsys.dlg.open("*.asar|*.asar||","Browse",,winform.hwnd); 162 | if(#path){ 163 | winform.editAsarPath.text = path; 164 | showAsarInfo(); 165 | } 166 | else { 167 | return; 168 | } 169 | } 170 | 171 | var dir = winform.editOutDir.text; 172 | var parentDir = fsys.getParentDir(winform.asaPath) 173 | ..io.createDir(dir) 174 | if( ! #dir ) 175 | dir = fsys.dlg.opendir(parentDir,winform.hwnd,"Browse"); 176 | 177 | if(!dir) return; 178 | 179 | winform.progress.hide = false; 180 | winform.progress.setProgressRange(1,1000); 181 | 182 | winform.btnExtract.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'} 183 | var msg = MSG() 184 | for path,size,progress in winform.unasar.eachUnpack(dir) { 185 | winform.progress.progressPos = progress * 1000; 186 | win.peekPumpMessage( msg ) 187 | } 188 | winform.btnExtract.disabledText = null; 189 | 190 | winform.progress.hide = true; 191 | process.explore_select(dir) 192 | } 193 | 194 | winform.btnExtract.skin({ 195 | background={ 196 | default=0xFF8FB2B0; 197 | hover=0xFF928BB3; 198 | disabled=0xFFCCCCCC; 199 | } 200 | }) 201 | 202 | winform.btnOpen.skin({ 203 | background={ 204 | default=0xFF8FB2B0; 205 | hover=0xFF928BB3; 206 | disabled=0xFFCCCCCC; 207 | } 208 | }) 209 | 210 | winform.btnReplace.skin({ 211 | background={ 212 | default=0xFF8FB2B0; 213 | hover=0xFF928BB3; 214 | disabled=0xFFCCCCCC; 215 | } 216 | }) 217 | 218 | winform.show(); 219 | 220 | win.loopMessage(); 221 | return winform; --------------------------------------------------------------------------------