[Re] How to extract data from NSAppleScript?

AnaghSharmaAnaghSharma USMember ✭✭

Apologies for not providing specific information in the last question.

I have been working on a demo macOS menu bar app just to explore Xamarin. In order to have the "Launch at Login" option in app, I am executing a script using NSAppleScript. It works fine and the app gets added to Login items of macOS. But there may be some cases when -

  1. User can remove the app from login items using System Preferences.
  2. User can add the app again to login items using System Preferences.

In that case, my "Launch at Login" functionality would break. As a workaround, I thought I can check if the item is already in the login items and found out that it's fairly possible using AppleScript. But I could not find out how to get the result back after executing a script.

Thanks.

Best Answer

  • AnaghSharmaAnaghSharma US ✭✭
    Accepted Answer

    @XavierFortin Thanks a lot. I made some changes to the script and can finally have the Launch at Login functionality.

    Here is the script -
    tell application "System Events"
    get the name of every login item
    if login item "AppName" exists then
    return true
    else
    return false
    end if
    end tell

Answers

  • XavierFortinXavierFortin USMember ✭✭

    Hi,

    I think this is more of a Cocoa question, than a Xamarin.Mac specific one.

    Nonetheless, are you using an NSAppleScript object?

    If so, the ExecuteAndReturnError return an NSAppleEventDescriptor object. I'm pretty sure you can get the return value of an executed Apple Script with NSAppleEventDescriptor properties like BooleanValue, StringValue, etc...

  • AnaghSharmaAnaghSharma USMember ✭✭

    Yes. I am using NSAppleScript object.

    I had already tried NSAppleEventDescriptor before but did not find it helpful (StringValue doesn't return anything useful).

    Is there any way where I can listen to and get notified to any change (addition/removal of my app) in system preferences?

  • XavierFortinXavierFortin USMember ✭✭

    Well, in this case, I think there might be an issue with your script. Showing it to us might be helpful in helping you.

    Just to make sure, I tried this:

    NSAppleScript appleScript = new NSAppleScript("return \"Test\"");
    
    NSDictionary error;
    NSAppleEventDescriptor result = appleScript.ExecuteAndReturnError(out error);
    
    Console.WriteLine(result.StringValue);
    

    And I get the expected "Test" string in the console output.

    Is there any way where I can listen to and get notified to any change (addition/removal of my app) in system preferences?

    As for this, I genuinely have no idea.

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    Is there any way where I can listen to and get notified to any change (addition/removal of my app) in system preferences?

    I also have no clue, but I know that Apple has provided very little in programmatic APIs related to System Preferences and it would not surprise me if there was no supported way to query there. It is considered a "user setting".

  • AnaghSharmaAnaghSharma USMember ✭✭

    @XavierFortin I am trying this -

    NSAppleScript login = new NSAppleScript("tell application \"System Events\"\n return login items\n end tell");
    NSDictionary errors = new NSDictionary();
    NSAppleEventDescriptor result = login.ExecuteAndReturnError(out errors);
    Console.WriteLine(result.StringValue);
    

    StringValue is still null. Yes there might be something wrong with the script but it works fine when I tried it in the in-built Script Editor app of macOS.

    @ChrisHamons I asked this because I have seen the same in one of the menu bar app that I use. As soon as I remove that app from login items, the checkbox for Launch at Login gets unchecked in the in-app settings window.

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    From: https://developer.apple.com/documentation/foundation/nsapplescript/1410034-executeandreturnerror?language=objc

    Return Value: The result of executing the event, or nil if an error occurs.

  • XavierFortinXavierFortin USMember ✭✭
    edited July 2017

    Hi,

    StringValue is null because your script actually returns a complex structure and not a string. You can see this by checking the NumberOfItems property on you NSAppleEventDescriptor. You'll have to use method such as DescriptorAtIndex or DescriptorForKeyword to find your specific items in the result.

    If you do a ToString on the NSAppleEventDescriptor, you should see the dictionary like structure.

    You could also change your script so it returns a more simple value (e.g. passing exactly what you're searching for as an argument and returning true or false if it finds it).

  • AnaghSharmaAnaghSharma USMember ✭✭

    StringValue is null because your script actually returns a complex structure and not a string. You can see this by checking the NumberOfItems property on you NSAppleEventDescriptor. You'll have to use method such as DescriptorAtIndex or DescriptorForKeyword to find your specific items in the result.

    Seems like I was checking the wrong entity all this time.

    You could also change your script so it returns a more simple value (e.g. passing exactly what you're searching for as an argument and returning true or false if it finds it).

    This seems like what I am looking for. I'll try it and let you know. Thanks @XavierFortin :)

  • AnaghSharmaAnaghSharma USMember ✭✭
    Accepted Answer

    @XavierFortin Thanks a lot. I made some changes to the script and can finally have the Launch at Login functionality.

    Here is the script -
    tell application "System Events"
    get the name of every login item
    if login item "AppName" exists then
    return true
    else
    return false
    end if
    end tell

  • XavierFortinXavierFortin USMember ✭✭

    Glad to hear it.

    I'd choose your last post as the answer to your question, so anyone looking for similar issue would know this post has been answered to.

Sign In or Register to comment.