# Make StdC++ Console App Droppable?



## vettezuki (Oct 18, 2005)

New to Mac/OSX programming.

In Windows when dropping a file (of which there are no restrictions) on a conole app, it is the equivalent of calling the application's main function with argv[1] as the full path to the file that was dropped on the app.  This is pretty convenient.

I've managed to write a console app in CW that I can explicitly call from the terminal, like so:
$myapp <path_to_input_file>

It works fine (though it opens a separate terminal window for cerr output that does not return control to the calling terminal; I have to command+break to close, but that's a separate question).

However, apparently I have to define a value somewhere (.plc file in CW?) that describes what files are droppable onto the application???  

Any help, much obliged.


----------



## Viro (Oct 19, 2005)

I do not understand how this is supposed to work. If you drag a file to the console, how is it to know what application to call? 

As it is, if you drag a file to the Terminal.app, the entire path is copied. Thus, if you have typed $my_app in the terminal, dragging the file you want will cause the path to be placed in the terminal, resulting in $my_app <path_to_file>, which is as far as I can see what you want.

Maybe I'm understanding your question wrong as I've never worked with CodeWarrior.


----------



## vettezuki (Oct 19, 2005)

Viro said:
			
		

> I do not understand how this is supposed to work. If you drag a file to the console, how is it to know what application to call?



Certainly it does not, that's not what I meant.




			
				Viro said:
			
		

> As it is, if you drag a file to the Terminal.app, the entire path is copied. Thus, if you have typed $my_app in the terminal, dragging the file you want will cause the path to be placed in the terminal, resulting in $my_app <path_to_file>, which is as far as I can see what you want.
> 
> Maybe I'm understanding your question wrong as I've never worked with CodeWarrior.



Same for Windows and Unix.  This does work fine.  However, in Windows, you can drop anyfile onto a CONSOLE APP and it will call that appp and pass the path to the file that was dropped on it as argv[1].  

I would like to do this in OSX.


----------



## kainjow (Oct 19, 2005)

I don't think it's possible with standard Mac console apps. You need to bundle it into a .app and implement specific functions for accepting a dropped file in Carbon or Cocoa.

What you can do is use an AppleScript to allow someone to drop a file onto the AppleScript, and then have the AppleScript launch the console app. I wrote up a small little script to do this for you. Just open it in Script Editor and Save As an Application so it can be used.


----------



## Viro (Oct 19, 2005)

I honestly do not understand what the OP is describing. Do you mean to say that on Windows, if I drag any file to the command prompt (which is saying something like c:\ with no launched application), it will automatically load up a program (what program?) and pass the path to the file as the first command line argument?

Or do you mean that if you have an application running on the command line, and you drag a file to it, it automatically .... relaunches the application, passing the path to the argv variable?

Neither of these seems plausible and I work on Mac OS X and Linux almost 8 hours every day.


----------



## kainjow (Oct 19, 2005)

I think what he wants is to be able to drop a file onto a Mac executable and have the executable launch with the path as an argument to the program. He mentions you can do this on Windows, but as I said you can't really do it with a normal Mac console program. You have to do it as Carbon/Cocoa or an AppleScript workaround like I posted.


----------



## vettezuki (Oct 19, 2005)

kainjow said:
			
		

> I think what he wants is to be able to drop a file onto a Mac executable and have the executable launch with the path as an argument to the program. He mentions you can do this on Windows, but as I said you can't really do it with a normal Mac console program. You have to do it as Carbon/Cocoa or an AppleScript workaround like I posted.




You are correct kainjow.  Thank you for your time and help.  I'll check out the script this afternoon.  Something like this is what expected to have to do.  Hopefully I'll be able to "package" the end result in such a way that it appears to be a single file to the end user, but one step at a time    I'll report later on.


----------



## vettezuki (Oct 19, 2005)

kainjow said:
			
		

> I don't think it's possible with standard Mac console apps. You need to bundle it into a .app and implement specific functions for accepting a dropped file in Carbon or Cocoa.
> 
> What you can do is use an AppleScript to allow someone to drop a file onto the AppleScript, and then have the AppleScript launch the console app. I wrote up a small little script to do this for you. Just open it in Script Editor and Save As an Application so it can be used.




Gosh darn it.  I'm registered and logged in, but seem to be prevented from downloading this file.  When I click on it, it asks me to log in (though I am logged in) and informs I may not have access privelages.  What gives?


----------



## kainjow (Oct 19, 2005)

Hm, not sure why you can't download it.

But if you're wanting to make a program that is all neatly packaged up, the easiet way is to make an AppleScript Droplet application in Xcode (File > New Project). It sets up the code for you, and you can then drag and drop the code in from the file above. I've attached an example script/application that when run will display the contents of a file dropped onto it. All you'd have to change is the path of the console app to run, which can be embedded directly into the .app (not sure how to access it from AppleScript though - I'm sure not hard).


