How to relaunch current program in macOS with execl("/usr/bin/open"...)? - c

I can successfully launch an app with
execl("/usr/bin/open", "open", "/Applications/Foo.app", 0);
But this doesn't work when I'm calling it inside Foo.app
I want my app to relaunch itself when it crashes and autoupdates.
Thanks!

open won't start a second instance of your app if one is already running, it will simply make it the active app.
You can start a second instance of your app by executing the app bundle's executable:
excel("/Applications/Foo.app/Contents/MacOS/Foo", ...
While not the recommended way to launching a Cocoa app, I've been assured by Apple engineers that this will work. But be warned, you now have two instances of your app running, sharing the same NSUserDefaults, and other resources, so expect some strange behavior (or immediately terminate the first app through exit()).
Having said that, this probably isn't want you want to do.
First, you can't "detect a crash and take some action" as—by definition—your app has crashed. There are packages out there that will detect a crash and log information about it; look to a solution like that to restart your app.
As for updates, again I'd steer you towards a third-party solution like Sparkle. It handles quitting your old app, replacing it, and then launching the new one in a sane manner.
Finally, you can register your app as a "user agent" with launchd so that it gets automatically restarted if it quits.

Related

Packaged shell extension killing application

I have a WPF application. To give it an identity to consume UWP APIs, I've added sparse package support. This installs / uninstalls / updates (we're not using MSIX) with my WPF application fine, and my app is running with an identity. It shows in task manager with a Package Name listed on my process.
Now I'm attempting to add context menu support following Microsoft's docs.
I've created a shell extension which will show when opening the context menu for any file and folder, which is pretty much a copy of their sample with different GetIcon(), GetTitle() and Invoke() implementations for IExplorerCommand.
I'm specifying this in the AppxManifest.xml (values anonymised):
<desktop4:Extension Category="windows.fileExplorerContextMenus">
<desktop4:FileExplorerContextMenus>
<desktop5:ItemType Type="*">
<desktop5:Verb Id="MyFileCommand" Clsid="file-guid"/>
</desktop5:ItemType>
<desktop5:ItemType Type="Directory">
<desktop5:Verb Id="MyFolderCommand" Clsid="folder-guid"/>
</desktop5:ItemType>
</desktop4:FileExplorerContextMenus>
</desktop4:Extension>
<com:Extension Category="windows.comServer">
<com:ComServer>
<com:SurrogateServer DisplayName="SSVerbHandler">
<com:Class Id="file-guid" Path="my-shell-extension.dll" ThreadingModel="STA"/>
</com:SurrogateServer>
<com:SurrogateServer DisplayName="SSVerbHandler">
<com:Class Id="folder-guid" Path="my-shell-extension.dll" ThreadingModel="STA"/>
</com:SurrogateServer>
</com:ComServer>
</com:Extension>
This works, my context menu entry is listed and performs the action as expected. But here's the issue: each time the context menu is opened for the first time, it kills the already running instance of my WPF application. By first time, I mean restarting explorer.exe and right clicking on a file or folder.
My gut feeling is this is related to UWP side of things. This is because originally it would always kill my application when right clicking to open a context menu. But with a little trial and error I solved this by configuring multi-instance support in my AppxManifest.xml:
<Package
...
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
xmlns:iot2="http://schemas.microsoft.com/appx/manifest/iot/windows10/2"
IgnorableNamespaces="uap mp desktop4 iot2">
...
<Applications>
<Application Id="App"
...
desktop4:SupportsMultipleInstances="true"
iot2:SupportsMultipleInstances="true">
...
</Application>
</Applications>
...
</Package>
I'm hoping someone can suggest any troubleshooting ideas as I'm now struggling.
I've sprinkled some ol' trusty MessageBox functions within the shell extension in DllMain, DllCanUnloadNow and DllGetClassObject. But for that first load attempt, no message boxes are shown, no context menu item listed and my application is still killed.
I've poked around in the event viewer hoping to see any errors or warnings listed recently, plus in Applications and Service Logs\Microsoft\Windows\Appx* and Applications and Service Logs\Microsoft\Windows\AppModel-Runtime. Nothing has jumped out at me.
According to this SO anwser, if there's an error with the shell extension itself, it may not show. That does fit, but I'm sceptical as it always works on subsequent attempts, and the previously solved UWP killing issue.
In the scenario where my application stops, using these powershell commands I get:
$process = Start-Process .\MyApp.exe -PassThru -Wait
$process.ExitCode
1
I do have crash logging in my app, but nothing gets logged. This is the only place Environment.Exit(1) is called within the WPF application.
I did try the silent monitoring detection in GFlags on the WPF application, but couldn't seem to trigger it. Only when I manually closed the application. (Ignore Self Exits unchecked for testing). I'm not sure if that's because the exit code is 1.
When the error occurs with process monitor running, I can see lots of ThreadExit before a final ProcessExit with the exit code 1. That would imply it's exiting cleanly with my application itself returning 1?
It's also worth mentioning I've lived in managed / .NET land for the last decade or so, I don't have much experience with C++ (or unmanaged languages in general) or UWP, and the first time I've attempted to write a shell extension.

