Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 409
  • Last Modified:

cmd.exe will not close when running .bat file to perform FTP upload

I'm trying to  create a batch file and FTP script to upload a file to a FTP site.  The code is working but the cmd.exe fails to close when the file is uploaded.  My Bat file looks like:

ftp -n -s:"C:\myFolder\FTP_Script.txt"

Open in new window

The script file looks like:
Open  FTPURL.Com
User MyUserName
MyPassword
CD "/FTP Folder"
bin
Put "C:\Work\dummy.txt"
quit

Open in new window

The file gets uploaded properly, but the Command window does not close.  The lines in the cmd.exe window look like:
ftp> Open FTPURL.com
220 Serv-U FTP Server v15.1 ready...
ftp> User MyUserName
331 User name okay, need password.

230 User logged in, proceed.
ftp> CD "/FTP Folder"
250 Directory changed to /FTP Folder
ftp> bin
200 Type set to I.
ftp> put "C:\Work\dummy.txt"
220 Port command successful.
150 Opening Binary mode data connection for Dummy.txt
_

Open in new window

Then it just hangs there, and never closes the cmd.exe window.
0
Dale Fye
Asked:
Dale Fye
  • 6
  • 5
  • 2
  • +4
2 Solutions
 
Gustav BrockCIOCommented:
You can try using mput for put. That has worked for me - though years ago in the days of Windows NT/2000.

/gustav
0
 
pcelbaCommented:
Update your BAT file:
START ftp -n -s:"C:\myFolder\FTP_Script.txt"
EXIT

or 

EXIT /B

Open in new window

0
 
Jim Dettman (Microsoft MVP/ EE MVE)PresidentCommented:
Here's the way I do mine.   Couple things:

1. Walk through your script file commands manually to see where a problem us.
2. Don't use the MPut, MGet, etc.   You can run into issues.  For example, you do a MGet(), followed by a MDel().   If someone uploads a file between MGet() and the MDel(), you end up deleting the file.  Always better to handle files one at a time.

 Also if downloading, you want to take a snapshot of the FTP directory, then process against the snapshot.  This avoids grabbing files that may not have completely uploaded as yet for the most part.

Jim.

10        On Error GoTo FTPUploadFile_Error

          ' Generate file names
20        strFTPScriptFile = "\FTP_" & AppShortName() & "_" & RoutineName & ".txt"
30        strFTPCommandFile = "\FTP_" & AppShortName() & "_" & RoutineName & ".bat"
40        strFTPLogfile = "\FTP_" & AppShortName() & "_" & RoutineName & ".log"

          ' Write script file
50        intFileNum = FreeFile
60        Open strFTPScriptFile For Output As #intFileNum
70        Print #intFileNum, strUserName
80        Print #intFileNum, strPassword
90        If left$(strMode, 1) = "P" Then
100           Print #intFileNum, "passive"
110       End If
120       Print #intFileNum, "type " & IIf(strTransferType = "B", "binary", "ascii")
130       Print #intFileNum, "put " & Chr$(34) & strLocalFileName & Chr$(34) & " " & Chr$(34) & strFTPFilename & Chr$(34)
140       Print #intFileNum, "quit"
150       Close #intFileNum

          ' Write command file
160       intFileNum = FreeFile
170       Open strFTPCommandFile For Output As #intFileNum
180       Print #intFileNum, "@ftp -i -s:" & strFTPScriptFile & " " & strFTPSiteName & " > " & strFTPLogfile
190       Close #intFileNum

          ' Execute
200       lngHWnd = Shell(strFTPCommandFile, vbHide)
210       WaitWhileRunning (lngHWnd)

          ' Check log file
220       If IsValidFTP(strFTPLogfile) Then
230           FTPUploadFile = True
240       Else
250           If DebugMode() = True Then
260               Stop
270               FTPUploadFile = False
280           Else
290               oOCS_SendMail.SetParams "ITALERT", ".", "."
300               oOCS_SendMail.Subject = "FTP Upload failed"
310               strMailMessage = "The file: " & strLocalFileName & " did not upload." & vbCrLf
320               strMailMessage = strMailMessage & "Command, script, and log files are attached." & vbCrLf & vbCrLf
330               strMailMessage = strMailMessage & "App name:" & AppShortName() & " Version: " & AppVersion()
340               oOCS_SendMail.Message = strMailMessage
350               oOCS_SendMail.Attachment = strFTPCommandFile & ";" & strFTPScriptFile & ";" & strFTPLogfile
360               oOCS_SendMail.Send
370               FTPUploadFile = False
380           End If
390       End If

