Xamarin.Mac: Launch another application with arguments in the sandbox - xamarin

I implemented launch at login for my application using this tutorial:
https://blog.timschroeder.net/2012/07/03/the-launch-at-login-sandbox-project/
Basically you would need to implement a Helper app that will be registered to start at login and the Helper will launch your application.
The problem is that I would like to launch my application hidden and for that I need to pass it one argument. Unfortunately I didn't find any way to do that.
I found these methods to launch an App:
//Works to launch the app but no way to pass arg
var app = SBApplication.FromBundleIdentifier(PackageId);
app?.Activate();
//Same issue here
NSWorkspace.SharedWorkspace.OpenFile("/Applications/HelloWorld.app")
//If you run the code bellow outside of the sandbox it works fine.
//Inside of the sandbox it just launches the app but without args
var aTask = NSTask.LaunchFromPath("/usr/bin/open",
new string[] { "-a","HelloWorld.app", "--args", "--hidden" });
aTask.Launch();

Related

macOS - Impossible to launch an app with localized name and space

I have this macOS app that is launched at login. This app has a space in the name "My App.app".
For that matter, I have created a helper app that loads at login and launches the main app.
I am inside this helper, trying to launch the main app.
For this reason I need to get the main app path. So, I do:
let appName = "My App.app"
let path = "/Applications/" + appName
let newURL = NSURL.fileURL(withPath: path)
when I try to use this
let app = try NSWorkspace.shared.launchApplication(at: newURL,
options:[.withErrorPresentation, .inhibitingBackgroundOnly, .async],
configuration: [:])
I get an error "APPLICATION NOT FOUND".
One of the problems is that the App contains a space in the name "My App.app". I remove the space in the app name and this command successfully launches the app.
But I need the space in the name.
Then I try to launch the app using the bundle identifier.
NSWorkspace.shared.launchApplication(withBundleIdentifier: mainAppBundleIdentifier,
options: [.withErrorPresentation, .inhibitingBackgroundOnly, .async],
additionalEventParamDescriptor: nil,
launchIdentifier: nil)
then I get another error,
MyApp can’t be opened. Move “My App” to the Applications folder and try again.
The problem is that the app is already on the Applications folder.
then I use this, just to check
let path = NSWorkspace.shared.absolutePathForApplication(withBundleIdentifier: mainBundleId)
and I get this
"/Users/myself/Library/Mail/V6/0982138471-EA33/[Gmail].mbox/All
Mail.mbox/871628745618726547816A/Data/2/8/5/Attachments/582584/2/MyAppMac.app"
WTF!!??
Two things wrong about this:
This is a link to an email I have sent yesterday to a tester, sending him the application.
The app mentioned in the link is MyAppMac.app that is the Xcode target name, without localization.
How in the heavens name do I launch an app from another app when the app contains a space in the name and is localized?
How do I get the target name?
The usual way to launch the main application is first to check if it's already running and if not to run the executable and pass a variable to inform the main application that it was launched by the helper
For example
func applicationDidFinishLaunching(_ aNotification: Notification) {
let appName = "Foo"
let bundleIdentifier = "com.spacedog.foo"
if NSRunningApplication.runningApplications(withBundleIdentifier: bundleIdentifier).isEmpty {
let bundleURL = Bundle.main.bundleURL
var pathComponents = bundleURL.pathComponents
pathComponents.removeLast(3)
pathComponents.append(contentsOf: ["MacOS", appName])
let mainAppURL = NSURL.fileURL(withPathComponents:pathComponents)!
let options = [NSWorkspace.LaunchConfigurationKey.arguments : ["launchedAtLogin"]]
_ = try? NSWorkspace.shared.launchApplication(at: mainAppURL as URL, options: .withoutActivation, configuration: options)
}
NSApp.terminate(nil)
}

Launching an Electron app on Windows restart