----------



## vettezuki (Oct 19, 2005)

kainjow said:
			
		

> Hm, not sure why you can't download it.
> 
> But if you're wanting to make a program that is all neatly packaged up, the easiet way is to make an AppleScript Droplet application in Xcode (File > New Project). It sets up the code for you, and you can then drag and drop the code in from the file above. I've attached an example script/application that when run will display the contents of a file dropped onto it. All you'd have to change is the path of the console app to run, which can be embedded directly into the .app (not sure how to access it from AppleScript though - I'm sure not hard).



Okay, making some good progress here.  I was able to download your code, create a new Applescript Droplet in xcode (first time with XCode), move your code into new project and modify "Application.applescript" to call "myapp" intead of "cat".  This works:

Now, if I embed the source of myapp into the XCode Applescript Droplet project, how do I call main()?  Also, I'm not clear what your main() is doing:

extern void ASKInitialize();
extern int NSApplicationMain(int argc, const char *argv[]);

int main(int argc, const char *argv[])
{
    ASKInitialize();

    return NSApplicationMain(argc, argv);
}


----------



## kainjow (Oct 19, 2005)

I don't know either 

That was setup by default by Xcode when I went to File > New Project > AppleScript Droplet. I'd leave it be if I were you


----------



## kainjow (Oct 19, 2005)

Ok I found out how to get the path of a file in your bundle's resource folder.

What you need to do is add to this project the compiled command line executable as a resource. Compile the project, and make sure it gets copied into the /Contents/Resources folder of your .app. Once you have this setup, you can use this code to get the path of your file in the resources folder:

```
set execPath to the main bundle's resource path & "/myapp"
```
And then use this instead of the hardcoded path.


----------



## vettezuki (Oct 19, 2005)

kainjow said:
			
		

> Ok I found out how to get the path of a file in your bundle's resource folder.
> 
> What you need to do is add to this project the compiled command line executable as a resource. Compile the project, and make sure it gets copied into the /Contents/Resources folder of your .app.



I don't have this dir.  I do have an English.lproj folder at the root of the project folder.  This seems to be the location of the files corresponding to "Resources."  I copied the compiled executable to this dir and added it to the project. It does show up under Targets/My First Droplet/Bundle Resources.



			
				kainjow said:
			
		