Open in new window

0
What Kind of Coding Program is Right for You?

There are many ways to learn to code these days. From coding bootcamps like Flatiron School to online courses to totally free beginner resources. The best way to learn to code depends on many factors, but the most important one is you. See what course is best for you.

 
Dale FyeAuthor Commented:
Tried most of the above.  

Gustav, tried the mput last night, but this is only going to be a one file, once a day process, so I don't need the multiple aspect of that.

pcelba, tried the EXIT and Exit /B commands in the .bat, but those did not make a difference either.

Jim, didn't use your entire code because the client is insisting running this from a batch file, but compared your FTP File to mine and made the appropriate modifications and although the file is being uploaded, the Quit command is not terminating the connection to the FTP site.  

The FTP is working fine, but the Command Window will not close.

I added a > LogFile.txt to the .bat file, but that is simply returning the same information as was previously visible in the cmd.exe window.
0
 
Gustav BrockCIOCommented:
I also use mput for single files. It behaves a bit differently.

Perhaps you need to politely close the session by the commands:

    close
    bye

though I believe bye is just a synonym for quit.

/gustav
0
 
pcelbaCommented:
"tried the EXIT and Exit /B commands"  I've also recommended to use  START  ftp.  Did you try it?  Also START /B alternative is worth to try.

Your ftp seems to be frozen after the put command because the quit  or  bye  command should return  "221 Goodbye".

You may try HASH command to display the file transfer progress.
0
 
Jim Dettman (Microsoft MVP/ EE MVE)PresidentCommented:
Couple things:

1. I would put the FTP command itself in the script file.
2. I would then try and execute the script file from the command line manually.
3. I would then call the transfer with the shell command.
4. I noticed your transferring a .txt file, but your using binary mode?  
5. As pcelba said, seems like your hanging on the transfer itself, not that the batch file itself won't quit.

 Doing the above should get you to an answer where the problem is.

Jim.
0
 
Jim Dettman (Microsoft MVP/ EE MVE)PresidentCommented:
Check the active vs passive mode on the FTP script....the server may require passive mode.

Again, walk through the commands your using manually, then build up from there (have the script file include the FTP command, and quit, then execute the script manually, then call with shell from the program).

Jim.
0
 
Amitkumar PSr. ConsultantCommented:
Could you please give it a try by making firewall off ?

How about the result when you run each ftp command manually ?
0
 
Gerwin Jansen, EE MVETopic Advisor Commented:
What is the title of the cmd window when it is hanging? If it is FTP then the exit/bye command isn't working. Try adding a 'verbose' command at the beginning of the ftp script to see what is happening. Also, try adding an exit command in the bat file, after the ftp line.
0
 
Robberbaron (robr)Commented:
i concur with pelba.... depending upon server & client, should expect a
226 Closing data connection
after the successful transfer
0
 
Dale FyeAuthor Commented:
Jim,

Not familiar with "WaitWhileRunning", is that one of your functions?

Also, what are you using for "IsValidFTP"


Dale
0
 
Jim Dettman (Microsoft MVP/ EE MVE)PresidentCommented:
<<Not familiar with "WaitWhileRunning", is that one of your functions?>>

 Yes....uses the window handle and waits until the process disappears.  You can find that here:

https://www.experts-exchange.com/questions/27882738/Access-VBA-Function-To-Rename-A-File-After-Printing-To-PDF-Driver-Fails.html#a38447377

<<"IsValidFTP">>

 A procedure to loop through the resulting log file to see if the transfer was good or not:

Function IsValidFTP(strFTPLogfile As String) As Boolean

          ' Checks log file to see if last FTP operation OK.
          ' Looks for 226 message (Transfer complete)

          ' 1.5 - OCS/JRD - 02/28/12 - FTP and FTPs clients are indentical at this point in checking
          ' the log file.  Routines were split for consistency with all the other routines
          ' which are split.
          ' 1.6 - OCS/JRD - 07/05/14 - Changed check to look at server return code only
          ' rather than full reply.

          Const RoutineName = "IsValidFTP"
          Const Version = "1.6"

          Dim intFileNum As Integer
          Dim lsLine As String