So I've built a Windows installer for my Electron app using https://github.com/electron/grunt-electron-installer.
I'm not sure how to launch my app on system start up, like when the user reboots their computer. I suspect it's something I need to do on --squirrel-install but I can't find any documentation on how to do so.
Ideally I would provide a menu option for the user to enable/disable this behaviour.
If you are using electron on Windows/MAC, there is an existing api which you can use to easily auto start your electron APP:
_electron.app.setLoginItemSettings({
openAtLogin: true,
path: _electron.app.getPath('exe')
})
the reference can be found here:
https://electronjs.org/docs/api/app#appsetloginitemsettingssettings-macos-windows
This can be done in a few different ways. The method i used to do this on a windows OS was to use the node winreg module, this allowed me to add a registry key that launched that app on startup. I use this method on a settings window in the application that has some user settings:
function setKeyValue () {
var regKey = new winreg({
hive: winreg.HKCU,
key: '\\Software\\Microsoft\\Windows\\CurrentVersion\\Run'
});
regKey.set('Your_Application_Name', winreg.REG_SZ, '"' + process.execPath + '"', function (err) {
if (!err) {
//notify user?
}
});
I also have the opposite method that removes the reg key regKey.remove if the user disables the app launch on startup.
Alternatively, i have recently seen this node module: auto-launch ,this allows you to set whether the app launches on startup on Mac, Windows and Linux, and therefore might be more useful for you.

Change Parse Application when App is running

I have an Android Application that works with locals instalations and I want use it with diferents Parse applications. Each instalation administrator will contract with Parse directly. When app start it will look for the keys for parse.
I wonder how to change the Parse App linkeded in the Android App once this is running
I have tried to call Parse.initialize (context, apllicationId, clientKey) twice but it doesn't work. I have tried the app register in diferent Parse App every time you start the App link with a different Parse App
It´s always linked only with the first application
public void onCreate(final Bundle icicle){
super.onCreate(icicle);
final Context context = this;
setContentView(R.layout.ssa);
getActionBar().hide();
// Getting the global variables
fmGlobalsBean = Utilities.getGlobals(this);
if(!"".equals(fmGlobalsBean.getUrl_server())){
Parse.initialize(contexto, "p4IWkTRc0WTdKkMH6r60hjYzwX1TIXChy8VcDvPb", "KhkcX4G3dqVpRawHyIYfnHAWqj1H2vyhwD3wINlQ");
ParseInstallation.getCurrentInstallation().saveInBackground();
ParsePush.subscribeInBackground(fmGlobalsBean.getUrl_server());
}
else
{
Parse.initialize(this, "Y3xgZ58u4Qcn9TrovFqCOe4PBzhURjXooZ3vDKgB", "ealo3nm4wa4lbJ7KrSR2OSf60DZiUjEUjdUJTQzs");
ParseInstallation.getCurrentInstallation().saveInBackground();
ParsePush.subscribeInBackground("INITIAL");
}
}

Unable to make my OS X app (written in swift) launch at login

Some details:
I am not enrolled into Mac Developer program, hence the code is not signed.
I am not sandboxing the app.
It's a status bar only app, no dock or menu will appear.
Here's what I did:
Added a new project for helper app on top my existing main app project.
In main app settings:
Added ServiceManagement.framework framework to my main app.
Set Strip Debug Symbols During Copy to NO
In Build Phases tab, under Copy Files, added Contents/Library/LoginItems as Subpath. And added my Helper App.app
For helper app settings:
Set Application is background only to YES
Under Build Settings, set Skip Install to YES
Hocus Pocus.app is my main app and Hocus Pocus Helper.app is helper app.
In AppDelegate of helper app, my code is:
func applicationDidFinishLaunching(aNotification: NSNotification) {
NSWorkspace.sharedWorkspace().launchApplication("Hocus Pocus.app")
NSApplication.sharedApplication().terminate(self)
}
In AppDelegate of main app:
...
override init() {
self.mainBundle = NSBundle.mainBundle()
let path = mainBundle.bundlePath.stringByAppendingPathComponent(
"Contents/Library/LoginItems/Hocus Pocus Helper.app")
self.helperBundle = NSBundle(path: path)!
super.init()
}
...
...
func makeThisAppStartAtLogin(state: Int) {
let result = SMLoginItemSetEnabled(helperBundle.bundleIdentifier!, Boolean(state))
if result != 0 {
println("success")
}
else {
println("failed")
}
}
It's not working when I call makeThisAppStartAtLogin(1), why?
Apple documentation mentions:
The Boolean enabled state of the helper application. This value is effective only for the currently logged in user. If true, the helper application will be started immediately (and upon subsequent logins) and kept running. If false, the helper application will no longer be kept running.
When I call makeThisAppStartAtLogin(_:), it should start helper app immediately. But it doesn't seem to be doing that.
The if block prints success.
In Helper App code, I also sent the path to launchApplication(_:) instead of app name, it did not make any difference.
I have ran this app from default debug directory and also under /Applications
I have also tried following, it didn't make any difference:
...
let launchDaemon: CFStringRef = "avi.Hocus-Pocus-Helper"
if SMLoginItemSetEnabled(launchDaemon, Boolean(state)) {
...
I have checked that helper app is copied to main app at correct path.
When I launch the helper app manually, either from debug folder or from main app's Contents, it does launches main app and kill itself, as it should.
Here's the full repository, if you are interested. Check loginitems branch.

Multiple Facebook Canvas Applications within same web application - CanvasAuthorizeAttribute

I am having a problem with running multiple Facebook applications under a single Web application.
Similar to this problem:
Multiple facebook apps under one web application
I do like the solution suggested here, however the CanvasAuthorizeAttribute uses the FacebookApplication.Current internally and this is a static instance of the FB application within the Web application.
I can't call the .SetApplication method within the controller as I will have concurrency issues.
It would be nice if the FacebookApplication.Current called the Func that is passed into the .SetApplication instead of just calling inside of the .SetApplication.
That way I could pass a function that does my logic for retrieving the correct FB application.
Am I missing something that is already in the SDK?
You can always have your own logic at http://facebook.stackoverflow.com/questions/4931240/multiple-facebook-apps-under-one-web-application/4936703#4936703
private IFacebookApplication Current
{
get
{
var url = HttpContext.Current.Request.Url;
var app = GetSettingsForUrl(url);
// put your custom logic here and return the appropriate IFacebookApplication
return app;
}
}
But you should do this during Application_Start where it is still running on a single thread and not in Controller.

Resources