<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Vincent Gable's Blog &#187; NSTask</title>
	<atom:link href="http://vgable.com/blog/tag/nstask/feed/" rel="self" type="application/rss+xml" />
	<link>http://vgable.com/blog</link>
	<description>my weblog.</description>
	<lastBuildDate>Tue, 29 Nov 2011 22:20:23 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Restarting Your Mac OS X Cocoa Application</title>
		<link>http://vgable.com/blog/2008/10/05/restarting-your-cocoa-application/</link>
		<comments>http://vgable.com/blog/2008/10/05/restarting-your-cocoa-application/#comments</comments>
		<pubDate>Mon, 06 Oct 2008 00:35:09 +0000</pubDate>
		<dc:creator>Vincent Gable</dc:creator>
				<category><![CDATA[Bug Bite]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[MacOSX]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[UNIX]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[NSTask]]></category>
		<category><![CDATA[NSUserDefaults]]></category>

		<guid isPermaLink="false">http://vgable.com/blog/2008/10/05/restarting-your-cocoa-application/</guid>
		<description><![CDATA[Restarting your own application is a tricky thing to do, because you can&#8217;t tell yourself to start up when you aren&#8217;t running. Here is one solution, use NSTask to run a very short script that you can embed right in your Objective-C code: kill -9 YourPID open PathToYourApp Something to be aware of, kill -9 [...]]]></description>
			<content:encoded><![CDATA[<p>Restarting your own application is a tricky thing to do, because you can&#8217;t tell yourself to start up when you aren&#8217;t running.  Here is one solution, use <code><a href="http://vgable.com/blog/2008/03/05/calling-the-command-line-from-cocoa/">NSTask</a></code> to run a very short script that you can embed right in your Objective-C code:<br />
<code>kill -9 <em>YourPID</em><br />
open <em>PathToYourApp</em></code><br />
Something to be aware of, <code>kill -9</code> will immediately terminate your application, without going through the usual <code><a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSApplication_Class/Reference/Reference.html#//apple_ref/doc/uid/20000012-CACBFGDB">applicationWillTerminate:</a></code> business that happens when an application quits more gracefully.</p>
<p><code>- (void) restartOurselves<br />{<br />&nbsp;&nbsp;&nbsp;//$N = argv[N]<br />&nbsp;&nbsp;&nbsp;NSString *killArg1AndOpenArg2Script = @"kill -9 $1 \n open \"$2\"";<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;//NSTask needs its arguments to be strings<br />&nbsp;&nbsp;&nbsp;NSString *ourPID = [NSString stringWithFormat:@"%d",<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[[NSProcessInfo processInfo] processIdentifier]];<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;//this will be the path to the .app bundle,<br />&nbsp;&nbsp;&nbsp;//not the executable inside it; exactly what `open` wants<br />&nbsp;&nbsp;&nbsp;NSString * pathToUs = [[NSBundle mainBundle] bundlePath];<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;NSArray *shArgs = [NSArray arrayWithObjects:@"-c", // -c tells sh to execute the next argument, passing it the remaining arguments.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   killArg1AndOpenArg2Script,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   @"", //$0 path to script (ignored)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   ourPID, //$1 in restartScript<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   pathToUs, //$2 in the restartScript<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   nil];<br />&nbsp;&nbsp;&nbsp;NSTask *restartTask = [NSTask launchedTaskWithLaunchPath:@"/bin/sh" arguments:shArgs];<br />&nbsp;&nbsp;&nbsp;[restartTask waitUntilExit]; //wait for killArg1AndOpenArg2Script to finish<br />&nbsp;&nbsp;&nbsp;NSLog(@"*** ERROR: %@ should have been terminated, but we are still running", pathToUs);<br />&nbsp;&nbsp;&nbsp;assert(!"We should not be running!");<br />}<br /></code></p>
<p><strong>WARNING:</strong> don&#8217;t make the same mistake that I did and test <code>restartOurselves</code> without some kind of guard to keep your application from restarting forever.  It is <em>very</em> difficult to kill such a beast, because whenever it starts up it takes keyboard focus away from what you are doing&#8230;. well I&#8217;m sure you get <a href="http://www.youtube.com/watch?v=LD8HDta7Z_4">the idea</a>.</p>
<p><code>- (BOOL) weHaveRunBefore {<br />
&nbsp;&nbsp;&nbsp;NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];<br />
&nbsp;&nbsp;&nbsp;BOOL weHaveRunBefore = [prefs boolForKey:@"weHaveRunBefore"];<br />
&nbsp;&nbsp;&nbsp;[prefs setBool:YESs forKey:@"weHaveRunBefore"];<br />
&nbsp;&nbsp;&nbsp;[prefs synchronize];<br />
&nbsp;&nbsp;&nbsp;return weHaveRunBefore;<br />
}<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://vgable.com/blog/2008/10/05/restarting-your-cocoa-application/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Calling the Command Line from Cocoa</title>
		<link>http://vgable.com/blog/2008/03/05/calling-the-command-line-from-cocoa/</link>
		<comments>http://vgable.com/blog/2008/03/05/calling-the-command-line-from-cocoa/#comments</comments>
		<pubDate>Wed, 05 Mar 2008 23:21:16 +0000</pubDate>
		<dc:creator>Vincent Gable</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[MacOSX]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[UNIX]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Command-Line]]></category>
		<category><![CDATA[NSTask]]></category>
		<category><![CDATA[sh]]></category>

		<guid isPermaLink="false">http://vgable.com/blog/2008/03/05/calling-the-command-line-from-cocoa/</guid>
		<description><![CDATA[The best way to call a shell-command from Coca is by using an NSTask. Here are the three resources on using an NSTask that I found the most helpful: CocoDev&#8217;s write up A few quick exaples NSTask Class Refrence And here is some sample code to do it for you. You are free to use [...]]]></description>
			<content:encoded><![CDATA[<p>The best way to call a shell-command from Coca is by using an <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSTask_Class/Reference/Reference.html">NSTask</a>.  Here are the three resources on using an NSTask that I found the most helpful:<br />
<a href="http://www.cocoadev.com/index.pl?NSTask">CocoDev&#8217;s write up</a><br />
<a href="http://www.borkware.com/quickies/one?topic=NSTask">A few quick exaples</a><br />
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSTask_Class/Reference/Reference.html">NSTask Class Refrence</a></p>
<p><a href="http://www.vgable.com/code/ShellTask.zip">And here is some sample code to do it for you.</a>  You are free to use this code however you please, but attribution is always appreciated.  The two principle functions are:</p>
<p><code>+ (NSString*) executeShellCommandSynchronously:(NSString*)command</code> executes the command &#8220;command&#8221; with <a href="http://en.wikipedia.org/wiki/Bourne_shell">sh</a>, wait until it finishes, and return whatever it printed to stdout and stderr as an NSString.<br />
CAUTION: may deadlock under some circumstances if the output gets so big it fills the pipe.  See <a href="http://dev.notoptimal.net/search/label/NSTask"> http://dev.notoptimal.net/search/label/NSTask</a> for an overview of the problem, and a solution.  I have not experienced the problem myself, so I can&#8217;t comment.</p>
<p><code>executeShellCommandAsynchronously:</code> will have <a href="http://en.wikipedia.org/wiki/Bourne_shell">sh</a> execute <code>command</code> in the background, without blocking anything.</p>
<p>For quick hacks, the POSIX <a href="http://www.hmug.org/man/3/system.php"><code>int system(const char* command)</code></a> function, might be a good one-line solution.  It synchronously evaluates <code>command</code> with <a href="http://en.wikipedia.org/wiki/Bourne_shell">sh</a>.</p>
<p>Enjoy!</p>
<p>EDITED 2009-11-29: this code probably <em>won&#8217;t</em> have the same <code>$PATH</code> you would get if you used Terminal. See <a href="http://stackoverflow.com/questions/386783/nstask-not-picking-up-the-expected-path-from-the-users-environment/1817870#1817870">this question on stackoverflow</a> for more details. A solution that seems to work is to do,</p>
<pre>
    [task setLaunchPath:@"/bin/bash"];
    NSArray	*args = [NSArray arrayWithObjects:@"-l",
    				 @"-c",
    				 <strong>commandlineHere</strong>,
    				 nil];
    [task setArguments: args];
</pre>
<p>This launches <code>bash</code> (<em>not</em> in <code>sh</code> compatibility mode), and -l (lowercase L) tells it to  &#8220;act as if it had been invoked as a login shell&#8221;. I haven&#8217;t tested this on systems where <code>bash</code> isn&#8217;t the default shell. There are lots of ways <code>$PATH</code> could be set, and I haven&#8217;t tested them all. But you are almost certainly going to be OK if everything you refer to is in <code>/usr/bin:/bin:/usr/sbin:/sbin</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://vgable.com/blog/2008/03/05/calling-the-command-line-from-cocoa/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>