10        On Error GoTo IsValidFTP_Error

20        IsValidFTP = False

30        intFileNum = FreeFile
40        Open strFTPLogfile For Input As #intFileNum

50        Do While Not EOF(intFileNum) And IsValidFTP = False
60            Line Input #intFileNum, lsLine
70            If InStr(1, lsLine, "226 ") > 0 Then
80                IsValidFTP = True
90            ElseIf InStr(1, lsLine, "250 ") Then
100               IsValidFTP = True
110           End If
120       Loop

IsValidFTP_Exit:
130       On Error Resume Next

140       Close #intFileNum

150       Exit Function

IsValidFTP_Error:
160       UnexpectedError ModuleName, RoutineName, Version, Err.Number, Err.Description, Err.Source, VBA.Erl
170       Resume IsValidFTP_Exit

End Function

Open in new window

0
 
Dale FyeAuthor Commented:
Jim,

Strange,  I made no changes to either the batch file or the actual FTP script code this morning (still running the original code I posted in my original post) and the process worked completely, including closing the cmd.exe window, so I still have no idea what caused the original problem.

I like that WaitWhileRunning routine.  That is pretty slick.

In your IsValidFTP function, it doesn't look like you are doing any testing for a failure of any type, just a single 226 or 250 will result in a True.  I'll have to take a look at the log file, now that we have the upload working.  It turns out the client will have multiple files being uploaded, so I want to be able to confirm that all files were uploaded successfully.  Maybe I can put a counter in there, but also check for an incomplete or invalid upload code, in case it fails.

Dale
0
 
Jim Dettman (Microsoft MVP/ EE MVE)PresidentCommented:
<<In your IsValidFTP function, it doesn't look like you are doing any testing for a failure of any type, just a single 226 or 250 will result in a True.>>

 Anything besides getting a 226 or 250 is a failure.

<< It turns out the client will have multiple files being uploaded>>

 My routines are written to process one file at a time.  Not very efficient if you have a lot of files though as your logging in/out for every one.

 Actually, I don't like using FTP and stick with AS2 whenever possible.  It's a managed file transfer and has none of the short comings of FTP.

Jim.
0
 
Dale FyeAuthor Commented:
I'm not familiar with AS2 (I'll have to look that up), I have not been doing much file transfer stuff for quite a while, but have had two clients in the last two months who have had a requirement.
0
 
Jim Dettman (Microsoft MVP/ EE MVE)PresidentCommented:
AS2 is an encrypted managed file transfer process from peer to peer using the http protocol (AS1 uses e-mail, AS3 uses FTP).

It's a managed file transfer, meaning it has  end to end checks on  the file being received,getting it in its entirety,  and re-tries when a send files.   Optionally you can get a receipt back back as well either async or sync.

This company:

https://www.rssbus.com/ports/

 Offers AS2 software for Free with one partner, so it's perfect for most ad-hoc situations.   And even if you need to buy a license because of needing some of the advanced features, it's still reasonably priced. They have some info as well there.

  Setup can be a bit of a pain at first, but no more so than using sFTP or FTPs and once you do a couple, it becomes easy.

 In terms of sending/receiving, all you have is in and out baskets (directories).  Drop a file in the out basket, software picks it up, sends it, and then either deletes it or renames it.   For receiving, you just do a fast directory check on the in-basket.

 Since it's a "push" of a file from both sides, it's very efficient as you don't need to continually log onto a FTP server and check for files.

Jim.
0
 
Dale FyeAuthor Commented:
Thanks, Jim.  I think my client is going to stick with the FTP process, but I will probably adopt your WaitWhileRunning and some variant of the IsFTPValid.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

What Kind of Coding Program is Right for You?

There are many ways to learn to code these days. From coding bootcamps like Flatiron School to online courses to totally free beginner resources. The best way to learn to code depends on many factors, but the most important one is you. See what course is best for you.

  • 6
  • 5
  • 2
  • +4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now