[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[其他] 又一个 dllcall.exe

论坛中已有的类似工具:


====================================================================================
以下内容摘自: http://www.vinoca.org/2011/08/25/dllcall/
dllcall ,用批处理做程序

dllcall 类似于 rundll32 的程序,但是调用很明了,实现方式也和 rundll32 不同,rundll32 可以为一些API提供窗口,dllcall 只是一个命令行(console pro)程序,所以 rundll32 应用最广的调用.cpl文件的执行在dllcall中不能实现。dllcall 主要用来扩展批处理,可以用批处理做一些简单的程序。

dllcall 的制作缘起主要是由于作者以前一直在用 NSIS 将一些工具打包放在移动设备中用来部署工作环境,但移动设备中的exe文件经常会被病毒感染,而且当工具包有一点小改动时也要重新编译整个包,当这个包很大时就很耗费时间,所以改用批处理加 7za 加单独压缩的包的形式,shorcut 也是这个原因制作的。

dllcall的特点:

  • 使用汇编语言编写,fasm汇编器汇编,指令级优化,极小的体积(目前版本4KB),超快的速度,真正意义上的绿色软件。
  • 开源软件,使用MIT开源协议发布,可以了解程序的每一个细节,放心地使用(可惜360之类的很多杀毒软件会报毒,汇编语言写的程序命运大都如此吧)。
  • 提供的只是一种机制,而非功能,从而随心所欲地实现自己想要的功能,而且仅仅是通过批处理。
  • 由于涉及到Windows API的调用,可能有些拗,其实编程很简单,很多人大抵是被课堂里的C语言给震慑了吧,用dllcall做程序,首先需知道自己想要什么功能,批处理能否实现(GUI界面当然不是命令行程序所擅长的),涉及到複雜結構體的填充,多個指針的調用,及上下函數傳遞參數非常複雜的情況不宜用dllcall。其实通过调用一两个API函数实现的功能最适合dllcall了,一些例子就在下面。


dllcall使用教程看这里
  1. Usage: dllcall {function name} [parameter(s)]... {DLL name}
  2. Examples:
  3. dllcall Sleep,1000,kernel32.dll
  4. dllcall MessageBoxA,,"Hello world!",Prompt,1,user32.dll
  5. dllcall MessageBoxW,,"%uAdd prefix %u indicate unicode s ",%ua,1,user32.dll
  6. dllcall ShellExecuteA,,,"http://www.google.com",,,,shell32.dll
  7. dllcall 61,,,,,,shell32.dll
  8. dllcall 61,,,,%uRun,"%u Only Demo",,shell32.dll
  9. dllcall SendMessageA,0x0FFFF,0x00112,0x0F170,1,user32.dll
  10. the display is going to low power.
  11. dllcall SHChangeNotify,0x8000000,0x1000,,,shell32.dll
  12. refresh desktop items.
复制代码
使用%u前缀指明后面跟的是unicode字符串,原因是所有与字符有关的API都有ansi及unicode两种版本,其函数后面有A及W字符,如MessageBoxA和MessageBoxW,而系统默认的字符编码是unicode,所以在给一些用序号导出的API传递字符串参数时只能在调用时实现编码的转换,shell32.dll中序号为61的函数就是这种情况。

用%o使用一个输出型参数,每次调用只能有一个%o出现,%o输出的结果在返回值之后,如dllcall GetWindowsDirectoryA,%o,4096,kernel32.dll ,输出结果为 10 C:\WINDOWS 。%od将输出转换为一整数 调用函数的返回值回显为一个十进制的数。

2009-12-29 更新:
考虑再三,还是加上了多个函数的调用,如 dllcall OpenClipboard,,user32.dll;GetClipboardData,1,user32.dll*;CloseClipboard,user32.dll- 这样的格式,”*”指明返回值是一个指向字符串的指针。

文档及源码整理得不太好,故文档不再放出,源码暂不放出。

每个DLL导出的函数可用 gie 获取,在这里下载,如用 gie -e shell32.dll 得到 shell32.dll 的所有导出函数,API的调用说明参见MSDN,也可在这里找到相关的资源。

  • “,”(即英文逗号)分隔传入的参数,在参数中使用英文逗号,用”\”转义,如”Hello\,i am tom.”这样的参数。逗号会被空格代替,参数可以是纯数字,如1234或”1234″,表示一个十进制的数; 0x 开头的参数表示一个十六进制的数,如0×1234或”0×1234″;
  • %u 开头的参数表示这是一个unicode 类型的字符串,如%uHello\,man 或”%uHello\,i am tom.”;
  • %o 开头的参数表示将这个参数中的结果打印出来,如%o 或”%o”,
  • %od 开头的参数与 %o 开头的参数类似,也是打印结果,但是会认为参数是一个整数,用法与%o 相同,如果不全是数字而且没有
  • 0x %u 等参数说明符,参数会被认为是一个字符串。 参数中有空格或中文字符,用引号将参数引起来,0x %u 等参数说明符号应在引号内,如果传入的参数值为0,可用,,这样的写法。


1.0.3.0版本加入功能说明: 加入%r参数说明符,加入符号”;”、”*”、”-”,增加了多个函数的调用。 %r用来引用一次dllcall使用中上一个函数的返回值; “;”用来分隔调用的函数,在函数中使用”;”用”\;”转义,”*”及”-”放在一个函数调用语句的后面,”*”用来指示函数的返回值是一个字符串的地址,”-”用来指示函数的返回值不再打印出来。例如:
  1. dllcall OpenClipboard,,user32.dll;GetClipboardData,1,user32.dll*;CloseClipboard,user32.dll-
复制代码
这个语句中有3个函数,第一个函数打开剪切板,第二个函数取得其中的数据,第三个函数关闭了剪切板。
2010-6-21 更新:
1.0.3.3版本加入功能说明: 加入%p参数说明符。 %p指出这个参数是一个指针,其后可跟一个十进制或十六进制的数对其赋初值。例如:
  1. dllcall IsNetworkAlive,%p0x1,sensapi.dll
复制代码
这个语句中传入IsNetworkAlive的参数是一个指针(即地址值),这个地址中的内容是1 。

2010-7-17 更新:
1.0.3.4版本加入功能说明: 加入”-r”选项。 由于Windows的命令解释器cmd.exe的for命令中使用dllcall会出错,所以”-r”选项的作用就是给出一个替代”,”的字符,如:
  1. for /f %i in ('dllcall -r# MessageBoxA##"test"#p#0x24#user32.dll') do set return=%i
复制代码
源码及可執行文件下載: http://vinoca.org/download


示例1: 对 notepad 操作
  1. @echo off
  2. start "" notepad.exe
  3. dllcall Sleep,700,kernel32.dll-
  4. dllcall FindWindowA,"Notepad",,user32.dll-
  5. set hPad=%errorlevel%
  6. dllcall ShowWindow,%hPad%,3,user32.dll-
  7. dllcall FindWindowExA,%hPad%,,"Edit",,user32.dll-
  8. set hEdit=%errorlevel%
  9. call:putchar 0x4F
  10. call:putchar 0x6E
  11. call:putchar 0x6C
  12. call:putchar 0x79
  13. call:putchar 0x2C 900
  14. call:putchar 0x08
  15. call:putchar 0x20
  16. call:putchar 0x44
  17. call:putchar 0x45
  18. call:putchar 0x4D
  19. call:putchar 0x4F
  20. call:putchar 0x2E
  21. call:sleep 1500
  22. rem 发送 WM_QUIT(0x12) 消息到notepad的主窗体,关闭notpead .
  23. dllcall PostMessageA,%hPad%,0x12,,,user32.dll-
  24. pause
  25. :putchar <char>
  26. setlocal
  27. set arg2=%2&&if "%2" == "" set arg2=300
  28. rem 发送WM_CHAR(0x102)消息到notepad的子窗体edit ,输入一个字符,wParam 参数为字符
  29. dllcall SendMessageA,%hEdit%,0x102,%1,,user32.dll-
  30. call:sleep %arg2%
  31. exit /b
  32. :sleep <ms>
  33. dllcall Sleep,%1,kernel32.dll-
  34. exit /b
复制代码
示例2: 关闭显示器
  1. @echo off
  2. rem invoke SendMessage,HWND_BROADCAST,WM_SYSCOMMAND,SC_MONITORPOWER,1
  3. rem 使显示器处于低功耗状态
  4. rem dllcall SendMessageA,0x0FFFF,0x00112,0x0F170,1,user32.dll
  5. rem invoke SendMessage,HWND_BROADCAST,WM_SYSCOMMAND,SC_MONITORPOWER,2
  6. rem 关闭显示器
  7. dllcall SendMessageA,0x0FFFF,0x00112,0x0F170,2,user32.dll
复制代码
示例3: 修改“开始”按钮的文字(WinXP)
  1. @echo off
  2. for /f %%i in ('dllcall -r# FindWindowA#"Shell_TrayWnd"##user32.dll') do set hWindow=%%i
  3. for /f %%i in ('dllcall -r# FindWindowExA#%hWindow%##"Button"##user32.dll') do set hWindow=%%i
  4. rem 发送WM_SETTEXT 消息到子窗体
  5. dllcall SendMessageA,%hWindow%,0x0C,,"傳送",user32.dll-
  6. exit
复制代码
示例4: 隐藏批处理窗体及播放wav格式音频文件
  1. @echo off
  2. set cmdTitle=cmd%random%
  3. title %cmdTitle%
  4. for /f %%i in ('dllcall -r# FindWindowA##%cmdTitle%#user32.dll') do set hCmd=%%i
  5. rem 隐藏窗口1秒
  6. dllcall ShowWindow,%hCmd%,,user32.dll-
  7. dllcall Sleep,1000,kernel32.dll-
  8. dllcall ShowWindow,%hCmd%,1,user32.dll-
  9. rem 播放 WAV 格式声音
  10. dllcall PlaySoundA,"type.wav",,0x20000,winmm.dll-
  11. pause
复制代码
示例5: 打开关闭光驱仓门
  1. @echo off
  2. dllcall mciSendStringA,"open cdaudio",,,,winmm.dll-
  3. ::打开光驱仓门
  4. dllcall mciSendStringA,"set cdaudio door open",,,,winmm.dll-
  5. ::关闭光驱仓门
  6. ::dllcall mciSendStringA,"set cdaudio door closed",,,,winmm.dll-
  7. dllcall mciSendStringA,"close cdaudio",,,,winmm.dll-
  8. pause
复制代码
示例6: 打开可移动存储设备
  1. @echo off
  2. set n=1
  3. :loop
  4. if %n%==12 goto endloop
  5. for /f "tokens=%n% delims=," %%i in ("C:,D:,E:,F:,E:,H:,I:,J:,K:,L:,M:,N:") do set driveString=%%i
  6. for /f %%i in ('dllcall -r# GetDriveTypeA#%driveString%#kernel32.dll') do set driveType=%%i
  7. if %driveType%==2 start "" "%driveString%"
  8. set /a n+=1
  9. goto loop
  10. :endloop
  11. pause
复制代码
示例7: MessageBox 演示
  1. @echo off
  2. set strPrompt=演示
  3. ::dllcall Beep,5000,50,kernel32.dll
  4. ::dllcall MessageBeep,0x20,user32.dll
  5. dllcall MessageBoxA,,"你好",%strPrompt%,,user32.dll-
  6. for /f %%i in ('dllcall -r# MessageBoxA##"喜欢用批处理吗?"#%strPrompt%#0x24#user32.dll') do set return=%%i
  7. if %return%==6 dllcall MessageBoxA,,"我也很喜欢哦。",%strPrompt%,0x30,user32.dll-
  8. if %return%==7 dllcall MessageBoxA,,"Oh ,No!",%strPrompt%,0x10,user32.dll-
  9. pause
复制代码
示例8: 命令行显示剪切板中文字数据
  1. dllcall OpenClipboard,,user32.dll;GetClipboardData,1,user32.dll*;CloseClipboard,user32.dll-
复制代码
示例9: 设置屏幕字体的边缘平滑
  1. dllcall SystemParametersInfoA,75,1,0,3,user32.dll-
  2. dllcall SystemParametersInfoA,8203,0,2,3,user32.dll-
  3. dllcall SystemParametersInfoA,8211,0,1,3,user32.dll-
  4. dllcall SystemParametersInfoA,8205,0,1000,3,user32.dll-
  5. dllcall RedrawWindow,0,0,0,1927,user32.dll-
复制代码
示例10: 测试网络是否可用
  1. dllcall IsNetworkAlive,%p0x1,sensapi.dll
  2. :: 返回1可用,返回0不可用。
复制代码
示例11: 模拟键盘按键
  1. start "" notepad.exe
  2. for /f %%i in ('dllcall -r# FindWindowA#"Notepad"##user32.dll') do set hPad=%%i
  3. dllcall ShowWindow,%hPad%,3,user32.dll-
  4. dllcall Sleep,1000,kernel32.dll-
  5. ::发送Alt+H 按键
  6. dllcall PostMessageA,%hPad%,0x104,0x48,0x20210001,user32.dll-
  7. dllcall Sleep,1000,kernel32.dll-
  8. ::发送A 按键
  9. dllcall PostMessageA,%hPad%,0x100,0x41,0,user32.dll-
  10. dllcall Sleep,2000,kernel32.dll-
  11. dllcall PostMessageA,%hPad%,0x12,,,user32.dll-
  12. pause
复制代码
示例12: plink cmd命令提示符窗口隐藏运行
  1. @echo off
  2. set cmdTitle=plink
  3. title %cmdTitle%
  4. for /f %%i in ('dllcall -r# FindWindowA##%cmdTitle%#user32.dll') do set hCmd=%%i
  5. dllcall ShowWindow,%hCmd%,,user32.dll-
  6. :: 443 远程ssh端口, 3390 本地socks端口
  7. plink -v -N ssh.com -l root -pw 123456 -P 443 -D 3390
复制代码
================================================================================================

---------------------------------------------
官网: http://www.vinoca.org/2011/08/25/dllcall/
---------------------------------------------
1

评分人数

    • cutebe: 好东西,虽迟但到。技术 + 1

  1. :: 创建VPN.bat
  2. @echo off
  3. :: -------- 创建 L2TP VPN
  4. set VPN_名称=VPN测试
  5. set VPN_IP=1.2.3.4
  6. dllcall createConn,"%VPN_名称%","%VPN_IP%",Create_L2TP_VPN.dll
  7. :: -------- 打开网络连接
  8. start ::{7007acc7-3202-11d1-aad2-00805fc1270e}
  9. ::::::::::::::::::::::::::::::::::::::::::::::::::::
  10. :: Create_L2TP_VPN.dll 出处:
  11. :: http://www.autoitx.com/redirect.php?goto=findpost&ptid=6046&pid=40774&fromuid=7662608
  12. ::::::::::::::::::::::::::::::::::::::::::::::::::::
复制代码

TOP

返回列表