Kaju self-updater talk (v.2.x)

  1. ‹ Older
  2. 7 weeks ago

    Kem T

    May 14 Testers, Xojo Pro, XDC Speakers, MVP Connecticut

    I'm getting ready to release an update, and I could use some help testing.

    Please take a look at this branch:

    https://github.com/ktekinay/Kaju/tree/feature/To_URLConnection

    The README contains all (well, most) of the changes since the last release. If there are any issues, please let me know.

  3. Douglas H

    May 14 Testers, Xojo Pro

    I don't have a way to easily test the problem I described in my Mar 10 post above, because it seems to only happen on faster hardware than I own. But refer to my Mar 10 post for a description of what I encountered with one user with a fast MBP. I'm sure you won't want to use my listed circumvention because I slipped in a call to a MBS function since I license them. But you could do something similar without MBS.

    If you don't implement something like that, I'll probably continue to slip in the MBS call in the versions I use myself.

    My one user who had the problem uses it in large sports events which are completely shut down for the season and won't even run the applications again until next year.

  4. Kem T

    May 14 Testers, Xojo Pro, XDC Speakers, MVP Connecticut

    Are you storing an instance of UpdateChecker in a property or a local variable?

  5. Douglas H

    May 15 Testers, Xojo Pro

    @Kem T Are you storing an instance of UpdateChecker in a property or a local variable?

    Sorry for the delay; was not in the office earlier.

    To answer your question, yes, it is in a local variable but IIRC the code I use came from a sample project (of yours?).

    In App, I declare app public property mKajuPrefsAppPath (type FolderItem) and app public property UpdateInitiater (type Kaju.UpdateInitiater). Then at the end of App.Open(), after setting up the mKajuPrefsAppPath, there is this block of code:

    // If we have app prefs folder, initialize update check
    if mKajuPrefsAppPath <> nil and mKajuPrefsAppPath.Exists then
      dim checker as new Kaju.UpdateChecker( mKajuPrefsAppPath )
      checker.AllowRedirection = true
      checker.ServerPublicRSAKey = kKajuPublicKey
      checker.UpdateURL = kKajuUpdateURL
      
      // Only check for final versions not previously ignored
      checker.AllowedStage = App.Final
      checker.HonorIgnored = true
      
      // Only allow window if update is available
      checker.AllowedInteraction = Kaju.UpdateChecker.kAllowUpdateWindow
      
      AddHandler checker.ExecuteAsyncComplete, WeakAddressOf Checker_ExecuteAsyncComplete
      checker.ExecuteAsync
    end if

    However, in App there are two private methods which IIRC were copied from a sample project of yours:

    Private Sub Checker_ExecuteAsyncComplete(sender As Kaju.UpdateChecker)
      '#pragma unused sender
      HandlePostCheck sender
    End Sub
    Private Sub HandlePostCheck(checker as Kaju.UpdateChecker)
       ... code which sets up a MsgBox when applicable ...
    End Sub

    Aside from the above App.Open() check, there are also menu items for checking for beta or final updates. The main MenuHandler for checking for (final, non-beta) updates is:

    Function OptionsCheckUpdate() as Boolean Handles OptionsCheckUpdate.Action
      // See App.Open for some required setup
    
      // If we have app prefs folder, initialize update check
      if mKajuPrefsAppPath <> nil and mKajuPrefsAppPath.Exists then
        dim checker as new Kaju.UpdateChecker( mKajuPrefsAppPath )
        checker.AllowRedirection = true
        checker.ServerPublicRSAKey = kKajuPublicKey
        checker.UpdateURL = kKajuUpdateURL
      
        // Unlike app startup checks, show ignored final versions also
        checker.AllowedStage = App.Final
        checker.HonorIgnored = false
      
        // Allow window all the time (even if error etc)
        checker.AllowedInteraction = Kaju.UpdateChecker.kAllowAll
      
        AddHandler checker.ExecuteAsyncComplete, WeakAddressOf Checker_ExecuteAsyncComplete
        checker.ExecuteAsync
      
      else
        MsgBox "Unable to check for updates" + EndOfLine + EndOfLine + _
        "No preference file path is available.  Please contact support."
      end if
    
      Return True
    
    End Function

    So in bothApp.Open() and my menu handler it is creating a local variable instance of UpdateChecker. However, I thought I had copied or at least patterned those blocks of code from a sample project.

    And it always worked as expected for all but one user, who never got notified of updates in the App.Open() check and never received a MsgBox at all from the menu handler option (whether or not he was on the current version -- he got no MsgBox at all).

    We happened to be at the same large sporting event in early March and we had a little time for me to investigate. First I tried remote debug, which ran as expected and gave the update window or MsgBox. So then I installed unlicensed Xojo on his MBP and the project source and ran in debug mode. It still worked.

    So then I figured it was timing dependent and inserted the .05 sec sleep in Kaju.UpdateChecker.GetAsyncHTTPSocket as described in my Mar 10 post, compiled on my MBP, and ran on his machine and then it worked. We didn't have more time, so I didn't try to narrow it down farther. And then after flying home from that sports event, the entire sport got shut down and the app may not be used at all again until next year. :(

    If you don't recognize the above code I use in App.Open() or the menu handler, I can try to determine where I got those code blocks. But I was thinking they came from a sample project of yours.

    Ahh, after typing all of the above, I just realized why you were asking. Your theory is that the App.Open() or menu handler completes and goes out of scope destroying the UpdateChecker instance before it can get an async response?

  6. Kem T

    May 15 Testers, Xojo Pro, XDC Speakers, MVP Connecticut

    Yes. My sample code was originally synchronous, so if it's still doing that, I should change and document it.

  7. Kem T

    May 16 Testers, Xojo Pro, XDC Speakers, MVP Connecticut
    Edited 7 weeks ago

    I just looked and the example test app is storing the UpdateChecker in a property. This is recommended, even required, for any object that acts asynchronously, but I imagine others will use local variables too and rely on the event handler to return the instance. As such, I'll change the code in an attempt to compensate by forcing the instance to be kept alive until the data is fetched.

    Edit:

    This is why I should look before posting. The code already holds an instance during the async operation, so whatever the issue, that's not it.

    (A little bragging here: I often have "I should have thought of that!" moments only to find out that, yes, I did think of that. This is totally a triumph as a programmer, and in no way indicative of a poor memory.)

  8. Kem T

    May 16 Testers, Xojo Pro, XDC Speakers, MVP Connecticut

    @Douglas H , the To_URLConnection branch now uses a Timer to start the URLConnection after it is set up. If this really is a timing issue, this should fix the problem. At worst, it introduces an 10 ms delay during which the user can wash their hair or catch up on Netflix.

  9. Douglas H

    May 16 Testers, Xojo Pro

    @Kem T, the one user I had with the issue -- and evidently with a fast enough machine to expose the problem -- won't be running any of my software now until next year. But I'll send him an email and see if he will run tests for me. If so, I'll make him a build with what is in that branch and ask him to try it.

  10. @Kem T I just looked and the example test app is storing the UpdateChecker in a property. This is recommended, even required, for any object that acts asynchronously, but I imagine others will use local variables too and rely on the event handler to return the instance. As such, I'll change the code in an attempt to compensate by forcing the instance to be kept alive until the data is fetched.

    Edit:

    This is why I should look before posting. The code already holds an instance during the async operation, so whatever the issue, that's not it.

    Although the Test app stores the instance of UpdateChecker in a property (Checker is a property):

    Dim u As New Kaju.UpdateChecker( App.PrefFolder )
    ...
    Checker = u

    It looks like the Admin app doesn't:

    Dim u As New Kaju.UpdateChecker( f )
    #pragma unused u

    Also, the README shows this snippet of code in the Step by Step section:

    dim updater as new Kaju.UpdateChecker( myAppPrefFolder )
    ...
    updater.ExecuteAsync

    Which also implies that it's stored in a local variable - perhaps it should be made clear that it should be put in a property here too.

    (A little bragging here: I often have "I should have thought of that!" moments only to find out that, yes, I did think of that. This is totally a triumph as a programmer, and in no way indicative of a poor memory.)

    Careful with that bragging :)

  11. Kem T

    May 19 Testers, Xojo Pro, XDC Speakers, MVP Connecticut

    To be clear, the class itself holds its own instance during async operations in a shared array. As such, no matter where you put it, it cannot go out of scope until the async operation is complete or errors. That's the thing I thought of during my original coding, so no modification to the example or Admin code, or docs, is needed.

  12. brian f

    May 19 Testers, Xojo Pro California

    [ OK ] Bragging Rights daemon Started

    :P

  13. @Kem T To be clear, the class itself holds its own instance during async operations in a shared array. As such, no matter where you put it, it cannot go out of scope until the async operation is complete or errors. That's the thing I thought of during my original coding, so no modification to the example or Admin code, or docs, is needed.

    Ahha. Bragging rights are established once again. Nice work.

    BTW I've tested your new branch on a development build and all seems to be working ok on the Mac. Did a quick test on Ubuntu too, but still getting the seg. fault there (as reported above and in Feedback Case #59800 ).

  14. Kem T

    May 19 Testers, Xojo Pro, XDC Speakers, MVP Connecticut

    You mean the To_URLConnection branch, right?

  15. @Kem T You mean the To_URLConnection branch, right?

    Yes.

  16. 6 weeks ago

    Douglas H

    May 21 Testers, Xojo Pro

    @Douglas H @Kem T, the one user I had with the issue -- and evidently with a fast enough machine to expose the problem -- won't be running any of my software now until next year. But I'll send him an email and see if he will run tests for me. If so, I'll make him a build with what is in that branch and ask him to try it.

    @Kem, sorry for the delay but I wanted to wait to respond until that user had tried it.

    Sadly, using the To_URLConnection branch it still works fine for every machine I have tried EXCEPT his. He reports he does not get prompted to update, and the menu option to check for updates does not report "No updates available" like it does for other machines. So it acts the same as the prior Kaju build did for this user.

    Would you like me to try putting the updatechecker into an App class property? The Kaju classes would remain the same -- just how my App.Open() and menu handler call it would change.

  17. Kem T

    May 21 Testers, Xojo Pro, XDC Speakers, MVP Connecticut

    Yes, please. This is a real head scratcher.

  18. Douglas H

    May 26 Testers, Xojo Pro

    @Kem T Yes, please. This is a real head scratcher.

    @Kem T, my user just got back to me and using an App class property (which I called mUpdateChecker) did NOT do it. Here is my revised code at the end of App.Open():

    if mKajuPrefsAppPath <> nil and mKajuPrefsAppPath.Exists then
      mUpdateChecker = new Kaju.UpdateChecker( mKajuPrefsAppPath )
      mUpdateChecker.AllowRedirection = true
      mUpdateChecker.ServerPublicRSAKey = kKajuPublicKey
      mUpdateChecker.UpdateURL = kKajuUpdateURL
      
      // Only check for final versions not previously ignored
      mUpdateChecker.AllowedStage = App.Final
      mUpdateChecker.HonorIgnored = true
      
      // Only allow window if update is available
      mUpdateChecker.AllowedInteraction = Kaju.UpdateChecker.kAllowUpdateWindow
      
      AddHandler mUpdateChecker.ExecuteAsyncComplete, WeakAddressOf Checker_ExecuteAsyncComplete
      mUpdateChecker.ExecuteAsync
    end if

    So I don't think it can be going out of scope now. The mUpdateChecker is a public property that I added to the App class.

    What else would you like me to try?

  19. Kem T

    May 26 Testers, Xojo Pro, XDC Speakers, MVP Connecticut

    What if they trash the prefs at mKajuPrefsAppPath?

  20. Douglas H

    May 26 Testers, Xojo Pro

    @Kem T What if they trash the prefs at mKajuPrefsAppPath?

    Is this just on the theory he may have an ignore set? I also have a menu option, and when he takes it he does NOT get any dialog at all including the "No updates available" that I get and everyone else gets. The menu handler looks like this:

    // See App.Open for some required setup
    
    // If we have app prefs folder, initialize update check
    if mKajuPrefsAppPath <> nil and mKajuPrefsAppPath.Exists then
      mUpdateChecker = new Kaju.UpdateChecker( mKajuPrefsAppPath )
      mUpdateChecker.AllowRedirection = true
      mUpdateChecker.ServerPublicRSAKey = kKajuPublicKey
      mUpdateChecker.UpdateURL = kKajuUpdateURL
      
      // Unlike app startup checks, show ignored final versions also
      mUpdateChecker.AllowedStage = App.Final
      mUpdateChecker.HonorIgnored = false
      
      // Allow window all the time (even if error etc)
      mUpdateChecker.AllowedInteraction = Kaju.UpdateChecker.kAllowAll
      
      AddHandler mUpdateChecker.ExecuteAsyncComplete, WeakAddressOf Checker_ExecuteAsyncComplete
      mUpdateChecker.ExecuteAsync
      
    else
      MsgBox "Unable to check for updates" + EndOfLine + EndOfLine + _
      "No preference file path is available.  Please contact support."
    end if
    
    Return True

    Note the .HonorIgnored = false statement.

    If you like, I can still have him delete the prefs file and try again but figured I could get you the above information faster if that was the only reason to ask.

  21. Kem T

    May 26 Testers, Xojo Pro, XDC Speakers, MVP Connecticut

    Yeah, that was it, but I'd still like to see.

    Where does "Checker_ExcecuteAsyncComplete" live?

  22. Newer ›

or Sign Up to reply!