Announcement

Collapse
No announcement yet.

Restart - Random Fail

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Restart - Random Fail

    If I want to close and restart an app, I do something like this code, which I've posted it for others to use. In this example, press F1 to close and restart the app.

    Code:
    'Compilable Example:
    #Compile Exe
    #Dim All
    %Unicode=1
    #Include "Win32Api.inc"
    Global hDlg,pid,Restart As Dword
    
    Function PBMain() As Long
       Dialog New Pixels, 0, "F1 to Auto Restart",,,300,50, %WS_OverlappedWindow To hDlg
       Dialog Show Modal hDlg Call DlgProc
       Sleep 1000
       If Restart Then pid = Shell(Exe.Full$, 1) 'Rerun this app
    End Function
    
    CallBack Function DlgProc
       Select Case CbMsg
          Case %WM_Help : Restart = 1 : Dialog End hDlg
       End Select
    End Function
    It always works on my PC.

    It sometimes works and sometimes does NOT work on my daughter's PC. It always closes, but does not always re-open.

    Has anyone else seen it fail to restart the app?

  • #2
    Gary

    I have had a similar problem

    I did not find the reason. I suspect that Windows gets confused with running and shelling programs all at the same time - but I have no reason for saying that.

    But the work around is to shell out to another program which SLEEPS for a bit and then shells back to the original program. This gives the original program time to close nicely and then be reopened again.

    Kerry
    [I]I made a coding error once - but fortunately I fixed it before anyone noticed[/I]
    Kerry Farmer

    Comment


    • #3
      "Killing" and restarting a program from within itself looks "ugly" to me. Lots of applications I personally use and do this, utilize a 'lil helper (launcher) to accomplish that. Which then typically goes
      - Main app invokes launcher*)
      - Either main app or launcher close main app**)
      - Launcher restarts main app and closes itself***)

      This launcher can be as simple as ...
      Code:
      Shell(Exe.Full$, 1)
      ... but I do think its benefical to do this operation in two seperate applications.

      *) Bonus points for a) configurable launcher parameters, e.g. what program to start with which command line parameters and b) making sure the launcher is successfully started, i.e. it signals back "I'm ready to go"
      **) Bonus points for making sure that the main app's process is actually terminated, not just its window hidden
      ***) Bonus points for making sure the main app is successfully started

      Comment


      • #4
        Hey Gary,

        And what you got if you try this with your beloved debug viewer...

        Code:
        #COMPILE EXE '#Win 9.07#
        #DIM ALL
        %UNICODE = 1
        #INCLUDE "Win32Api.inc"
        GLOBAL hDlg AS DWORD
        
        '_____________________________________________________________________________
        
        FUNCTION PBMAIN() AS LONG
         LOCAL pid     AS DWORD
         LOCAL ReStart AS LONG
        
         DIALOG NEW PIXELS, %HWND_DESKTOP, "Press F1 to Restart", , ,300,50, %WS_OVERLAPPEDWINDOW TO hDlg
        
         DIALOG SHOW MODAL hDlg CALL DlgProc TO Restart
         IF Restart THEN
           OutputDebugString("F1 was pressed")
           pid = SHELL(EXE.FULL$, 1)
           OutputDebugString("Shelling to " & EXE.FULL$ & ", pid = 0x" & HEX$(pid))
         ELSE
           OutputDebugString("No restart asked for")
         END IF
        
        END FUNCTION
        '_____________________________________________________________________________
        
        CALLBACK FUNCTION DlgProc
         SELECT CASE CBMSG
           CASE %WM_HELP
             DIALOG END hDlg, %TRUE
         END SELECT
        END FUNCTION
        '_____________________________________________________________________________
        '

        Comment


        • #5
          Hi Kurt,
          Where I use the code is in doing an online update. While the app is running, I rename the app EXE file to MyApp.old, then download the new app as MyApp.exe. When the download is complete I close the current instance and restart the downloaded EXE, which is now the new version of the EXE.

          Up until recently, where I was getting some testing done by my daughter, I'd never had a report of the approach failing.I find that if I want something to break, all I have to do is give it to my daughter. She excels in that type of result!

          Distributing a 2nd EXE, or extracting it as a resource, is certainly an alternate approach but seem far less clean to me than having just the one EXE involved.

          You do make a good point, of course, with the confirmation part of your suggestion. For now, I'll focus on making sure it works in the first place. But if that fails, then a multi-EXE approach should work. Another good thing about the suggestion is that the 2nd EXE can be used for "recovery" if needed.

          Howdy, Pierre!
          Debugger? You're going to make my brain hurt, aren't you? The point you're making is that I could add in a test to confirm that the SHELL was executed, or NOT. The code would give my daughter something to watch for in case a restart does not happen.

          Comment


          • #6
            Hi Gary,


            i would do what Pierre suggests, at least sorts of. You could write that data to a file too, if you are scared by outputdebugstring, but make sure what EXE.FULL$ returns and pid contains after shelling.

            Just a thought - could it be that EXE.FULL$ returns something wrong after renaming the EXE, or did you take measures (what ever they are), that only one instance of your app can run at a time (then it might be a timing issue)? What about storing the EXE´s name before you rename it and use this stored name for shelling?


            JK

            Comment


            • #7
              Howdy, Juergen!
              The "funny" thing is that I've used the approach on dozens of PCs myself with nary a problem. I've used it as well on 100+ of my gbXXX apps, also with nary a peep from users.

              Yep, I could do the file approach. Or, to avoid any likely timing issue, I could even put the information on the clipboard.

              But ... I just thought of a new piece of data in this story...

              The only time my app failed to restore is when my daughter and I were in a TeamViewer session. I just checked with her and she said that when she has done the restart outside of TeamViewer, it has always restarted. And, it sometimes DOES restart in a TeamViewer session.

              Comment


              • #8
                I did a real quick test, maybe there something going wrong with PB SHELL() behind the scene,
                GetLastError() return 1812 while ShellExecute() return no error.
                What do you got on the other side of my screen, aka your side?

                Code:
                #COMPILE EXE '#Win 9.07#
                #DIM ALL
                #INCLUDE "Win32Api.inc"
                GLOBAL hDlg AS DWORD
                
                '_____________________________________________________________________________
                
                FUNCTION WinError$(BYVAL ErrorCode AS DWORD) AS STRING
                 LOCAL pzError  AS ASCIIZ POINTER 'Max is 64K
                 LOCAL ErrorLen AS DWORD
                
                 ErrorLen = FormatMessage(%FORMAT_MESSAGE_FROM_SYSTEM OR %FORMAT_MESSAGE_ALLOCATE_BUFFER, _
                                          BYVAL %NULL, ErrorCode, %NULL, BYVAL VARPTR(pzError), %NULL, BYVAL %NULL)
                 IF ErrorLen THEN
                   REPLACE $CRLF WITH $SPC IN @pzError
                   FUNCTION = "Error" & STR$(ErrorCode) & " (0x" & HEX$(ErrorCode) & ") : " & @pzError
                   LocalFree(pzError)
                 ELSE
                   FUNCTION = "Unknown error" & STR$(ErrorCode) & " (0x" & HEX$(ErrorCode) & ")"
                 END IF
                
                END FUNCTION
                
                '_____________________________________________________________________________
                
                FUNCTION PBMAIN() AS LONG
                 LOCAL pid       AS DWORD
                 LOCAL ReStart   AS LONG
                 LOCAL RetVal    AS LONG
                 LOCAL TryMe     AS LONG
                 LOCAL LastError AS LONG
                
                 DIALOG NEW PIXELS, %HWND_DESKTOP, "Press F1 to Restart", , ,300,50, %WS_OVERLAPPEDWINDOW TO hDlg
                
                 DIALOG SHOW MODAL hDlg CALL DlgProc TO Restart
                 IF Restart THEN
                   TryMe = %TRUE
                   SetLastError(%ERROR_SUCCESS) 'Clear previous error, if any
                   IF TryMe THEN
                     pid = SHELL(EXE.FULL$, %SW_SHOWNORMAL)
                   ELSE
                     RetVal = ShellExecute(%NULL, "OPEN", EXE.FULL$, BYVAL %NULL, CURDIR$, %SW_SHOWNORMAL)
                   END IF
                   LastError = GetLastError()
                   IF LastError THEN
                     MessageBox(%HWND_DESKTOP, "Who do you gonna call?" & $CRLF & _
                                               EXE.FULL$ & $CRLF & "pid = 0x" & HEX$(pid) & $CRLF & _
                                               WinError$(LastError), EXE.FULL$, %MB_OK OR %MB_TOPMOST)
                   END IF
                 END IF
                
                END FUNCTION
                '_____________________________________________________________________________
                
                CALLBACK FUNCTION DlgProc
                 SELECT CASE CBMSG
                   CASE %WM_HELP
                     DIALOG END hDlg, %TRUE
                 END SELECT
                END FUNCTION
                '_____________________________________________________________________________
                '

                Comment


                • #9
                  Gary,

                  this makes it look even more a timing issue. The additional load of TeamViewer may slow things down a bit on your daughters computer and spoil a timing which otherwise would work. Please attach some debugging code to find out what really happens when it fails!


                  JK

                  Comment


                  • #10
                    Pierre!
                    I get no error message with either Shell or ShellExecute.

                    When I hit F1 the app closes and opens, every time.

                    Comment


                    • #11
                      Great, do you think your daughter could run the exe as a test to pinpoint the problem?

                      Added: Windows 10?

                      Comment


                      • #12
                        Yep, she would do that for me. But, she is some kind of "Saturday-is-Sabbath" day religious person and does not do computers today. Tomorrow!

                        Comment


                        • #13
                          My daughter tried it and got no messages at all. The #8 code closed and restarted perfectly, even with with Team Viewer active.

                          Comment


                          • #14
                            Gary, I do not know if this will help any, but I threw my Errorhandler at it just to see if it can catch an error?
                            Attached Files
                            Engineer's Motto: If it aint broke take it apart and fix it

                            "If at 1st you don't succeed... call it version 1.0"

                            "Half of Programming is coding"....."The other 90% is DEBUGGING"

                            "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                            Comment


                            • #15
                              Hi, Cliff... your inc requires PowerBASIC includes, yes?

                              Comment


                              • #16
                                No, I guess not. It didn't compile with Jose or PowerBASIC includes. Are there some know changes I should make?

                                added ... I have grandkids over right now ... I'll look at it in more detail after we put them to bed.

                                Comment


                                • #17
                                  I noticed in my code the use of ExitProcess after the shell.
                                  https://forum.powerbasic.com/forum/u...estart-program
                                  https://duckduckgo.com instead of google

                                  Comment


                                  • #18
                                    If program doesn't allow multiple instances it could fail if buffer receives multiple F1 keys.
                                    It could be a race condition causing multiple occurances of the program.
                                    Testing the code it was possible to get multiple instances.
                                    Dime to a doughnut this fixes it? Curious to know.

                                    Gary,
                                    I goofed so updated the code because I didn't call the RestartProgram function 12:36 PM 2/8/19

                                    Code:
                                    GLOBAL hDlg,pid,Restart AS DWORD
                                    
                                    FUNCTION PBMAIN() AS LONG
                                       DIALOG NEW PIXELS, 0, "F1 to Auto Restart",,,300,50, %WS_OVERLAPPEDWINDOW TO hDlg
                                       DIALOG SHOW MODAL hDlg CALL DlgProc
                                       IF Restart THEN RestartProgram
                                    END FUNCTION
                                    
                                    CALLBACK FUNCTION DlgProc
                                       SELECT CASE CBMSG
                                          CASE %WM_HELP:Restart=1:DIALOG END hDlg  'should have called RestartProgram
                                       END SELECT
                                    END FUNCTION
                                    
                                    FUNCTION RestartProgram AS LONG
                                     'cleanup optional close files, signal threads to finish, etc
                                     pid = SHELL(EXE.FULL$, 1)
                                    END 'assure no other code executes and no race condition
                                    END FUNCTION
                                    RestartProgram function was not being called in the above code
                                    Corrected code and removed unneeded flags and globals
                                    Code:
                                    FUNCTION PBMAIN() AS LONG
                                     LOCAL hDlg AS DWORD
                                     DIALOG NEW PIXELS, 0, "F1 to Auto Restart",,,300,50, %WS_OVERLAPPEDWINDOW TO hDlg
                                     DIALOG SHOW MODAL hDlg CALL DlgProc
                                    END FUNCTION
                                    
                                    CALLBACK FUNCTION DlgProc
                                     SELECT CASE CBMSG
                                      CASE %WM_HELP:DIALOG END CB.HNDL:RestartProgram
                                     END SELECT
                                    END FUNCTION
                                    
                                    FUNCTION RestartProgram AS LONG
                                     LOCAL pid AS LONG
                                     'cleanup optional close files, signal threads to finish, etc
                                     pid = SHELL(EXE.FULL$, 1)
                                    END 'assure no other code executes and no race condition
                                    END FUNCTION
                                    Last edited by Mike Doty; 8 Feb 2019, 12:41 PM.
                                    https://duckduckgo.com instead of google

                                    Comment


                                    • #19
                                      Howdy, Mike!

                                      Thanks for the suggestion.

                                      In my original program, ending the app is done within code after pressing a button on a dialog. In this example, I use F1 for simplicity but it too randomly fails on my daughter's PC.

                                      I'll give it a try and let you know how it works. My daughter is away right now - will test it when she returns.

                                      Comment


                                      • #20
                                        Gary, it should need the Powerbasic "Win32Api.inc" and whatever includes that file needs
                                        Engineer's Motto: If it aint broke take it apart and fix it

                                        "If at 1st you don't succeed... call it version 1.0"

                                        "Half of Programming is coding"....."The other 90% is DEBUGGING"

                                        "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                                        Comment

                                        Working...
                                        X