Send both computer shut down command and Quit my application

  1. ‹ Older
  2. 4 months ago

    Sagi G

    Jan 13 Pre-Release Testers
    Edited 4 months ago

    Hi @Stéphane ;Thank you very much for the feedback!
    Professional media content creators, the only clients for this app, work almost exclusively with robust workstations and never ever put the machine to sleep, most media creators leave the machine on 24/7 some shut down at nights and some only shut down during weekends.
    In fact as part of 'Media work optimisation' many of them even go step further and remove hibernation completely from their systems to make the machine more efficient and light.
    In light of this I don't expect this feature to be much in use, if ever, but still I give the option even if for rare cases.
    It works and I can leave it as is, but it bothers me I don't know how to delay the shut down event under OS X to make it 'slicker'

  3. @Sagi G — Oh, I see! What I don't understand, however, is why you want a delay. Is it just to allow your app to properly quit?

  4. Sagi G

    Jan 13 Pre-Release Testers

    You got it @Stéphane ;Mons
    If the Shell command is executed immediately the app ever get to quit properly , and if I quit the app first I can't send the shutdown command. of course timer will not work either so the only proper solution is to do as I do under Windows: 'shutdown -s -t 15' which gives me 15 seconds to operate, I was hoping someone have an idea how to achieve such command-line under Mac as well.

  5. @Sagi G — Well I don't think it should be an issue on macOS, especially if you execute the command in the App.Close event (which is executed only if you haven't cancelled quitting). This is your last chance of executing anything and your app effectively quits as soon as it encounters a Return.

    Shutting down is not a synchronous process because it will let up to 30 seconds for each process to quit before it tries more radical methods. Your app should have plenty of time to actually quit before the system shuts down. Or are you experiencing something different?

  6. Kem T

    Jan 13 Pre-Release Testers, Xojo Pro, XDC Speakers New York

    If you look at the Kaju project, you'll see the technique I use to run a shell script after the app has quit. In short, I write the shell script, then call it through a Shell using nohup. In your case, you'd do that in App.Close and the script would pause for a couple of seconds, then call shut down.

    https://github.com/ktekinay/Kaju

    But I think this is all too complicated. Your entire point is that you don't want your app reopening on restart, yes? I think there is a key you can write to or include in a plist somewhere that will tell the OS to skip your app, in which case you can just call shut down directly.

  7. Sagi G

    Jan 13 Pre-Release Testers

    Hmmm... I think I get it now that you mention App.close
    My code was sitting on a timer because it's part of a larger event I created that clean things up and needs time, but you're definitely right, I can (and should) move this part of the code to App.close
    Stupid of me not to do that as I already have there some other closing arrangements.
    I'll make the switch and report back with the results once tested on all OS environments.
    Thanks @Stéphane ;Mons !

  8. Sagi G

    Jan 13 Pre-Release Testers

    @Stéphane ;Mons unfortunately moving the code to the app close event handler did not help, the immediate execution still override the app close event, I guess it makes sense because the app waits for the shell result property but the system is already shutting down (without waiting for applications Quit confirmation).

    @Kem T Thanks for chiming in, you are right, I do want to keep it simple without external scripts or plist alteration, plus, my Mac skills are limited as is so I'm looking for a more straight up solution.

    So odd there is no match to Windows: shutdown -s -t 15 on Mac without using something like: sudo shutdown -h +2 which of course require admin password authorization.

  9. Kem T

    Jan 13 Pre-Release Testers, Xojo Pro, XDC Speakers Answer New York

    You should avoid that anyway as it's a sudden stop rather than an orderly shutdown.

  10. Sagi G

    Jan 13 Pre-Release Testers

    @Kem T You should avoid that anyway as it's a sudden stop rather than an orderly shutdown.

    Okay, so you say Mac can not do what Windows can in that regard and that method should be avoided, got it Thanks.

  11. Kem T

    Jan 13 Pre-Release Testers, Xojo Pro, XDC Speakers New York

    I don't actually know what that command does on Windows. If it's a sudden stop too, I'd recommend against it as well.

  12. Sagi G

    Jan 13 Pre-Release Testers

    Windows shutdown -s -t 15 is a legit scheduled shutdown command which activates Windows Shutdown/Reboot/Log Off mechanism and it has all the necessary Syntax switches.
    https://www.lifewire.com/shutdown-command-2618100

  13. Kem T

    Jan 13 Pre-Release Testers, Xojo Pro, XDC Speakers New York
    Edited 4 months ago

    The reason this works on Windows is because of the difference in Shell on the platforms. On the Mac, the executed commands are tied to Shell that started them. If that Shell is terminated, the underlying commands are too. On Windows, though, they are detached and will survive the destruction of the Shell and even your app quitting.

    The way to do this on the Mac is to use nohup, but I have another solution for you. Include an AppleScript applet with your app that is launched during App.Close. That applet will wait a couple of seconds, then tell System Events to shut down.

    The only thing I don't know is if the applet will be relaunched on restarted causing an annoying loop. Frankly, I'd include the shell script and call it using nohup.

  14. Sagi G

    Jan 13 Pre-Release Testers

    @Kem T Hahaha, Thanks for the offer but I think I'll pass for now as I mentioned my Mac skills are still a bit limited.
    Just now getting to know this OS, My Application started as Windows only and lots of Mac users saw it and implore me to make it available for Mac as well but I'm far from being able to include a shell script and call it using nohup.
    I'm just happy right now it all finally work in Mac as it works in Windows, took me a lot of time adjusting the code to get to this point, not as easy as I thought it would be using cross-platform development tool :)
    If shutdown become that complicated in Mac my Mac users can easily live without that single feature.

  15. Lennox J

    Jan 13 Jamaica. West Indies

    Hi Kem,

    I would like to take that offer the applet.

    Thanks again.

    Lennox

  16. Kem T

    Jan 13 Pre-Release Testers, Xojo Pro, XDC Speakers New York

    Er, I wasn't really offering to write it, but here's a shot:

    delay 5
    tell app "System Events" to shut down

    Save that as an app using Script Editor, copy it to the app's Resources (or similar) folder using a compile script, then call it in App.Close with something like this:

    dim f as FolderItem = SpecialFolder.Resources.Child( "My Shutdown.app" )
    f.Launch
    //
    // Give it two seconds
    //
    dim targetTicks as integer = Ticks + 120
    while Ticks < targetTicks
      App.YieldToNextThread
    wend

    If you want to go the script route, save this script as something like "My Shutdown.applescript" to the Resources folder (mind the permissions):

    #!/usr/bin/osascript
    
    delay 5
    tell app "System Events" to shut down

    Call it this way:

    dim f as FolderItem = SpecialFolder.Resources _
        .Child( "My Shutdown.applescript" )
    dim cmd as string = "/usr/bin/nohup " + f.ShellPath
    
    dim sh as new Shell
    sh.Mode = 1
    sh.Execute cmd
    
    // Same delay code as above
    
    sh.Poll

    I haven't tested this, but conceptually it should work.

  17. Sagi G

    Jan 13 Pre-Release Testers

    Brilliant @Kem T !
    I've just finished making the script and I'm struggling with the execution method and I see your post right on time :)

  18. Lennox J

    Jan 13 Jamaica. West Indies

    Thanks Kem,

    Shuts dow the Mac, but on reboot all open windows and documents are relaunched.

    Thanks again.

    Lennox

  19. Kem T

    Jan 13 Pre-Release Testers, Xojo Pro, XDC Speakers New York

    That's the default behavior of the Mac OS. Are you saying that your app is among those that are relaunched?

  20. Lennox J

    Jan 13 Jamaica. West Indies
    Edited 4 months ago

    Hi Kem,

    I just launched the AppleScript itself, I did not use it from any app.

    I saw this...

    defaults write org.x.X11 wm_auto_quit -bool true
    Automatically quit quartz-wm (thus shutting down the X11
    server) when the last window is closed.

    defaults write org.x.X11 wm_auto_quit_timeout -int 3
    Set the timeout for the auto-quit feature. If wm_auto_quit is
    true, quartz-wm will wait this many seconds before attempting
    to shutdown. If another window is created in that time,
    quartz-wm will not shutdown.

    Is it possible to code that in Xojo?

    Thanks.

    Lennox

  21. Sagi G

    Jan 13 Pre-Release Testers
    Edited 4 months ago

    Okay, so I was half an hour away from giving up with my super slow VirtualBox Mac testing machine but it finally work.
    For the record if anyone try this here are my findings:

    Write an AppleScript in my case:

    delay 5
    tell app "System Events" to shut down

    Save it as usual or export it to your project location for project management convenience.
    Name it whatever suits you, I named it SDSq.scpt
    Open the project
    Import/Drag the script onto the project Contents/Navigator.

    Now,

    1. For some reason I can't add Quote in the App.Close so I had to move the code elsewhere, I used my existing timer for this
    2. FolderItem.ShellPath did not work only NativePath

    The code in the timer look like so:

    If Shutdown Then
      #if TargetMacOS Then
       Dim k As FolderItem = SpecialFolder.Resources.Child("SDSq.scpt")
        If k <> Nil and k.Exists Then
         cmd = "osascript """ + k.NativePath + Quote
        End If
      #Elseif TargetWindows Then
        cmd = "shutdown -s -t 15 -c ""Scheduled Shutdown starts in 15 seconds By By"""
      #endif
    End If
    Me.Mode = 0
    Quit

    In the App.Close event I ended up with this:

    If Shutdown Then
          dim sh as new Shell
          sh.Execute cmd
       #If TargetMacOS Then
          // Give it two seconds
          dim targetTicks as integer = Ticks + 120
          while Ticks < targetTicks
          App.YieldToNextThread
          wend
       #endif
    End If

    Note: in case any other machine is logged on to the target machine you are trying to shut down, the script will never get carried out by itself, a confirmation dialog box pops out and nothing shall happen if no one confirms it.

or Sign Up to reply!