Help writing a process for FTP Shell Function

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • JHNielson
    New Member
    • Feb 2007
    • 121

    #1

    Help writing a process for FTP Shell Function

    I posted this in the Access thread, but seeing as how this is a VB problem, I thought this might be the better place

    I have a code to FTP files to a server, using a script FTP.scr.

    I need to wait until the FTP completes before proceeding to the next code. So far every process I have written keeps failing, and I'm not sure where I'm going wrong.

    This is the code as I have it now:

    Code:
    Public Sub FTP_Shell(SCR_FILE As String)
    
    Dim FTP_Task As Long, ret As Long, FTP_Handle As Long
    Dim FTP_PROCESS As String
    Dim stSysDir As String
        stSysDir = Environ$("COMSPEC")
        stSysDir = Left$(stSysDir, Len(stSysDir) - Len(Dir(stSysDir)))
        
        FTP_PROCESS = CreateProcessA(sNull, p_Path, ByVal 0&, ByVal 0&, 1&, NORMAL_PRIORITY_CLASS, ByVal 0&, sNull, sInfo, pInfo)
        
        FTP_Task = Shell(stSysDir & "ftp.exe -s:" & stSCRFile, vbNormalFocus)
        FTP_Handle = OpenProcess(FTP_PROCESS, False, FTP_Task)
        
        ret = WaitForSingleObject(FTP_Handle, INFINITE)
        ret = CloseHandle(FTP_Handle)
    
    End Sub
    
    Function TEST_FTP_FILES()
    
    Call FTP_Shell("C:\DLU\System\FTP\Test_FTP.scr")
    End Function
    I would really appreciate it if anyone had either a link ot a good resource on writing a process, or if anyone can help me wiht what this process would/should look like.

    I haven't really written processes before - this is a new area of vb for me.

    Thanks for any help anyone can provide.
  • tifoso
    New Member
    • Apr 2007
    • 41

    #2
    I had the same issue, the quick and dirty solution is send a dummy file after the one u r waiting for that way u can put a while loop /doevents on the dummy file and it won't happen until your main file has completed.

    i.e. add to the scr lines as below of course the dummy file has to be at the ftp site
    ...
    get good_file
    get dummy_file
    ...

    It is crude but I had a deadline and that is how it worked , there are more elegant ways but same as you I had to use a script as a requirement, since it was generated from some other place in the code.

    Comment

    • iburyak
      Recognized Expert Top Contributor
      • Nov 2006
      • 1016

      #3
      Maybe you will have any use of my code:


      1. On VB Form put a Command Button and put this code in it:

      Code:
      Private Sub Command1_Click()
      Testing
      End Sub
      2. Add Module to your project and put this code in it:

      Code:
      Option Explicit
      
      Private Type STARTUPINFO
               cb As Long
               lpReserved As String
               lpDesktop As String
               lpTitle As String
               dwX As Long
               dwY As Long
               dwXSize As Long
               dwYSize As Long
               dwXCountChars As Long
               dwYCountChars As Long
               dwFillAttribute As Long
               dwFlags As Long
               wShowWindow As Integer
               cbReserved2 As Integer
               lpReserved2 As Long
               hStdInput As Long
               hStdOutput As Long
               hStdError As Long
            End Type
      
            Private Type PROCESS_INFORMATION
               hProcess As Long
               hThread As Long
               dwProcessId As Long
               dwThreadID As Long
            End Type
      
            Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal _
               hHandle As Long, ByVal dwMilliseconds As Long) As Long
      
            Private Declare Function CreateProcessA Lib "kernel32" (ByVal _
               lpApplicationName As Long, ByVal lpCommandLine As String, ByVal _
               lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _
               ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _
               ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As Long, _
               lpStartupInfo As STARTUPINFO, lpProcessInformation As _
               PROCESS_INFORMATION) As Long
      
            Private Declare Function CloseHandle Lib "kernel32" (ByVal _
               hObject As Long) As Long
      
            Private Const NORMAL_PRIORITY_CLASS = &H20&
            Private Const INFINITE = -1&
            
          
      
      
            Public Sub ExecCmd(cmdline$)
               Dim proc As PROCESS_INFORMATION
               Dim start As STARTUPINFO
               Dim ReturnValue As Integer
               
               ' Initialize the STARTUPINFO structure:
               start.cb = Len(start)
      
               ' Start the shelled application:
               ReturnValue = CreateProcessA(0&, cmdline$, 0&, 0&, 1&, _
                  NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc)
      
               ' Wait for the shelled application to finish:
               Do
                  ReturnValue = WaitForSingleObject(proc.hProcess, 0)
                  DoEvents
               Loop Until ReturnValue <> 258
      
               ReturnValue = CloseHandle(proc.hProcess)
            End Sub
      
            Sub Testing()
               ExecCmd "NOTEPAD.EXE"
               'ExecCmd "net send /domain:NYGISW517628 Hello"
               MsgBox "Process Finished"
            End Sub
      3. Run application and press Command1 button.

      Good Luck.

      Comment

      • JHNielson
        New Member
        • Feb 2007
        • 121

        #4
        Originally posted by iburyak
        Maybe you will have any use of my code:


        1. On VB Form put a Command Button and put this code in it:

        Code:
        Private Sub Command1_Click()
        Testing
        End Sub
        2. Add Module to your project and put this code in it:

        Code:
        Option Explicit
        
        Private Type STARTUPINFO
                 cb As Long
                 lpReserved As String
                 lpDesktop As String
                 lpTitle As String
                 dwX As Long
                 dwY As Long
                 dwXSize As Long
                 dwYSize As Long
                 dwXCountChars As Long
                 dwYCountChars As Long
                 dwFillAttribute As Long
                 dwFlags As Long
                 wShowWindow As Integer
                 cbReserved2 As Integer
                 lpReserved2 As Long
                 hStdInput As Long
                 hStdOutput As Long
                 hStdError As Long
              End Type
        
              Private Type PROCESS_INFORMATION
                 hProcess As Long
                 hThread As Long
                 dwProcessId As Long
                 dwThreadID As Long
              End Type
        
              Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal _
                 hHandle As Long, ByVal dwMilliseconds As Long) As Long
        
              Private Declare Function CreateProcessA Lib "kernel32" (ByVal _
                 lpApplicationName As Long, ByVal lpCommandLine As String, ByVal _
                 lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _
                 ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _
                 ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As Long, _
                 lpStartupInfo As STARTUPINFO, lpProcessInformation As _
                 PROCESS_INFORMATION) As Long
        
              Private Declare Function CloseHandle Lib "kernel32" (ByVal _
                 hObject As Long) As Long
        
              Private Const NORMAL_PRIORITY_CLASS = &H20&
              Private Const INFINITE = -1&
              
            
        
        
              Public Sub ExecCmd(cmdline$)
                 Dim proc As PROCESS_INFORMATION
                 Dim start As STARTUPINFO
                 Dim ReturnValue As Integer
                 
                 ' Initialize the STARTUPINFO structure:
                 start.cb = Len(start)
        
                 ' Start the shelled application:
                 ReturnValue = CreateProcessA(0&, cmdline$, 0&, 0&, 1&, _
                    NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc)
        
                 ' Wait for the shelled application to finish:
                 Do
                    ReturnValue = WaitForSingleObject(proc.hProcess, 0)
                    DoEvents
                 Loop Until ReturnValue <> 258
        
                 ReturnValue = CloseHandle(proc.hProcess)
              End Sub
        
              Sub Testing()
                 ExecCmd "NOTEPAD.EXE"
                 'ExecCmd "net send /domain:NYGISW517628 Hello"
                 MsgBox "Process Finished"
              End Sub
        3. Run application and press Command1 button.

        Good Luck.

        Thanks so much. I will try it later and hopefully it will work.

        Comment

        • iburyak
          Recognized Expert Top Contributor
          • Nov 2006
          • 1016

          #5
          Let me know how it goes.... :)

          Comment

          • JHNielson
            New Member
            • Feb 2007
            • 121

            #6
            So I put the code in and ran it - and all that happens is it opens up Notepad and says "process finished". I'm not sure where I call on my script I have written, or where I put the process information in.


            Thanks for your generous help

            Comment

            • JHNielson
              New Member
              • Feb 2007
              • 121

              #7
              So here is the code I have. I got it to do everything I want it to do, expect now it doesn't seem to pick up the successful transfer return value. It waits but never stops.

              I tested an FTP connection manually, and when it was done successfully transferring, the number at the beginning of the line was 226. I assume that is th e return value it should be looking for. That is what I set it to, but it doesn't ever stop the program even after the FTP window has been closed.

              Any help would be great. I don't wan to be a pest about this, but I'm down to the wire and this has been plaguing me for weeks.


              Thanks again


              Code:
              Option Explicit
              
              Private Type STARTUPINFO
                       cb As Long
                       lpReserved As String
                       lpDesktop As String
                       lpTitle As String
                       dwX As Long
                       dwY As Long
                       dwXSize As Long
                       dwYSize As Long
                       dwXCountChars As Long
                       dwYCountChars As Long
                       dwFillAttribute As Long
                       dwFlags As Long
                       wShowWindow As Integer
                       cbReserved2 As Integer
                       lpReserved2 As Long
                       hStdInput As Long
                       hStdOutput As Long
                       hStdError As Long
                    End Type
              
                    Private Type PROCESS_INFORMATION
                       hProcess As Long
                       hThread As Long
                       dwProcessId As Long
                       dwThreadID As Long
                    End Type
              
                    Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal _
                       hHandle As Long, ByVal dwMilliseconds As Long) As Long
              
                    Private Declare Function CreateProcessA Lib "kernel32" (ByVal _
                       lpApplicationName As Long, ByVal lpCommandLine As String, ByVal _
                       lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _
                       ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _
                       ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As Long, _
                       lpStartupInfo As STARTUPINFO, lpProcessInformation As _
                       PROCESS_INFORMATION) As Long
              
                    Private Declare Function CloseHandle Lib "kernel32" (ByVal _
                       hObject As Long) As Long
              
                    Private Const NORMAL_PRIORITY_CLASS = &H20&
                    Private Const INFINITE = -1&
                    
                  
              
              
                    Public Sub ExecCmd(cmdline$, FTP_SCR As String)
                       Dim proc As PROCESS_INFORMATION
                       Dim start As STARTUPINFO
                       Dim ReturnValue As Integer
                       
                       ' Initialize the STARTUPINFO structure:
                       start.cb = Len(start)
              
                       ' Start the shelled application:
                       ReturnValue = Shell("ftp.exe -s:" & FTP_SCR, vbNormalFocus)
                       
              
                       ' Wait for the shelled application to finish:
                       Do
                          ReturnValue = WaitForSingleObject(proc.hProcess, 0)
                          DoEvents
                       Loop Until ReturnValue = 226
              
                       ReturnValue = CloseHandle(proc.hProcess)
                    End Sub
              
                    Sub Testing(FTP_SCR As String)
                    Dim ROOT_DRIVE As String
                 
                      ROOT_DRIVE = DLookup("[ROOT_FOLDER]", "[CONFIG - ROOT FOLDER]")
                      ExecCmd "FTP.EXE", FTP_SCR
                       'ExecCmd "net send /domain:NYGISW517628 Hello"
                      Kill "c:\DLU\System\FTP\TEST.jpg"
                       MsgBox "Process Finished"
                    End Sub
              
              Function TEST_FTP_FILES()
              Dim ROOT_DRIVE As String
              Dim FTP_SCR As String
              
                 
              ROOT_DRIVE = DLookup("[ROOT_FOLDER]", "[CONFIG - ROOT FOLDER]")
              FTP_SCR = ROOT_DRIVE & ":\DLU\System\FTP\Test_FTP.scr"
              Call Testing(FTP_SCR)
              
              End Function

              Comment

              • JHNielson
                New Member
                • Feb 2007
                • 121

                #8
                One more thing, when i set the "Loop return value..." statement to <> 258, the process just finishes without waiting for the file to transfer and the process to end.

                When I set it to =226, it never stops.

                Thanks, for an help I can get.

                Comment

                • iburyak
                  Recognized Expert Top Contributor
                  • Nov 2006
                  • 1016

                  #9
                  In my code I have this:

                  Code:
                  Do
                              ReturnValue = WaitForSingleObject(proc.hProcess, 0)
                              DoEvents
                  Loop Until ReturnValue <> 258
                  And you have this:

                  Code:
                  Do
                              ReturnValue = WaitForSingleObject(proc.hProcess, 0)
                              DoEvents
                  Loop Until ReturnValue = 226
                  This code is executed in a loop while it is waiting for Shell command to finish.
                  Debug this code and check which one you want to use.

                  I know for sure that mine works and waits for other program to finish and then proceeds with the code correctly. This is why I had a Notepad so you would see that Message box appear only when you close a Notepad symbolizing that other program has finished.

                  Good Luck.

                  Comment

                  • JHNielson
                    New Member
                    • Feb 2007
                    • 121

                    #10
                    Right- so when I run it with your code:
                    Code:
                    Do
                                ReturnValue = WaitForSingleObject(proc.hProcess, 0)
                                DoEvents
                    Loop Until ReturnValue <> 258
                    It proceeds through the rest of the code before the FTP finishes. The last process is to move the files from the current directory to a storage directory.
                    The files get moved before they get sent.


                    When I use my code:
                    Code:
                    Do
                                ReturnValue = WaitForSingleObject(proc.hProcess, 0)
                                DoEvents
                    Loop Until ReturnValue = 226
                    The rest of the code never finishes.

                    I'm trying to figure out what is keeping the process from finishing in my code, or from finishing too fast in your code. How do I figure out what the return value should be. Is there a list somewhere or a way to determine this?

                    Thanks

                    Comment

                    • iburyak
                      Recognized Expert Top Contributor
                      • Nov 2006
                      • 1016

                      #11
                      Check this out:

                      http://msdn2.microsoft .com/en-us/library/ms687032.aspx

                      Comment

                      • JHNielson
                        New Member
                        • Feb 2007
                        • 121

                        #12
                        Originally posted by iburyak
                        Check this out:

                        http://msdn2.microsoft .com/en-us/library/ms687032.aspx

                        Thanks - that helped, except for the question of where you get "258" from. what is that number. I thought it was the return value that comes from FTP? How do i verify that is the right number for my system? How do I find the number if it is not?

                        Am I looking at the wrong place in the code?

                        Thanks so much for your help. I hate to be such a pest, but I'm down to the wire and have been trying to get this right so long, and I'm so close now!

                        Thanks again

                        Comment

                        • iburyak
                          Recognized Expert Top Contributor
                          • Nov 2006
                          • 1016

                          #13
                          I understand your frastration and I am trying to help as much as I can.
                          You can probably do following:

                          Code:
                          Do
                                      ReturnValue = WaitForSingleObject(proc.hProcess, 0)
                                      Debug.print ReturnValue
                                      DoEvents
                          Loop Until ReturnValue = 226
                          You will see all possible return codes and would be able to judge which one to use.

                          This is how I found my number.... :)

                          I'll dig my old stuff more.... :)

                          Comment

                          • JHNielson
                            New Member
                            • Feb 2007
                            • 121

                            #14
                            Great thanks so much! I solved it! Thanks for all your great help!

                            Comment

                            • iburyak
                              Recognized Expert Top Contributor
                              • Nov 2006
                              • 1016

                              #15
                              So what was your final solution?
                              I am so happy that you are finally worked it out..... :)

                              Good Luck.
                              Irina.

                              Comment

                              Working...