Programmatically changing screen lock timeout - objective-c

In my Cocoa application I would like to access and change the computer's screen lock timeout setting. Changing it in System Preferences does not require the user to enter the admin password.
Unfortunately I couldn't find any information in the documentation, and I'm not sure what topic I should look into (security settings / prefPane programming).
Any help would be appreciated.

NSMutableDictionary* plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:#"/Users/new/Library/Preferences/com.apple.screensaver.plist"];
[plistDict setObject:#"1" forKey:#"askForPassword"];
[plistDict setObject:#"3600" forKey:#"askForPasswordDelay"];
[plistDict writeToFile:#"/Users/new/Library/Preferences/com.apple.screensaver.plist" atomically:YES];
or From terminal
defaults write com.apple.screensaver askForPasswordDelay 5

The above answer apparently works for some, but on 10.8 it fails if you are using FileVault. The setting will stick, but it won't actually take effect until you launch System Preferences. Luckily, there's a way to 'touch' the setting after you are done:
- (void)touchSecurityPreferences;
{
NSAppleScript *kickSecurityPreferencesScript = [[[NSAppleScript alloc] initWithSource: #"tell application \"System Events\" to tell security preferences to set require password to wake to true"] autorelease];
[kickSecurityPreferencesScript executeAndReturnError:nil];
}
Edit Turns out this only works for going from a non-zero setting to zero setting. I assume this is a security thing. To go the other way, launching System Preferences is the only way.
Edit 2 Here's code for launching System Preferences, should you want to do so:
- (void)launchAndQuitSecurityPreferences;
{
// necessary for screen saver setting changes to take effect on file-vault-enabled systems when going from a askForPasswordDelay setting of zero to a non-zero setting
NSAppleScript *kickSecurityPreferencesScript = [[[NSAppleScript alloc] initWithSource:
#"tell application \"System Preferences\"\n"
#" tell anchor \"General\" of pane \"com.apple.preference.security\" to reveal\n"
#" activate\n"
#"end tell\n"
#"delay 0\n"
#"tell application \"System Preferences\" to quit"] autorelease];
[kickSecurityPreferencesScript executeAndReturnError:nil];
}

Related

How to change safari setting programmatically

is it posible to change Mac safari setting by app after getting user permission if yes then how its done by objective c code. if no why.
An application can only change settings of another application if sandbox is disabled, by editing the application settings dictionary file:
NSString *safariSettingsPath = [#"~/Library/Preferences/com.apple.Safari.plist" stringByExpandingTildeInPath];
NSMutableDictionary *safariSettings = [[NSMutableDictionary alloc] initWithContentsOfFile:safariSettingsPath];
safariSettings[#"ExtensionsEnabled"] = #(NO);
[safariSettings writeToFile:safariSettingsPath atomically:YES];

ScriptingBridge without sdef? (cocoa)

I'd like to get properties of the currently active app. I understand that this should be possible with ScriptingBridge, however, this seems to require you generate an sdef file and import this in your project for the app you are trying to target. Since I want to target all apps, is there another way to do this?
Example of accessing system preferences:
SystemPreferencesApplication *systemPreferences =
[SBApplication
applicationWithBundleIdentifier:#"com.apple.systempreferences"];
If there's another way to access properties of any active app, please do share. (For example; window title)
Thanks.
I assume you want to run an applescript. The scripting bridge is good if you have a lot of applescript code to run. However if you only have a small amount then a simpler way is with NSApplescript.
For example if you wanted to run this applescript...
tell application "System Events"
set theProcesses to processes
repeat with aProcess in theProcesses
tell aProcess to get properties
end repeat
end tell
Then you can write it this way...
NSString* cmd = #"tell application \"System Events\"\nset theProcesses to processes\nrepeat with aProcess in theProcesses\ntell aProcess to get properties\nend repeat\nend tell";
NSAppleScript* theScript = [[NSAppleScript alloc] initWithSource:cmd];
NSDictionary* errorDict = nil;
NSAppleEventDescriptor* result = [theScript executeAndReturnError:&errorDict];
[theScript release];
if (errorDict) {
NSLog(#"Error:%# %#", [errorDict valueForKey:#"NSAppleScriptErrorNumber"], [errorDict valueForKey:#"NSAppleScriptErrorMessage"]);
return;
}
// do something with result
NSLog(#"result: %#", result);
You can get a list of every currently running Application with
NSWorkSpace.sharedWorkspace.runningApplications;
Each object in that array should be an NSRunningApplication, which you can query and manipulate freely.

Window Constantly Wants To Be On Top Of Others - Xcode

My app has buttons that open automator workflows like this:
- (IBAction)actionname:(id)sender {
NSTaskname = [[NSTask alloc] init];
[NSTaskname setLaunchPath:#"/usr/bin/automator"];
NSArray *arguments;
arguments = [NSArray arrayWithObjects:#"/Applications/appname.app/Contents/Resources/workflowname.workflow", nil];
[NSTaskname setArguments:arguments];
[NSTaskname launch];
}
The only problem is, that every single one appears behind the window of my app. Also, one workflow launches another app which also appears behind the window.
How can I fix this?
You can probably use NSRunningApplication to bring your NSTask process to the front with its PID like this...
NSRunningApplication* app = [NSRunningApplication runningApplicationWithProcessIdentifier:[NSTaskname processIdentifier]];
[app activateWithOptions: NSApplicationActivateAllWindows];
And if you need to activate a specific application, for example your workflow that launches another app, then you could do this using the application's bundle identifier. This example will activate Safari.
NSArray* apps = [NSRunningApplication runningApplicationsWithBundleIdentifier:#"com.apple.Safari"];
[(NSRunningApplication*)[apps objectAtIndex:0] activateWithOptions: NSApplicationActivateAllWindows];

How to check whether app is running using [[NSAppleScript alloc] initWithSource:

This is my original script. It will return the current url of Safari
NSAppleScript *scriptURL= [[NSAppleScript alloc] initWithSource:#"tell application \"Safari\" to return URL of front document as string"];
What if I want to check whether the Safari browser is open or not before asking the script to return the URL?
Here is how I do in applescript editor.. So this script will check whether the Safari is running or not.. This works in applescript editor
tell application "Safari"
if it is running then
//return url code here
end if
end tell
What I need now is to straight away called the script from my cocoa app by using ' [[NSAppleScript alloc] initWithSource:'
I've tried this but its not working
NSAppleScript *scriptURL= [[NSAppleScript alloc] initWithSource:#"tell application \"Safari\" if it is running to return URL of front document as string"];
Why would that work? It's bad AppleScript grammar.
There are ways to do this without resorting to AppleScript, but it'll do for now. You can have multiple lines in an embedded script by using the C escape sequence \n to insert a newline:
NSString *source = #"tell application \"Safari\"\nif it is running then\nreturn URL of front document as string\nend if\nend tell";
You can also break up a string constant by placing one right after another, which makes it easier to read:
NSString *source =
#"tell application \"Safari\"\n"
"if it is running then\n"
"return URL of front document as string\n"
"end if\n"
"end tell";
The C compiler will glue these string constants together into a single NSString object.
The OP's AppleScript one liner code is wrong. The AppleScript text in this should work:
NSAppleScript *scriptURL= [[NSAppleScript alloc] initWithSource:#"tell application \"Safari\" to if it is running then return URL of front document as string"];
As dougscripts (+1) has pointed out but I wanted to make it little bit clearer of why the one liner Applescript syntax within the NSAppleScript the OP tried did not work.
And to be honest I did suggest an edit which lost out three to two
The OP's NSAppleScript code:
NSAppleScript *scriptURL= [[NSAppleScript alloc] initWithSource:#"tell application \"Safari\" if it is running to return URL of front document as string"];
Did not work because the syntax is wrong. 
The correct syntax should be:
NSAppleScript *scriptURL= [[NSAppleScript alloc] initWithSource:#"tell application \"Safari\" to if it is running then return URL of front document as string"];
There are two changes within part of the code shown in bold below.
\"Safari\" to if it is running then return URL

Is there a way to programmatically connect to a remote server from Cocoa?

Is there an Coca/obj-C API call to mimic the "Connect to Server" action in Finder? It's possible with Automater, so it seems like Finder has a hook somewhere.
Turns out there's an old Carbon function (can't find a Cocoa equivalent) called FSMountServerVolumeSync which does what I was looking for. You can supply and smb:// URL and login credentials.
File Manager Reference
OSStatus FSMountServerVolumeSync (
CFURLRef url,
CFURLRef mountDir,
CFStringRef user,
CFStringRef password,
FSVolumeRefNum *mountedVolumeRefNum,
OptionBits flags
);
An easy way is to just run some applescript code. I'll show you 2 choices. This first one is the standard way to show that Finder window from applescript.
NSString* cmd = #"choose URL";
The resulting window is bare-bones though, so you can actually open the Finder's window with this command...
NSString* cmd = #"tell application \"Finder\" to activate\ndelay 0.2\ntell application \"System Events\" to keystroke \"k\" using command down";
After choosing either of the "cmd" strings, you can execute that applescript code with this...
NSAppleScript* theScript = [[NSAppleScript alloc] initWithSource:cmd];
[theScript executeAndReturnError:nil];
[theScript release];
This might not be the best way, but can't you just use mount?