> Once you have this setup, you can use this code to get the path of your file in the resources folder:
> 
> ```
> set execPath to the main bundle's resource path & "/myapp"
> ...



This is where I'm a little confused.  Does this go in Application.applescript? Like so:


```
set execPath to the main bundle's resource path & "/exsp"
set exec to "exsp " & quoted form of POSIX path of names
set result to do shell script exec
```

NOTE: "exsp" is the real name of my console app.


----------



## kainjow (Oct 19, 2005)

Hmm when you control/right click on DropletApp.app in your build directory, you should see a Contents folder, then inside a Resources folder, MacOS folder, PkgInfo, and Info.plist. When you add your exsp to your project *under the Resources group*, the next time you compile it should be copied into the Resources directory.

With this project, all your code should be AppleScript and be inside the .applescript file in the project.


----------



## vettezuki (Oct 19, 2005)

kainjow said:
			
		

> Hmm when you control/right click on DropletApp.app in your build directory, you should see a Contents folder, then inside a Resources folder, MacOS folder, PkgInfo, and Info.plist. When you add your exsp to your project *under the Resources group*, the next time you compile it should be copied into the Resources directory.
> 
> With this project, all your code should be AppleScript and be inside the .applescript file in the project.




Ok, Ctl+Right Click didn't do it so I figured display package contents was the correct choice and it seems to be:

So my executable is in 

Contents/Resources/English.lproj

I didn't put it there myself, so it must have been placed there during the Build process.  Everything basically makes sense; however, the Droplet does not find exsp.

The following is the relevent block (I think) of the Applescript:


```
on open names
	set execPath to the main bundle's resource path & "/exsp"
	set exec to "exsp " & quoted form of POSIX path of names
	set result to do shell script exec
	display dialog result
	(*
	tell application "Terminal"
		do shell script exec
	end tell
	*)
	
	-- Remove the following line if you want the application to stay open.
	quit
end open
```


The Error Dialog says

AppleScript Error
sh: line 1: exsp: command not found (127)


Mmmm, exsp is in the aforementioned folder.


----------



## kainjow (Oct 19, 2005)

/Contents/Resources/English.lproj is not what we're interested in.

The code above is looking for "exsp" inside /Contents/Resources (i.e. the path relative to the bundle should be /Contents/Resources/exsp). Does this path exist?

You need to update your code also to use the full path of exsp:


```
set execPath to the main bundle's resource path & "/exsp"
set exec to execPath & " " & quoted form of POSIX path of names
```


----------



## vettezuki (Oct 19, 2005)

Almost got it. Only change to what you had to make it necessarry to run was:


```
set execPath to the main bundle's resource path & "/exsp"
set exec to quoted form of execPath & " " & quoted form of POSIX path of names
set result to do shell script exec
```

It now calls exsp with the dropped file.  Yeah.

This is kind of a separate question but related to my project.  My console app uses cerr (stderr) for diagnostic output.  When executing exsp OSX opens an output window and displays the correct information.  However, though my application is returning from main(), I have to control break to kill the exsp process. . . Any idea?  Maybe I should start a new thread for this question.  

Many thanks for your help.


----------



## kainjow (Oct 19, 2005)

What output window are you referring to? Is it in Terminal?


----------



## vettezuki (Oct 19, 2005)

kainjow said:
			
		

> What output window are you referring to? Is it in Terminal?



The terminal process opens a separate "output" window.  So, if you were to use this in a standard unix way:

$./myapp args

instead of displaying stderr output from myapp to the terminal window from which myapp was called, OSX opens another output window, which correctly displays the myapp stderr output, but does not return control to the calling terminal, even though myapp has apparently exited main().  I tested this by commenting out all the cerr lines, and it runs perfectly, exiting completely.    With the cerr lines, myapp is hogging the majority of the cpu, and must be manually terminated.


----------



## kainjow (Oct 19, 2005)

I found this page which might help you.. it suggests to use file redirection to output the output to a file: http://bbs.applescript.net/viewtopic.php?pid=42439


----------



## vettezuki (Oct 19, 2005)

kainjow said:
			
		

> I found this page which might help you.. it suggests to use file redirection to output the output to a file: http://bbs.applescript.net/viewtopic.php?pid=42439



My problem isn't getting, capturing or redirecting output from the terminal, but that the system somehow gets hung up when using cerr for output from my console app to the terminal window. 

Actually, it's not a problem, I'll just bypass cerr altogether.  So all I need to do is capture the integer return from myapp's main(), and use a switch block type construction in the the script to display a dialog about what happened, or didn't as the case may be.

Peace out.


----------

