首页 文章

如何在不使用任何外部工具的情况下下载包含批处理文件的文件?

提问于
浏览
13

首先澄清这个问题的目的是HTTP(s)下载 . 对于FTP,我可能会问(并回答)另一个问题 . 这是some similar questions - 但我希望更精确 .

除了排除外部工具,我希望解决方案适用于最广泛类型的Windows机器(包括仍然有足够大份额的XP,Win2003,Vista) . 另外,由于 WSH 是可能的选项之一,我不喜欢使用临时文件,所有内容都要打包在一个 .bat 文件中(jscript和vbscript都可以) .

什么是可能的方法 .

带有BITSADMIN

  • "Pure"批处理解决方案 - 每个Windows机器上都有一个命令行实用程序 . 它不是很方便,但它是唯一一个不应该使用其他脚本语言的选项 .

  • 使用WSH - 可能有三种方法 - WinHTTPMSXML2.XMLHTTPInternetExlorer.Application - 所有这些方法都是可访问的ActiveX对象,按我喜欢的顺序排列.WinHTTP和MSXML2.XMLHTTP的功能非常相似,但WinHTTP的声誉更稳定 . InternetExlorer.Application实际上只是可以通过ActiveX对象访问的Internet Explorer,而且一些UI元素是不可避免的(是吗?)所以我会跳过这个 .

  • 使用.NET - 它's possible to create a hybrid batch file with all the three default .NET compilers (Jscript.net , VB.Net , C#) with Jscript.net there is no redundant error messages so I'我更喜欢它 . 如果我们忽略了一个已编译的.exe的事实,所有代码都在一个文件中,所以据我所知,这符合要求:-) . 使用.NET我们可以使用System .Net.WebClient或System.Net.HttpWebRequest(WebClient依赖它)或
    System.Web.HttpRequest,但是现在我'll post only System.Net.WebClient solution.And even more same ActiveX objects accessible with WSH are available here too.So there are really many ways to dowanload a file with .Net.May be in the future I' ll更新了我的答案 . 无论如何,只有Webclient是专门为下载而设计的 .

  • 使用powershell - 与.NET具有相同的可能性,但在你可以遇到的所有机器上安装的机会较少 . 所以我也会跳过这个 .

