# aardio 范例: DLL 查看工具



```aardio
//DLL 查看工具
import fonts.fontAwesome;
import win.ui;
/*DSG{{*/
winform = win.form(text="DLL查看工具";right=1019;bottom=679;bgcolor=0xF0FBFF;border="none")
winform.add(
btnLoad={cls="plus";text="分析";left=709;top=635;right=796;bottom=670;bgcolor=0xB0B28F;db=1;dr=1;font=LOGFONT(h=-13);notify=1;z=9};
caption={cls="bkplus";text="DLL / EXE 文件导入导出表查看工具 ( 双击单元格可以编辑复制 )";left=67;top=8;right=565;bottom=29;align="left";color=0x5C5C5C;dl=1;dt=1;font=LOGFONT(h=-14);z=6};
editExportDeclaration={cls="edit";left=102;top=48;right=1001;bottom=627;db=1;dl=1;dr=1;dt=1;edge=1;hide=1;hscroll=1;multiline=1;vscroll=1;z=12};
editFilePath={cls="plus";left=106;top=636;right=696;bottom=671;align="right";bgcolor=0xF0FBFF;border={bottom=1;color=0xFF008000};db=1;dl=1;dr=1;editable="edit";font=LOGFONT(h=-16);tabstop=1;textPadding={top=6;bottom=1};z=8};
lbInfo={cls="static";text="可拖放DLL到当前窗口";left=807;top=648;right=1001;bottom=673;db=1;dr=1;font=LOGFONT(h=-13);transparent=1;z=10};
listview={cls="listview";left=102;top=49;right=1002;bottom=628;db=1;dl=1;dr=1;dt=1;edge=1;z=7};
logo={cls="bkplus";text='\uF15B';left=35;top=7;right=64;bottom=32;color=0x626B58;dl=1;dt=1;font=LOGFONT(h=-18;name='FontAwesome');z=5};
navBar={cls="bkplus";left=0;top=37;right=83;bottom=681;bgcolor=0x4BB390;db=1;dl=1;dt=1;z=1};
navExport={cls="plus";text="导出表";left=0;top=48;right=85;bottom=128;bkBottom=3;bkLeft=7;bkRight=8;bkTop=2;border={color=0xFFFF0000};color=0xFFFFFF;dl=1;dt=1;font=LOGFONT(h=-13);iconStyle={font=LOGFONT(h=-37;name='FontAwesome');padding={bottom=20}};iconText='\uF0AE';notify=1;textPadding={bottom=10};valign="bottom";x=0.5;y=0.2;z=3};
navExportDeclaration={cls="plus";text="声明";left=0;top=216;right=82;bottom=296;bkBottom=3;bkLeft=7;bkRight=8;bkTop=2;border={color=0xFFFF0000};color=0xFFFFFF;dl=1;dt=1;font=LOGFONT(h=-13);iconStyle={font=LOGFONT(h=-37;name='FontAwesome');padding={bottom=20}};iconText='\uF0F6';notify=1;textPadding={bottom=10};valign="bottom";x=0.5;y=0.2;z=11};
navImport={cls="plus";text="导入表";left=0;top=132;right=85;bottom=212;bkBottom=3;bkLeft=7;bkRight=8;bkTop=2;border={color=0xFFFF0000};color=0xFFFFFF;dl=1;dt=1;font=LOGFONT(h=-13);iconStyle={font=LOGFONT(h=-37;name='FontAwesome');padding={bottom=20}};iconText='\uF1DE';notify=1;textPadding={bottom=10};valign="bottom";x=0.5;y=0.2;z=4};
titleBar={cls="bkplus";left=0;top=0;right=1022;bottom=38;bgcolor=0x606B52;dl=1;dr=1;dt=1;forecolor=0xFFFFFF;linearGradient=180;z=2}
)
/*}}*/

import win.ui.simpleWindow;
win.ui.simpleWindow( winform );

import win.ui.tabs;
var tbs = win.ui.tabs( 
	winform.navExport,
	winform.navImport,
	winform.navExportDeclaration
);

tbs.skin({
	background={
		active=0xFFFFFFFF;
		default=0x00FFFFFF;
		hover=0x38FFFFFF
	};
	color={
		default=0xFFFFFFFF; 
	};
	checked={
		background={default=0xFFFFFFFF;};
		color={default=0xFF42A875;};
	}
})

winform.btnLoad.skin({
	background={
		default=0xFF8FB2B0;
		hover=0xFF928BB3;
		disabled=0xFFCCCCCC; 
	}
})

tbs.selIndex = 1;

import raw.pefile;
var showPeFile = function(pefile){
	
	if(pefile.getClrHeader()){
		winform.lbInfo.text = ( ..string.endsWith(pefile.path,".exe",true) ? ".NET 程序" : ".NET 程序集" )
		
		if( winform.btnLoad.text != "反编译" ){
			tbs.selIndex = 2; 
			winform.btnLoad.text = "反编译";
		}
	}
	else { 
		var major = pefile.majorLinkerVersion;
		var minor = pefile.minorLinkerVersion;
		  
		var linker = "未知编译器 v"+major+"."+minor;
		
		if( major == 14 ){
			/*
			可使用 sys.vc14.require 自动检测、按需安装运行库。
			例如 sys.vc14.require("2022")
			*/
			if( minor >= 50 ){
        		linker = "VC++ 2026(MSVC v145)"; 
    		}
    		elseif( minor >= 40 ){
        		linker = "VC++ 2022(MSVC v144)";
    		}
    		if( minor >= 30 ){
        		linker = "VC++ 2022(MSVC v143)";
    		}
    		elseif( minor >= 20 ){
        		linker = "VC++ 2019(MSVC v142)";
    		}
    		elseif( minor >= 10 ){
        		linker = "VC++ 2017(MSVC v141)";
    		}
    		else {
        		linker = "VC++2015(MSVC v140)";
    		}
		}
		elseif( major == 12 ){
    		linker = "VC++ 2013(MSVC v120)";
		}
		elseif( major == 11 ){
    		linker = "VC++ 2012(MSVC v110)";
		}
		elseif( major == 10 ){
    		linker = "VC++ 2010(MSVC v100)";
    		 
    		if(string.endsWith(pefile.path,".exe",true)){
				var aardioLibs = 0; 
				
				import fsys.res;
				var hm = fsys.res.load(pefile.path)
				if(hm){
					fsys.res.enum(
						function(module,resType,resName){ 
							if(resName=="BUILTIN")
								|| (resName=="BUILTIN.COM")
								|| (resName=="BUILTIN.THREAD") {
								aardioLibs++
							}
							return true;
						},"LIB",hm
					)
					
					fsys.res.free(hm);
				}
				
				if(aardioLibs===3){
					linker = "aardio";
				}
			}
 
		}
		elseif( major == 9 ){
    		linker = "VC++ 2008(MSVC v90)";
		}
		elseif( major == 8 ){
    		linker = "VC++ 2005(MSVC v80)";
		}
		elseif( major == 7 ){
			if( minor >= 10 ) linker = "VC++ 2003(MSVC v71)";
			else  linker = "VC++ 2002(MSVC v70)";
		}
		elseif( major == 6 ){
    		linker = "VC++ 6.0(MSVC v60)";
		}
		else if( major <= 3){
 
			var isGccSection = false;
			var isGoSection = false;
			var sections = pefile.sections;
			 
			for(i, sec in sections){ 
    			var name = string.str(sec.name); 
    			
    			if( name == ".eh_frame" || name == ".eh_fram" || name == ".ctors" || name == ".dtors" ){
        			isGccSection = true;
        			break;
    			}
    			elseif( name == ".symtab" ){
					isGoSection = true;
				}
			}
			
			var importsMsvcrt = false;
			if( pefile.isImported("msvcrt.dll") ){
    			importsMsvcrt = true;
			}
			
			if( isGoSection ){
				linker = "Go Linker v"+major+"."+minor+""
				if(isGccSection && importsMsvcrt)  linker = "Go(CGO/MinGW) v2."+minor+""
			}
			elseif(  (isGccSection && importsMsvcrt) ){
        		linker = "MinGW / GCC"; 
        		if(major == 2) linker = linker + "(ld 2."+minor+")";
    		}
    		elseif(importsMsvcrt){
    			linker = "MinGW / GCC (Likely)";
    		} 
		}  
		
		winform.lbInfo.text = ( pefile.isPe32 ? "32 位 " : "64 位 " ) + linker;
		winform.btnLoad.text = "分析"; 
	}
		
	winform.listview.clear(true);
	
	if(tbs.selIndex==2){
		winform.listview.visible = true;
		winform.editExportDeclaration.visible = false;

		winform.listview.insertColumn("DLL",100) 
		winform.listview.insertColumn("序号",50) 
		winform.listview.insertColumn("函数名",-1)

		var data = pefile.getImportDirectory(); 
		if(data){
			for i,module in table.eachIndex(data){
				for i,f in table.eachIndex(module.functions){
					winform.listview.addItem({module.name;f.hint,f.name})
				}
			}	
		}	
	}
	elseif(tbs.selIndex==1){ 
		winform.listview.visible = true;
		winform.editExportDeclaration.visible = false;
		
		winform.listview.insertColumn("序号",50)
		winform.listview.insertColumn("地址",150)
		winform.listview.insertColumn("导出函数",-1) 
		
		var names = pefile.getExportNames();
		if(names){
			for(k,v in names){ 
				if(v.name=="MetaDataGetDispenser"){
					winform.lbInfo.text = ( ..string.endsWith(pefile.path,".exe",true) ? ".NET 程序" : ".NET 程序集" ) 
					if( winform.btnLoad.text != "反编译" ){ 
						winform.btnLoad.text = "反编译";
					} 
					
					break;
				}
			}
		 	
			winform.listview.setTable(names);			
		}
	} 
	elseif(tbs.selIndex==3){
		winform.listview.visible = false;
		winform.editExportDeclaration.visible = true; 
		winform.editExportDeclaration.text = "";
		
		var code = pefile.exportDeclaration(); 
		if(code){
			winform.editExportDeclaration.text = code;
		}
		else {
			winform.editExportDeclaration.text = '/*\r\n自动生成API声明代码仅支持使用C++修饰名的API函数\r\n*/'
		}
	}
}

var searchDll = function(dllPath){
	return io.exist(dllPath) 
		|| win.path.searchDll(dllPath) 
    	|| win.path.search(dllPath)
    	|| fsys.wow64.disableRedirection(lambda()win.path.search(dllPath))
}

import win.path;
import fsys.wow64;
winform.btnLoad.oncommand = function(id,event){ 
	var ilSpy = (winform.btnLoad.text == "反编译");
	
    var dllPath = searchDll(winform.editFilePath.text) || searchDll(winform.editFilePath.text+".dll"); 
	var pefile,err = raw.pefile(dllPath);
	if(!pefile){
		winform.setTimeout( 
			function(){
				winform.editFilePath.editBox.showWarningTip(,err)
			});
			
		return;
	}

	winform.editFilePath.text = dllPath;
	showPeFile(pefile);	
	pefile.close();
	
	if(ilSpy) {
		winform.btnLoad.disabledText =  "请稍候";
		
		import dotNet.ilSpy;
		dotNet.ilSpy(dllPath);
		
		winform.setTimeout( 
			function(){
				winform.btnLoad.disabledText = null;
			},3000) 
	}
}

winform.editFilePath.editBox.onOk = function(){
	winform.btnLoad.oncommand();
}

import fsys.lnk;
winform.onDropFiles = function(files){
    var path = files[1];
    if(string.endsWith(path,".lnk",true)){
    	var lnk = fsys.lnk().load(path);
    	if(lnk){
    		path = lnk.path;
    	}
    	else {
    		return;
    	}
    }
    
	winform.editFilePath.text = path;
	winform.btnLoad.oncommand();
	
	if(string.endsWith(path,".exe",true)){
		if(!winform.listview.count){
			tbs.selIndex = 2;
		} 
    }
}

tbs.onSelChange = function(idx,strip,form){
	var pefile,err = raw.pefile(winform.editFilePath.text);
	if(pefile) {
		showPeFile(pefile);
		pefile.close();
	}
}

import win.ui.grid;
win.ui.grid(winform.listview);

winform.show();
winform.editFilePath.setFocus();
winform.editFilePath.editBox.showInfoTip("DLL文件名","请在这里输入DLL名字、文件路径等然后直接回车,也可以直接拖放DLL文件到这里")
winform.editFilePath.editBox.disableInputMethod()

winform.editFilePath.editBox.onChange = function(){ 
	winform.btnLoad.text = "分析";
}

winform.listview.setExtended(0x10000/*_LVS_EX_DOUBLEBUFFER*/);
win.loopMessage();
```