React Kiosk App keeps crashing on Chrome - Chrome not Responding

We have a Kiosk app which runs on Chrome Kiosk mode and is written in React JS. But for some of our Kiosk machines (All of our machines are Windows machines), it seems to be crashing regularly (Approx. %4 of the devices) without any user input or fixed time between crashes.
I reviewed the code several times but never found any background tasks running, or any reason for the Chrome to crash at all.
Because the crashes are irregular, I cannot connect to a problematic device and wait for it to crash for hours to debug the process. And because the app is automatically started via a VB script when Windows is started, the clients often "solve" the crashes by restarting the Kiosk machine, which is time consuming and leads to tons of complaints.
So my questions are;
Can I somehow force Chrome to restart, or lets say Go to first page in history if it crashes?
Can I catch errors globally without using ErrorBoundries in JavaScript (It is already implemented and is used for other things)
I tried using --remote-debugging-port=9222 to use Developer Tools, but I need to be connected to the machine and go to localhost:9222 port manually to use this and cannot afford to be connected to the device all the time. So is there a way to connect and use Developer Tools on 9222 port remotely?
I tried saving console logs to a file (using Chrome Command Line Arguments) but never saw any "Errors" on the list, so is there any arguments to help me save crash logs to a file to inspect them after the crash?
Thanks for all your help.

macOS: Keep XPC Service (bundled) running after user quits main app

The bundled XPC Service in my macOS application need to do some post processing work with files dumped by the parent app, which most probably can't be completed within the usage time of the application. So, Is there a way to make the XPC service keep running even after the user quits the main app?
You could install it as launch daemon (running in root context as long as computer is switched on) or as launch agent (running in user context as long as user is logged in).
It sounds like you should be using the WatchPaths or QueueDirectories feature of launchd.
WatchPaths starts the job whenever any of the paths being watched have changed
or
QueueDirectories starts your job whenever the given directories are non-empty, and it keeps your job running as long as those directories are not empty
Both of these are covered by Apple's launchd documentation.

Windows 10 BackgroundUploader breaks after app restart

I'm trying to upload some video files using BackgroundUploader component.
It works great if I keep the application open until the transfer completes.
It also works great if the app is closed, the transfer is completed under the hood, which is great.
But it doesn't work if the application is restarted (rerun normally) before the transfer is finished. Simply put, there is no sign of error, the UploadOperation status is running but nothing happens anymore regarding this upload request.
I can see using WireShark that the transfer is stopped:
When the application starts there is no code that does anything regarding BackgroundUploader.
I don't know why but it behaves as normal when the app is not run from Visual Studio even if it is only Start Without Debugging.
Is this some kind of know issue or limitation?
What will happen with background transfers if the app is updated via Windows Store in the middile?

Windows Service with running some Process

I have a problem with windows service. I'd like to his level run the program in a given situation. Every minute check a certain value and if the value is to adopt "truth" is to me the program starts. Only at the moment this does not work ...
The problem is that when debugging the code executes correctly, it displays my window, but the service is run normally nothing happens ...
Link to movies about this all:
https://youtu.be/GPv5dn92BGg
You need to jump through several hoops to launch interactive applications from a service. First, the service needs to be explicitly allowed to interact with the desktop. Then the service needs to specify the correct WindowStation for it to show on.
It may be simpler to just set your child application up as a scheduled task, as these can interact with the desktop for you

Resources