1 回答

  • 32

    答案 . 所有脚本都应该使用 .bat / .cmd 扩展名保存,并且可以直接用作批处理脚本 .

    1)Certutuil

    certutil.exe -urlcache -split -f "https://download.sysinternals.com/files/PSTools.zip" pstools.zip
    

    CertUtil命令可以被滥用来从Internet下载文件 . 默认情况下,自Windows Vista以来可以在Windows中使用 . 对于WinXP Server 2003管理工具是必需的 .

    2) Bitsadmin

    最简单的方法来使用它

    bitsadmin /transfer myDownloadJob /download /priority normal http://downloadsrv/10mb.zip c:\10mb.zip
    

    或者(如果要添加凭据,代理等,最终将需要此功能)

    @echo off
        setlocal
    
        :: uses bitsadmin utility to download a file
        :: bitsadmin is not available in winXP Home edition
        :: the only way to download a file with 'pure' batch
       :download
    
        if "%2" equ "" (
          call :help
          exit /b 5
       )
    
       if "%1" equ "" (
          call :help
          exit /b 6
       )
        set url=%~1
        set file=%~2
        rem ----
        if "%~3" NEQ "" (
            set /A timeout=%~3
        ) else (
            set timeout=5
        )
    
        bitsadmin /cancel download >nul
        bitsadmin /create /download download >nul 
        call bitsadmin /addfile download "%url%" "%CD%\%file%" >nul
        bitsadmin /resume download >nul 
        bitsadmin /setproxysettings download AUTODETECT >nul
    
        set /a attempts=0
        :repeat
        set /a attempts +=1
        if "%attempts%" EQU "10" (
            echo TIMED OUT
            endlocal
            exit /b 1
        )
        bitsadmin /info download /verbose | find  "STATE: ERROR"  >nul 2>&1 && endlocal &&  bitsadmin /cancel download && echo SOME KIND OF ERROR && exit /b 2
        bitsadmin /info download /verbose | find  "STATE: SUSPENDED" >nul 2>&1 && endlocal &&  bitsadmin /cancel download &&echo FILE WAS NOT ADDED && exit /b 3
        bitsadmin /info download /verbose | find  "STATE: TRANSIENT_ERROR" >nul 2>&1 && endlocal &&  bitsadmin /cancel download &&echo TRANSIENT ERROR && exit /b 4
        bitsadmin /info download /verbose | find  "STATE: TRANSFERRED" >nul 2>&1 && goto :finishing 
    
       w32tm /stripchart /computer:localhost /period:1 /dataonly /samples:%timeout%  >nul 2>&1
        goto :repeat
        :finishing 
        bitsadmin /complete download >nul
        echo download finished
        endlocal
       goto :eof
    
       :help
       echo %~n0 url file [timeout]
       echo.
       echo  url - the source for download
       echo  file - file name in local directory where the file will be stored
       echo  timeout - number in seconds between each check if download is complete (attempts are 10)
       echo.
       goto :eof
    

    3) - WinHttp and WSH(SSL /证书和代理选项从未经过测试......) . Here是一个使用WinHttpRequest的即用型脚本 . 它可以执行所有的http请求,也可以用于下载文件(不是太大的文件) . 如果需要,还可以添加自己的身份验证标头 .

    call winhhtpjs.bat https://example.com/files/some.zip -saveTo c:\somezip.zip
    

    4) MSXML2.XMLHTTP and WSH (更好地使用WinHTTP)(SSL /证书和代理选项从未经过测试......)

    @if (@X)==(@Y) @end /* JScript comment
        @echo off
    
        rem :: the first argument is the script name as it will be used for proper help message
        cscript //E:JScript //nologo "%~f0" "%~nx0" %*
    
        exit /b %errorlevel%
    
    @if (@X)==(@Y) @end JScript comment */
    
    // used resources
    //http://www.codeproject.com/Tips/506439/Downloading-files-with-VBScript
    //http://blogs.msdn.com/b/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx
    //https://msdn.microsoft.com/en-us/library/ie/ms535874(v=vs.85).aspx
    //https://msdn.microsoft.com/en-us/library/aa923283.aspx
    //https://msdn.microsoft.com/en-us/library/ms759148(v=vs.85).aspx
    //https://msdn.microsoft.com/en-us/library/ms759148(v=vs.85).aspx
    //https://msdn.microsoft.com/en-us/library/ms760236(v=vs.85).aspx
    //http://stackoverflow.com/questions/20712635/providing-authentication-info-via-msxml2-serverxmlhttp
    //https://msdn.microsoft.com/en-us/library/ms763680(v=vs.85).aspx
    //https://msdn.microsoft.com/en-us/library/ms757849(v=vs.85).aspx
    //http://fm4dd.com/programming/shell/microsoft-vbs-http-download.htm
    //http://stackoverflow.com/questions/11573022/vba-serverxmlhttp-https-request-with-self-signed-certificate
    //http://www.qtcentre.org/threads/44629-Using-XMLHttpRequest-for-HTTPS-Post-to-server-with-SSL-certificate
    
    // global variables and constants
    var ARGS = WScript.Arguments;
    var scriptName=ARGS.Item(0);
    
    var url="";
    var saveTo="";
    
    var user=0;
    var pass=0;
    
    var proxy=0;
    var bypass="";
    var proxy_user=0;
    var proxy_pass=0;
    
    var certificate=0;
    
    var force=true;
    
    //ActiveX objects
    //Use the right version of MSXML
    /*var progIDs = [ 'Msxml2.DOMDocument.6.0', 'Msxml2.DOMDocument.5.0', 'Msxml2.DOMDocument.4.0', 'Msxml2.DOMDocument.3.0', 'Msxml2.DOMDocument' ]
    for (var i = 0; i < progIDs.length; i++) {
        try {
            var XMLHTTPObj = new ActiveXObject(progIDs[i]);
        }catch (ex) {       
        }
    }
    
    if typeof  XMLHTTPObj === 'undefined'{
        WScript.Echo ("You are using too ancient windows or you have no installed IE");
        WScript.Quit(1);
    }*/
    
    var XMLHTTPObj = new ActiveXObject("MSXML2.XMLHTTP");
    var FileSystemObj = new ActiveXObject("Scripting.FileSystemObject");
    var AdoDBObj = new ActiveXObject("ADODB.Stream");
    
    
    function printHelp(){
        WScript.Echo(scriptName + " - downloads a file through HTTP");
        WScript.Echo(scriptName + " url localfile [-force yse|no] [-user username -password password] [-proxy proxyserver:port -bypass bypass_list]");
        WScript.Echo("                          [-proxyuser proxy_username -proxypassword proxy_password] [-certificate certificateString]");
        WScript.Echo("-force  - decide to not or to overwrite if the local exists");
        WScript.Echo("proxyserver:port - the proxy server");
        WScript.Echo("bypass- bypass list can be \"\" if you don't need it");
        WScript.Echo("proxy_user , proxy_password - credentials for proxy server");
        WScript.Echo("user , password - credentials for the server");
        WScript.Echo("certificate - location of SSL certificate");
        WScript.Echo("Example:");
        WScript.Echo(scriptName +" http://somelink.com/somefile.zip c:\\somefile.zip -certificate \"LOCAL_MACHINE\\Personal\\My Middle-Tier Certificate\"");    
    }
    
    function parseArgs(){
        //
        if (ARGS.Length < 3) {
            WScript.Echo("insufficient arguments");
            printHelp();
            WScript.Quit(43);
        }
        url=ARGS.Item(1);
        saveTo=ARGS.Item(2);
    
        if(ARGS.Length % 2 != 1) {
            WScript.Echo("illegal arguments");
            printHelp();
            WScript.Quit(44);
        }
    
        for (var i=3;i<ARGS.Length-1;i=i+2){
            if(ARGS.Item(i).toLowerCase=="-force" && ARGS.Item(i+1)=='no'){
                force=false;
            }
    
            if(ARGS.Item(i).toLowerCase=="-user"){
                user=ARGS.Item(i+1);
            }
    
            if(ARGS.Item(i).toLowerCase=="-password"){
                pass=ARGS.Item(i+1);
            }
    
            if(ARGS.Item(i).toLowerCase=="-proxy"){
                proxy=ARGS.Item(i+1);
            }
    
            if(ARGS.Item(i).toLowerCase=="-bypass"){
                bypass=ARGS.Item(i+1);
            }
    
            if(ARGS.Item(i).toLowerCase=="-proxyuser"){
                proxy_user=ARGS.Item(i+1);
            }
    
            if(ARGS.Item(i).toLowerCase=="-proxypassword"){
                proxy_pass=ARGS.Item(i+1);
            }
    
            if(ARGS.Item(i).toLowerCase=="-certificate"){
                certificate=ARGS.Item(i+1);
            }
        }
    }
    
    function existsItem(path){
        return FileSystemObj.FolderExists(path)||FileSystemObj.FileExists(path);
    }
    
    stripTrailingSlash = function(path){
        while (path.substr(path.length - 1,path.length) == '\\') {
            path=path.substr(0, path.length - 1);
        }
        return path;
    }
    
    function deleteItem(path){
        if (FileSystemObj.FileExists(path)){
            FileSystemObj.DeleteFile(path);
            return true;
        } else if (FileSystemObj.FolderExists(path) ) {
            FileSystemObj.DeleteFolder(stripTrailingSlash(path));
            return true;
        } else {
            return false;
        }
    }
    
    function writeFile(fileName,data ){
        AdoDBObj.Type = 1;       
        AdoDBObj.Open();
        AdoDBObj.Position=0;
        AdoDBObj.Write(data);
        AdoDBObj.SaveToFile(fileName,2);
        AdoDBObj.Close();   
    }
    
    function download( url,file){
        if (force && existsItem(file)){
            if(!deleteItem(file)){
                WScript.Echo("Unable to delete "+ file);
                WScript.Quit(8);
            }
        }else if (existsItem(file)){
            WScript.Echo("Item " + file + " already exist");
            WScript.Quit(9);
        }
    
    
    
        if (proxy!=0 && bypass !="") {
            //https://msdn.microsoft.com/en-us/library/ms760236(v=vs.85).aspx
            XMLHTTPObj.setProxy(SXH_PROXY_SET_DIRECT,proxy,bypass);
        } else if (proxy!=0) {
            XMLHTTPObj.setProxy(SXH_PROXY_SET_DIRECT,proxy,"");
        }
    
    
    
        if (proxy_user!=0 && proxy_pass!=0 ) {
            //https://msdn.microsoft.com/en-us/library/ms763680(v=vs.85).aspx
            XMLHTTPObj.setProxyCredentials(proxy_user,proxy_pass);
        }
    
        if(certificate!=0) {
            //https://msdn.microsoft.com/en-us/library/ms763811(v=vs.85).aspx
            WinHTTPObj.setOption(3,certificate);
        }
    
        if (user!=0 && pass!=0){
            //https://msdn.microsoft.com/en-us/library/ms757849(v=vs.85).aspx
             XMLHTTPObj.Open('GET',url,false,user,pass);
        } else {
            XMLHTTPObj.Open('GET',url,false);
        }
    
    
    
        XMLHTTPObj.Send();
        var status=XMLHTTPObj.Status
    
        switch(status){
            case 200:
                WScript.Echo("Status: 200 OK");
                break;
            case 401:
                WScript.Echo("Status: 401 Unauthorized");
                WScript.Echo("Check if correct user and password were provided");
                WScript.Quit(401);
                break;
            case 407:
                Wscript.Echo("Status:407 Proxy Authentication Required");
                Wscript.Echo("Check if correct proxy user and password were provided");
                WScript.Quit(407);
                break;
            default:
                Wscript.Echo("Status: "+status);
                WScript.Echo("Try to help yourself -> https://en.wikipedia.org/wiki/List_of_HTTP_status_codes");
                WScript.Quit(status);
        }
        writeFile(file,XMLHTTPObj.ResponseBody);
    }
    
    function main(){
        parseArgs();
        download(url,saveTo);
    }
    main();
    

    5) .NET and webclient (这里没有SSL选项 . 请尝试添加它.Poxy选项从未经过测试)

    @if (@X)==(@Y) @end /* JScript comment
    @echo off
    setlocal
    
    for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d  /o:-n "%SystemRoot%\Microsoft.NET\Framework\*jsc.exe"') do (
       set "jsc=%%v"
    )
    
    ::if not exist "%~n0.exe" (
        "%jsc%" /nologo /out:"%~n0.exe" "%~dpsfnx0"
    ::)
    
     %~n0.exe %*
    
    endlocal & exit /b %errorlevel%
    
    
    */
    
    //todo SSL Support
    //todo Better help message
    //todo check if local file exists
    
    
    import System;
    import System.Net.WebClient;
    import System.Net.NetworkCredential;
    import System.Net.WebProxy;
    import System.Uri;
    import System.Security.Cryptography.X509Certificates;
    
    var arguments:String[] = Environment.GetCommandLineArgs();
    
    var url=0;
    var toFile=0;
    var force=true;
    
    var user=0;
    var password=0;
    
    var proxy=0;
    var bypass=0;
    var proxy_user=0;
    var proxy_pass=0;
    
    var certificate=0;
    
    function printHelp(){
        Console.WriteLine(arguments[0] + "download from url to a file");
        Console.WriteLine(arguments[0] + "<url> <file> [-user user -password password] [-proxy proxy] [-proxy_user proxy.user -proxy_pass proxy.pass]");
    
    }
    
    function parseArgs(){
    
        if (arguments.length < 3) {
            Console.WriteLine("Wrong arguments");
            printHelp();
            Environment.Exit(1);
        }
    
        if (arguments.length %2 != 1) {
            Console.WriteLine("Wrong number arguments");
            printHelp();
            Environment.Exit(2);    
        }
    
        url=arguments[1];
        toFile=arguments[2];
    
        for (var i=3;i<arguments.length-1;i=i+2){
            var arg=arguments[i].ToLower();
            switch (arg){
                case  "-user" :
                    user=arguments[i+1];
                    break;
                case "-password" :
                    password=arguments[i+1];
                    break;
                case "-proxy" :
                    proxy=arguments[i+1];
                    break;
                case "-proxy_user" :
                    proxy_user=arguments[i+1];
                    break;
                case "-proxy_pass" :
                    proxy_pass=arguments[i+1];
                    break;
                case "-bypass" :
                    bypass=[arguments[i+1]];
                    break;
                /*case "-certificate" :
                    certificate=arguments[i+1];
                    break;*/
                default:
                    Console.WriteLine("Invalid argument "+ arguments[i]);
                    printHelp();
                    Environment.Exit(3);
            }
        }
    
    }
    
    function download(){
        var client:System.Net.WebClient = new System.Net.WebClient();
    
        if (user!=0 && password!=0){
            client.Credentials=new System.Net.NetworkCredential(user, password);
        }
    
        if (proxy!=0){
            var webproxy =new System.Net.WebProxy();
            webproxy.Address=new Uri(proxy);
            if (proxy_user!=0 && proxy_pass!=0){
                webproxy.Credentials=new System.Net.NetworkCredential(proxy_user,proxy_pass);
            }
            webproxy.UseDefaultCredentials =false;
    
            if (bypass!=0){
                webproxy.BypassList=bypass;
                webproxy.BypassProxyOnLocal = false;
            }
            client.Proxy=webproxy;
        }
    
        try {
            client.DownloadFile(arguments[1], arguments[2]);
        } catch (e) {
            Console.BackgroundColor = ConsoleColor.Green;
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("\n\nProblem with downloading " + arguments[1] + " to " + arguments[2] + "Check if the internet address is valid");
            Console.ResetColor();
            Environment.Exit(5);
        }
    }
    
     parseArgs();
     download();
    

相关问题