VBScript下载并执行FTP上的文件

By | 2012/09/23

 

代码更新: 2013/1/11

解决本地文件夹或文件名中有空格的问题

 


 

代码更新: 2012/9/25

去除ping小黑窗

优化代码结构


 

代码已更新  2012/9/24

下载全部文件

 


 

1. 程序只会下载含有关键字(forme)的文件   

2. 程序只会执行vbs 或者 bat类型的文件(如果需要可自行添加更多的文件支持)

3. 如果需要更新当前程序,新文件(ftp上的文件)需要包含关键字(syncftp)

4. 如果本地有同名文件,程序不会进行下载

5. 如果本地程序已执行过,则不会再次执行

6. 程序运行时会生成两个文件,一个是log文件,一个是配置文件

7. 如果需要定时执行,可以写为计划任务

 

代码如下:

 

 

'***********************************************************************************
'*
'* File:        SyncVbs - FtpAndLocal
'* Author:      moose
'* Email:       852354673@qq.com
'* Site:        www.pystack.org
'* Created:     2012/9/10
'* Last Modified:   2012/9/20
'* Version:     0.3
'*
'***********************************************************************************
Const secureKey = "U3luY1ZicyAtIEZ0cEFuZExvY2Fs"
 
startTime = Now()
currVbsName = WScript.ScriptName
currVbsPath = WScript.ScriptFullName
currVbsDir = Left(currVbsPath,InStrRev(currVbsPath,"\"))
 
 
'生成日志文件
logFileName = "syncvbs.log"
logFilePath = currVbsDir & logFileName
Set fs = CreateObject("scripting.filesystemobject")
Set ws = CreateObject("wscript.shell")
Set logFileObject = fs.OpenTextFile(logFilePath,8,True)
logFileObject.WriteLine "********************************** " &Now& " **********************************"
 
 
'检查当前文件是否合法
If Not isALegalFile(currVbsName,secureKey) Then
    logFileObject.WriteLine Time & "  Illegal file : " & currVbsName
    logFileObject.WriteBlankLines 4
    logFileObject.Close
    WScript.Quit
End If
 
 
'ftp相关配置
Const ftp_server = "192.168.8.123"
Const ftp_user = "moose"
Const ftp_password = "moose"
Const ftp_remoteDir = "\"
Const ftp_localDir = "D:\ftptest\"
Const ftp_remoteFile = "*"
Const ftp_configFile = "listfiles.ini"
 
 
'生成本地文件列表
If "" = Trim(ftp_localDir) Then
    logFileObject.WriteLine Time & "  Variable(ftp_localDir) is null..."
    logFileObject.WriteBlankLines 4
    logFileObject.Close
    WScript.Quit
End If
localFileNamesStr = getLocalFileList(ftp_localDir)
 
 
'检查网络是否连接
If "" = Trim(ftp_server) Then   '如果远程IP为空,则退出程序
    logFileObject.WriteLine Time & "  Variable(ftp_server) is null..."
    logFileObject.WriteBlankLines 4
    logFileObject.Close
    WScript.Quit
End If
 
If Not isFtpAccessable(ftp_server) Then     '如果网络不连通,则退出程序
    logFileObject.WriteLine Time & "  Ip(" &ftp_server& ") is not accessable..."
    logFileObject.WriteBlankLines 4
    logFileObject.Close
    WScript.Quit
End If
 
 
'生成远程ftp文件列表
If Trim(ftp_user) = "" Then
    ftp_user = "Anonymous"
End If
If Len(Trim(ftp_remoteDir)) = 0 Then
    ftp_remoteDir = "\"
End If
remoteFileNamesStr = getRemoteFileList(ftp_server,ftp_user,ftp_password,ftp_remoteDir)
 
If "" = remoteFileNamesStr Then     '如果远程文件为空,则退出程序
    logFileObject.WriteLine Time & "  No file in remote directory..."
    logFileObject.WriteBlankLines 4
    logFileObject.Close
    WScript.Quit
End If
 
 
'检查远程文件是否与本地文件同名
unSameFileNameStr = removeSameFile(localFileNamesStr,remoteFileNamesStr)
If "" = unSameFileNameStr Then      '如果非同名文件为空,则退出程序
    logFileObject.WriteLine Time & "  No file need to be download..."
    logFileObject.WriteBlankLines 4
    logFileObject.Close
    WScript.Quit
End If
 
 
'下载远程文件
downloadRemoteFile ftp_server,ftp_user,ftp_password,ftp_localDir,ftp_remoteDir,unSameFileNameStr
 
 
'执行下载完毕的文件
executeFiles(unSameFileNameStr)
 
 
'文件结束
 
logFileObject.WriteLine Time & "  Done"
logFileObject.WriteLine "Time used: " & DateDiff("s",startTime,Now) & "s"
logFileObject.WriteBlankLines 4
logFileObject.Close
 
 
'********************************************************************
'*
'* Function updateThisFile(str_fileToUpdate)
'* Purpose: 更新当前脚本
'* Input:   str_fileToUpdate: 新脚本名称
'* Output:  
'*
'********************************************************************
Function updateThisFile(str_fileToUpdatePath)
    fs.DeleteFile currVbsPath,True
    fs.MoveFile str_fileToUpdatePath,currVbsPath
End Function
 
 
 
'********************************************************************
'*
'* Function executeFiles(str_filesPath)
'* Purpose: 执行下载完的文件
'* Input:   str_filesPath: 本地文件串
'* Output:  True/False
'*
'********************************************************************
Function executeFiles(str_filesPath)
    logFileObject.WriteLine Time & "  Executing files..."
    filesNeedToExec_obj = Split(str_filesPath,",")
    fileExecutedCount_int = 0
    failToExecuteCount_int = 0
     
    For Each fileToExec_str In filesNeedToExec_obj
        '获得文件后缀
        fileType_str = Right(fileToExec_str,Len(fileToExec_str)-InStrRev(fileToExec_str,"."))
        fileType_str = Trim(LCase(fileType_str))
         
        If InStr(fileType_str, "vbs")>0 Or InStr(fileType_str, "bat")>0 Then     
            fileToExecPath_str = ftp_localDir & fileToExec_str
            'WScript.Echo fileType_str & " : " & fileToExecPath_str
            'WScript.Echo Asc(Right(fileToExecPath_str,1))
            'fileToExecPath_str = Left(fileToExecPath_str,Len(fileToExecPath_str)-1)    '为什么要减1
            'WScript.Echo fileToExecPath_str
             
            If fs.FileExists(fileToExecPath_str) Then
                If InStr(LCase(fileToExec_str),"syncvbs")>0  Then 
                    updateThisFile(fileToExecPath_str)
                else
                    logFileObject.WriteLine Time & "  Executing file (" &fileToExec_str& ")"
                    fileToExecPath_str = """" &fileToExecPath_str& """"        
                     
                    ws.Run fileToExecPath_str,0,True
                    fileExecutedCount_int = fileExecutedCount_int + 1
                    logFileObject.WriteLine Time & "  Done"
                End If
            Else
                logFileObject.WriteLine Time & "  Error:File (" &fileToExec_str& ") not downloaded..."
                failToExecuteCount_int = failToExecuteCount_int + 1
            End If 
        End If
    Next
     
    logFileObject.WriteLine Time & "  Executed(" &fileExecutedCount_int& ")    Failed(" &failToExecuteCount_int& ")"
    logFileObject.WriteBlankLines 1
End Function
 
 
 
'********************************************************************
'*
'* Function downloadRemoteFile(str_server,str_user,str_password,str_localDir,str_remoteDir,str_remoteFiles)
'* Purpose: 获得远程目录的文件列表
'* Input:   str_server: 远程主机地址
'*          str_user:ftp用户名
'*          str_password:ftp密码
'*          str_localDir:本地目录
'*          str_remoteDir:远程目录
'*          str_remoteFiles:待下载文件
'* Output:  null
'*
'********************************************************************
Function downloadRemoteFile(str_server,str_user,str_password,str_localDir,str_remoteDir,str_remoteFiles)
    '如果需要下载的文件为空,则退出function
    If "" = str_remoteFiles Then
        logFileObject.WriteLine Time & "  No file need to download..."
        Exit Function
    End If
     
    '处理路径中的空格
    str_remoteDir = Trim(str_remoteDir)
    If InStr(str_remoteDir," ")>0 Then
        If Left(str_remoteDir,1)<> """" And Right(str_remoteDir,1) <> """" Then
            str_remoteDir = """" &str_remoteDir& """"
        End If
    End If
     
    '设置工作路径
    originalWorkingDirectory = ws.CurrentDirectory
    ws.CurrentDirectory = str_localDir
     
    '生成ftp命令
    ftpScript_str = ""
    ftpScript_str = ftpScript_str & "USER " & str_user & vbCrLf 
    ftpScript_str = ftpScript_str & str_password & vbCrLf 
    ftpScript_str = ftpScript_str & "cd " & str_remoteDir & vbCrLf 
    ftpScript_str = ftpScript_str & "binary" & vbCrLf 
    ftpScript_str = ftpScript_str & "prompt off" & vbCrLf 
     
    remoteFiles_obj = Split(str_remoteFiles,",")    
    For Each remoteFile_str In remoteFiles_obj
        'remoteFile_str = Left(remoteFile_str,Len(remoteFile_str)-1)    '去除回车符(为什么会有换行符?)
        If InStr(remoteFile_str, " ")>0 Then
            remoteFile_str = """" & remoteFile_str & """"
        End If
        ftpScript_str = ftpScript_str & "get " & remoteFile_str & vbCrLf    
    Next
 
    ftpScript_str = ftpScript_str & "bye" & vbCrLf & "quit" & vbCrLf & "quit" & vbCrLf 
     
    '创建临时文件
    tempDir_str = ws.ExpandEnvironmentStrings("%TEMP%")
    scriptFilePath_str = tempDir_str& "\" &fs.GetTempName
    ftpResultPath_str = tempDir_str& "\" &fs.GetTempName
     
    '临时ftp脚本文件
    Set scriptFile_obj = fs.OpenTextFile(scriptFilePath_str,2,True)
    scriptFile_obj.Write(ftpScript_str)
    scriptFile_obj.Close
         
    '执行ftp脚本
    logFileObject.WriteLine Time & "  Downloading files from ftp..."
    ws.Run "%comspec% /c FTP -n -s:" &""""&scriptFilePath_str&""""& " " &str_server& " > " &ftpResultPath_str,0,True
    WScript.Sleep 1000
     
    '临时ftp结果文件
    Set resultFile_obj = fs.OpenTextFile(ftpResultPath_str,1)
    successDownloadCount_int = 0
    failToDownloadCount_int = 0
    'WScript.Echo scriptFilePath_str & "  " &ftpResultPath_str
    'WScript.Echo ftpScript_str
     
    Do Until resultFile_obj.AtEndOfStream
        currLine_str = resultFile_obj.ReadLine
        'WScript.Echo currLine_str
         
'       If InStr(currLine_str,"get ")>0 And InStr(currLine_str,"forme")>0 Then 
        If InStr(currLine_str,"get ")>0 Then
            currLine_str = Right(currLine_str,Len(currLine_str)-(InStr(currLine_str,"get ")+3))
            nextLine_str = resultFile_obj.ReadLine
            nextLine_str = resultFile_obj.ReadLine
            nextLine_str = resultFile_obj.ReadLine
             
            If InStr(nextLine_str,"226 Transfer complete")>0 Then
                successDownloadCount_int = successDownloadCount_int + 1
                logFileObject.WriteLine Time & "  Finish downloading file(" &currLine_str& ")"
            Else
                failToDownloadCount_int = failToDownloadCount_int + 1
                logFileObject.WriteLine Time & "  Error:Fail to download file(" &currLine_str& ")"
            End If
        End If
    Loop
    resultFile_obj.Close
     
    logFileObject.WriteLine Time & "  Complete(" &successDownloadCount_int& ")    Failed(" &failToDownloadCount_int& ")"
    logFileObject.WriteBlankLines 1
End Function
 
 
 
'********************************************************************
'*
'* Function removeSameFile(Str_localFiles,str_removeFiles)
'* Purpose: 去除远程文件列表和本地文件列表中相同的文件
'* Input:   Str_localFiles: 本地文件串
'*          str_removeFiles:远程文件串
'* Output:  True/False
'*
'********************************************************************
Function removeSameFile(Str_localFiles,str_removeFiles)
    '如果本地文件列表为空,则退出function
    If "" = Trim(Str_localFiles) Then
        removeSameFile = str_removeFiles
        Exit Function
    End If
     
    unSameFileName_str = ""
    unSameFileCount_int = 0
    saneFileCount = 0
    remoteFiles_obj = Split(str_removeFiles,",")
     
    For Each remoteFile_str In remoteFiles_obj
        'newremoteFile_str = Left(Trim(remoteFile_str),Len(remoteFile_str)-InStrRev(remoteFile_str,"."))  '好奇怪的问题
        If InStr(Str_localFiles,remoteFile_str) > 0  Then
            logFileObject.WriteLine Time & "  File(" &remoteFile_str& ") has been downloaded..."
            saneFileCount = saneFileCount + 1
        Else
            logFileObject.WriteLine Time & "  File(" &remoteFile_str& ") need to download..."
            unSameFileName_str = unSameFileName_str & remoteFile_str & ","
            unSameFileCount_int = unSameFileCount_int + 1
        End If
    Next
     
    logFileObject.WriteLine Time & "  NeedTo Download(" &unSameFileCount_int& ")     Has Downloaded(" &saneFileCount& ")"
    logFileObject.WriteBlankLines 1
         
    '去除最后一个逗号
    If Not "" = Trim(unSameFileName_str) Then
        unSameFileName_str = Left(unSameFileName_str,Len(unSameFileName_str)-1)
    End If
     
    '返回文件列表字符串
    removeSameFile = unSameFileName_str
End Function
 
 
 
'********************************************************************
'*
'* Function getRemoteFileList(str_server,str_user,str_password,str_remoteDir)
'* Purpose: 获得远程目录的文件列表
'* Input:   str_server: 远程主机地址
'*          str_user:ftp用户名
'*          str_password:ftp密码
'*          str_remoteDir:远程目录
'* Output:  文件字符串
'*
'********************************************************************
Function getRemoteFileList(str_server,str_user,str_password,str_remoteDir)
    '处理含有空格的路径,加上引号
    str_remoteDir = Trim(str_remoteDir)
    If InStr(str_remoteDir," ")>0 Then
        If Left(str_remoteDir,1)<> """" And Right(str_remoteDir,1) <> """" Then
            str_remoteDir = """" &str_remoteDir& """"
        End If
    End If
     
    '查看配置文件是否存在,不存在则创建
    fileListScriptConfigPath_str = currVbsDir & ftp_configFile
    If Not fs.FileExists(fileListScriptConfigPath_str) Then
        logFileObject.WriteLine Time & "  Generate file(" &ftp_configFile& ")"
        Set fileListScriptFile_obj = fs.OpenTextFile(fileListScriptConfigPath_str,2,True)
         
        fileListScriptFile_obj.WriteLine "USER " & str_user
        fileListScriptFile_obj.WriteLine str_password
        fileListScriptFile_obj.WriteLine "cd " & str_remoteDir
        fileListScriptFile_obj.WriteLine "ls"
        fileListScriptFile_obj.WriteLine "bye"
        fileListScriptFile_obj.WriteLine "quit" 
        fileListScriptFile_obj.WriteLine "quit" 
        fileListScriptFile_obj.Close
         
        logFileObject.WriteLine Time & "  Done"
        logFileObject.WriteBlankLines 1
    End If
    logFileObject.WriteLine Time & "  Generating remote file list..."
     
    '创建临时文件
    tmpDir_str = ws.ExpandEnvironmentStrings("%TEMP%")
    tmpFilePath_str = tmpDir_str& "\" &fs.GetTempName
    ws.Run "%comspec% /c FTP -n -s:" &"""" &fileListScriptConfigPath_str& """"& " " &str_server& " > " &tmpFilePath_str,0,True
     
    '读取文件,得到文件列表
    '***********************V1**************************
'   Set tempFile_obj = fs.OpenTextFile(tmpFilePath_str,1)
'   remoteFiles_str = ""
'   needToBeDownload_int = 0
'   Do Until tempFile_obj.AtEndOfStream
'       tempLine_str = tempFile_obj.ReadLine
         
'       If InStr(tempLine_str,"forme")>0 Then    '只下载forme文件
'           remoteFiles_str = remoteFiles_str & tempLine_str & ","
'           needToBeDownload_int = needToBeDownload_int + 1
'       End If 
'   Loop
'   tempFile_obj.Close
    '***********************V1 end***********************
     
     
    '***********************V2**************************
    '找出文件开始行和结束行
    remoteFiles_str = ""
    Set tempFile_obj = fs.OpenTextFile(tmpFilePath_str,1)
    currentLine_int = 1
    startLine_int = 0
    endLine_int = 0
    Do Until tempFile_obj.AtEndOfStream
        tempLine_str = tempFile_obj.ReadLine
        If InStr(tempLine_str,"150") Then
            startLine_int = currentLine_int
        ElseIf InStr(tempLine_str,"226") Then
            endLine_int = currentLine_int
        Else
            currentLine_int = currentLine_int + 1
        End If 
    Loop
    tempFile_obj.Close
    If endLine_int < startLine_int Then
        logFileObject.WriteLine Time & "  (EndLine < StartLine)  No file will download..."
        getRemoteFileList = remoteFiles_str
        Exit Function
    End If
    'WScript.Echo endLine_int & startLine_int
     
    '得到文件列表字符串
    Set tempFile_obj = fs.OpenTextFile(tmpFilePath_str,1)
    currentLine_int = 0
    Do Until tempFile_obj.AtEndOfStream
        currLine_str = tempFile_obj.ReadLine
        currentLine_int = currentLine_int + 1
        If currentLine_int > startLine_int And currentLine_int <= endLine_int Then
            currLine_str = Left(currLine_str,Len(currLine_str)-1)
            remoteFiles_str = remoteFiles_str & currLine_str & ","
        End If
    Loop
    tempFile_obj.Close
    'WScript.Echo remoteFiles_str
    'WScript.Echo tmpFilePath_str
    '***********************V2 end***********************
     
    logFileObject.WriteLine Time & "  There " & endLine_int - startLine_int & " files in remote directory"
    logFileObject.WriteBlankLines 1
     
    '去除最后一个逗号
    If Not "" = Trim(remoteFiles_str) Then
        remoteFiles_str = Left(remoteFiles_str,Len(remoteFiles_str)-1)
    End If
     
    '返回文件列表字符串
    getRemoteFileList = remoteFiles_str
End Function
 
 
 
 
'********************************************************************
'*
'* Function isFtpAccessable(ip_str)
'* Purpose: 检查网络是否连通
'* Input:   str_ipaddr: 远程ftp IP地址
'* Output:  True/False
'*
'********************************************************************
Function isFtpAccessable(str_ipaddr)    
    tmpDir_str = ws.ExpandEnvironmentStrings("%TEMP%")
    tmpFilePath_str = tmpDir_str& "\" &fs.GetTempName
    connand_str = "%comspec% /c ping " & str_ipaddr & " >"&tmpFilePath_str
     
    '**********************V1**********************
    '会弹出小黑窗
'   Set pingResult_obj = ws.Exec(connand_str)
'   result_str = pingResult_obj.StdOut.ReadAll
    '**********************V1 end******************
     
    '**********************V2**********************
    '取消小黑窗
    ws.Run connand_str,0,True
    Set tmpFile_obj = fs.OpenTextFile(tmpFilePath_str,1)
    result_str = tmpFile_obj.ReadAll
    tmpFile_obj.Close
    '**********************V2 end******************
         
    If InStr(result_str,"Minimum")>0 Or InStr(result_str,"最长")>0  Then
        isFtpAccessable = True
    Else
        isFtpAccessable = False
    End If
End Function
 
 
 
'********************************************************************
'*
'* Function getLocalFileList(str_localDir)
'* Purpose: 获得本地目录的文件列表
'* Input:   str_localDir: 本地目录
'* Output:  文件字符串
'*
'********************************************************************
Function getLocalFileList(str_localDir)
    '如果目录不存在,则新建目录
    If Not fs.FolderExists(str_localDir) Then
        logFileObject.WriteLine Time & "  Folder (" &str_localDir& ") not exist..."
        fs.CreateFolder(str_localDir)
        logFileObject.WriteLine Time & "  Finish creating folder (" &str_localDir& ")"
        getLocalFileList = ""
        Exit Function
    End If
         
    localFileNames_str = ""
    LocalFileCount = 0
    Set localDir_obj = fs.GetFolder(str_localDir)
    For Each localFile_obj In localDir_obj.Files
        LocalFileCount = LocalFileCount + 1
        localFileNames_str = localFileNames_str & localFile_obj.Name & ","
    Next
     
    '去除最后一个,号
    If Not localFileNames_str = "" Then
        localFileNames_str = Left(localFileNames_str,Len(localFileNames_str)-1)
    End If
    logFileObject.WriteLine Time & "  LocalFile (Total: " &LocalFileCount& ")    " &localFileNames_str
    logFileObject.WriteBlankLines 1
     
    getLocalFileList = localFileNames_str
End Function
 
 
'********************************************************************
'*
'* Function isALegalFile(str_vbsName,str_secureKey)
'* Purpose: 检查文件是否合法
'* Input:   str_vbsName: vbs文件名
'*          str_secureKey:验证字符
'* Output:  True/False
'*
'********************************************************************
Function isALegalFile(str_vbsName,str_secureKey)
    If base64Encode(str_vbsName) = str_secureKey Then
        isALegalFile = True
    Else
        isALegalFile = False
    End If
End Function
 
 
 
'********************************************************************
'*
'* Function Base64Encode(str_filename)
'* Purpose: 根据文件名生成校验字符
'* Input:   str_filename
'* Output:  校验字符
'*
'********************************************************************
Function base64Encode(str_filename)
    Const Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    Dim cOut, sOut, I
     
    For I = 1 To Len(str_filename) Step 3
        Dim nGroup, pOut, sGroup
         
        nGroup = &H10000 * Asc(Mid(str_filename, I, 1)) + _
        &H100 * MyASC(Mid(str_filename, I + 1, 1)) + MyASC(Mid(str_filename, I + 2, 1))
         
        nGroup = Oct(nGroup)
         
        nGroup = String(8 - Len(nGroup), "0") & nGroup
         
        pOut = Mid(Base64, CLng(" &o" & Mid(nGroup, 1, 2)) + 1, 1) + _
        Mid(Base64, CLng(" &o" & Mid(nGroup, 3, 2)) + 1, 1) + _
        Mid(Base64, CLng(" &o" & Mid(nGroup, 5, 2)) + 1, 1) + _
        Mid(Base64, CLng(" &o" & Mid(nGroup, 7, 2)) + 1, 1)
         
        sOut = sOut + pOut
         
    Next
    Select Case Len(str_filename) Mod 3
        Case 1: '8 bit final
        sOut = Left(sOut, Len(sOut) - 2) + "=="
        Case 2: '16 bit final
        sOut = Left(sOut, Len(sOut) - 1) + "="
    End Select
    Base64Encode = sOut
End Function
 
Function MyASC(OneChar)
    If OneChar = "" Then MyASC = 0 Else MyASC = Asc(OneChar)
End Function

 

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *