?? 用批處理調用api實現文件下載.txt
字號:
[組圖]記用BAT(批處理腳本)實現文件下載功能 熱 薦 【字體:小 大】
閑來無事之--記用BAT(批處理腳本)實現文件下載功能
作者:ZV(ZVROP… 文章來源:s8s8.net 點擊數:4864 更新時間:2004-8-19
作者:ZV(ZVROP)
郵件:zvrop@163.com
主頁:(被整頓掉老~~~~~>_<~~~~~~)
網站:http://www.s8s8.net
日期:2004-8-18
轉載請保全文檔完整,謝謝
寫的倉卒繁多,錯漏難免,還請各位給予斧正.
有什么問題,可以給我發email.^_^...
目錄:
一.寫在前面的話
二.故事的起因
三.解決-腹稿
四.解決-實戰
五.解決-打造
六.包裝
七.小節
八.后記
九,參考文獻
正文開始:
一.寫在前面的話
這篇文檔講述的并不是什么新鮮的技術,我只是起到將他們混和起來實現了自己需要的功能的作用,如果你對批處理和PE格式相當了解,那我的這篇文檔就權且當作瀏覽溫習吧...^_^...
另外,由于我本人廢話比較多,這也是不想給雜志寫稿子的主要原因,給我干癟癟的3000字能講出什么來,不如這樣沒有限制的爽快(當然也沒什么報酬...一_一..),所以也為了防止你在看文章的途中睡著,請自備小錐子一把.....
最后,這篇文檔說是用批處理下載文件,其實它包含了很多方面的知識,如果有時間,不妨一看哈,^_^,開始買瓜了..
二.故事的起因
最初萌發這個想法的是不久前,在論壇(廣告一下:http://www.s8s8.net)上的UNIX SHELL板塊有個會員發了一篇帖子,內容是用BASH SHELL寫的一個成批下載圖片的腳本(其實是H圖片...一_一..),接下來跟貼那個多啊...,有繁衍出PHP的,VBS的,C的,C#的,JAVA的,甚至交流到多線程,斷點續傳....引用花大哥的一句話"無語,為了MM照片,大家的動力都很足啊!"...汗~~..
在發了一份PHP和C的代碼后(感覺我動力特足~大色狼...一_一..),覺得很簡單(因為用C或者PHP等腳本來實現文件的下載本來就是很基礎的東西)我就開始想用微軟最原始的腳本--Batch(批處理)來嘗試實現(本文標題中的"閑來無事"就是紀念此處,一_一.),這似乎有點不可思議,因為批處理幾乎沒有實現的支持網絡的功能(當然,如果你說你能用TELNET下載到文件的我是很佩服的..一_一..),但也不是完全沒有辦法,畢竟WINDOWS里面能用的東西這么多,沒有完不成的事情....在這種挑戰的勾引下,我完成了用批處理下載文件的功能....現在讓我一步一步回放我的思路,揭開用批處理下載文件的奧秘...
三.解決-腹稿
如果用批處理來下載文件的話,肯定會馬上想到Cscript腳本(或者是JAVA腳本),那是當然,太多的批處理腳本實現一些本身并不可能實現的功能的時候都是采用ECHO出一個其他腳本的方法來解決.可是我們的目的就在于用批處理實現下載的功能,如果要用VBS來幫忙的話不如直接寫VBS了.這個想法順即告吹....
再來,記得以前有流行過一陣用RUNDLL32來加載DLL中的API,似乎和我們需要的目的沾邊,因為下載文件能用的API太多了,如果RUNDLL能調用,那最好不過了.于是我打開MSDN,找了一個API: URLDownloadToFile
URLDownloadToFile函數原型:
代碼
HRESULT URLDownloadToFile(
LPUNKNOWN pCaller,
LPCTSTR szURL,
LPCTSTR szFileName,
DWORD dwReserved,
LPBINDSTATUSCALLBACK lpfnCB
);
URLDownloadToFile函數的一些信息:
引用
Header Urlmon.h
Import library Urlmon.lib
Minimum availability Internet Explorer 3.0
Minimum operating systems Windows NT 4.0, Windows 95
根據這些,我們可以知道,這個API是在URLMON.DLL文件中的一個導出函數,簡單的實現了把一個文件從WEB服務器下載本機的功能,其實用這個函數還不錯的,至少它幫我們處理了斷點續傳,緩存等等的功能,比起直接使用SOCKET函數來實現或者用WININET里的函數來實現簡單多得多了.
URLDownloadToFile有五個參數:
第一個參數是僅當調用者是一個ActiveX對象才使用,一般為NULL.
第二個參數就是要下載文件的目標URL,完整路徑.
第三個是本地保存路徑,也是完整路徑
第四個是保留,必須為0
第五個是指向一個IBindStatusCallback接口的指針,這就類似一種回調機制,你可以參考這些來活動當前下載進度,選擇是否繼續下載等等.
這里面我們只關心第二和第三個參數.其他的通通設置成0.(當然你寫C的時候最好設置為NULL)
嗯,敲了點鍵盤介紹了這個函數,是因為整篇的文檔都和這個函數息息相關,有了這個函數,就可以呼叫RUNDLL32來調用它,但是很可惜,這個美好的計劃馬上也破裂了...
我去微軟看了他們的164787號文檔(http://support.microsoft.com/default.aspx?...kb;en-us;164787),該文檔闡述了RUNDLL32的調用方式和能被他調用的函數的格式:
它們是這么說的:
引用
Rundll and Rundll32 programs do not allow you to call any exported function from any DLL. For example, you can not use these utility programs to call the Win32 API (Application Programming Interface) calls exported from the system DLLs. The programs only allow you to call functions from a DLL that are explicitly written to be called by them.
這個是規定的格式:
代碼
void CALLBACK
EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
很不幸,我們的URLDownloadToFile小兄弟并沒有符合這些條件,被RUNDLL32無情的拋棄了(汗一滴..)...但是我們并沒有因此而嫌棄它(汗一滴AGAIN..),畢竟,在后來實現的過程里,它是為我們的工作省下了不少功夫.
到此,用RUNDLL32運行計劃流產....(寒...)
想了一根煙功夫,現在URLDownloadToFile有了,怎么才能調用這個函數呢?總不能模仿匯編PUSH 5個參數進棧,然后CALL吧,那這個函數的地址還要用LoadLibrary()和GetProcAddress()計算得來,那這兩個函數的地址.....還是放棄...等等,如果用一個EXE來實現的話就簡單很多了(至少EXE是不需要任何解釋器的),對,寫一個EXE來下載文件.可我們的目的是用BAT來下載呢,BAT文件能包裹EXE的數據嗎?答案是肯定的...往下看..
記得以前看過一篇文檔<<Do All in Cmd Shell>>里面介紹過一種方法.先賣個關子.大家都知道,如果用ECHO加上重定向符來寫文件的話,只能寫入ASCII的一部分,也就可以顯示出來的那些ASCII(也就是ASCII值小于128的那些),對于那些無法顯示的字符就沒有辦法了.但是這讓我們想起一個工具,一個微軟歷史上同樣古老的,批處理的兄弟--DEBUG!
現在思路清晰了:可以讓批處理把ECHO不能顯示的字符轉化為16進制數據(比如EXE中的那些數據)保存在批處理中,然后用DEBUG寫道文件里,最后用BAT調用生成的EXE,下載文件!(想完了這里,我感覺還是太麻煩,不知道哪位牛人對這個實現還有什么更加簡單的辦法嗎??)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -