NSWorkspace notification - application close [duplicate] - cocoa

My requirement is to open a file like pdf/ppt etc and close it after 20 minutes. I am able to open the files appropriately thanks to NSWorkspace. But how can I close the files ?. NSWorkspace does not seem to have a close method.

NSWorkspace just asks the operating system to open the file, it doesn't maintain any connection to the file at all. The OS will open the file with whatever the default application is for that file type, unless you specify a particular application to use. Anything that happens with the file after that point is completely outside of your application's control because the file is being managed by another process.
You would need to use either AppleScript/Apple Events or the Accessibility Framework to control whatever application currently has the file open and ask it to close the file, but there is no guarantee that it will do so.
The only way to guarantee that you will be able to close the file is to open it in your app. Obviously, this is impossible if you need to open a variety of diverse and possibly proprietary file types.

Related

Windows: tell app to open file

On Windows, how do I get my app to tell another app to open a file that I just generated. For example, "WordPad, please open 'foo.rtf' that I just made." Or Word, or other big apps that may already be open with other files. I have to assume that the app may or may not be open already.
Alternatively, if I could only do the equivalent of double-clicking the file, so as to open it with its default application, that would still be all right.
Depends on how your application handles opening other files.
One would think that assuming filetype associations are configured properly in Windows, it should know what application to open .rtf files with (per your example).
In powershell, you could use gc if you're only looking at plaintext data.
http://www.ats.ucla.edu/stat/mult_pkg/faq/general/powershell_examples.htm
In Python, you would handle the file as an object, per the example here:
https://docs.python.org/2/tutorial/inputoutput.html#reading-and-writing-files
But if you wanted to launch a specific secondary application to open the file, you might try running an outside program (executable) in python?

How can I associate a file with my app?

I have a Cocoa app "PDFHistory" on Mac OS X that uses the NSDocument architecture to save and load PDF files that are internally formatted specially for my app. I want to make it so whenever I save a file (e.g., "mydoc.pdf") from PDFHistory, then subsequently double-clicking on mydoc.pdf will automatically open it in PDFHistory.app. However, I don't want to make it so all .pdf files are automatically opened in PDFHistory, but rather use the system default (probably Preview.app). The .pdf suffix is a requirement, though, since I need the user to be able to e-mail the files to other users who can view the file in their default PDF viewer.
The problem is that if I set the LSHandlerRank to "Owner", then all .pdf files will be opened with PDFHistory, which is bad (since I only understand the internals of the .pdf file that PDFHistory wrote out). But if I set LSHandlerRank to "Alternate", then all .pdf files will be opened to the system default app (Preview.app), which is confusing for the user who had just created the file using my app.
Once upon a time, "creator codes" could be used to implement this sort of capability, but launch services started ignoring them back in Snow Leopard (see http://tidbits.com/article/10537). UTIs are not a substitute that provide this capability (see http://boredzo.org/blog/archives/2009-09-22/how-not-to-use-utis).
Using Finder to get info on the file allows the user to specify a specific app to use to open the specific file. This supposedly works by setting a "usro" property in a the file's resource. There is some open-source code to mimic this behavior (https://github.com/AlanQuatermain/SetAppAffinity), but is uses deprecated functions, and so would cause Apple to reject the app from the App Store. Similarly, people have posted AppleScript to set this property (https://discussions.apple.com/thread/2597365), but sandboxing would prevent me from invoking it.
Although the .pdf suffix is a requirement in order to be able to send the files to users on other systems/platforms, I considered trying to have the suffix registered with two extensions as ".phistory.pdf", which would allow "file.phistory.pdf" to be opened in PDFHistory, but "file.pdf" would be opened in the default PDF viewer. However, this simply didn't work: it appears that the final suffix is the only one used by launch services, and everything before that is ignored.
So is there any way to have my app be the default app for opening files that it created itself?

Windows API hook, custom save as file dialog to save directly to webserver via POST

I want to write a custom save as dialog that is hooked into the File -> "Save As" of most Windows program. This custom dialog will allow the user to enter their username, password, destination folder and uploads the file to the web server via a POST. If the user clicks cancel, it will call the original file dialog.
I've been reading up about Windows API hooking and this is vaguely how I think I would approach this:
Intercept "Save As"
Display my custom dialog, return some temporary path on the drive
Let the program write file to the temporary path, assume it calls WINAPI CreateFile(...) for now
Read the temporary file and upload to web server
Clean up temporary file
But I still can't get my head around the steps required to pull this off. Assuming I can intercept the "Save As" and CreateFile function, how do I detect the CreateFile was called from a "Save As" and not just any random file creation? I can think of a hack where I keep track of the time difference of when the File dialog got open and CreateFile got called.
My alternative solution is to use the existing file dialog and create a special folder on the disk, that is constantly monitored. When a file gets written there it will call an external program that uploads the file. I haven't looked into how to do this yet. I suspect this is easier.
UPDATE
As a first baby step, I wrote a .NET task tray application that allows the user to enter their login details and a folder to monitor. Whenever a file gets dropped in there there it will upload to the web server. So far it seems to work. Now I just need to figure out how to add a nice shortcut to the left pane of the file dialog. Once that's done I think I got a solution I'm happy with.
There is no need to hook or patch anything. Create a shell namespace extension that supports IStorage::CreateStream and implements it by returning a stream that POSTs its data to the Web server. The user can then choose to save the file to your namespace extension in order to upload the file.
Hooking the standard save dialog requires you to inject a DLL into every running process and have it replace the import stub of the the Win32 API GetSaveFileName() function in the process's PE header (something anti-virus and anti-malware apps are not likely to be happy about).
Then there is the new-style save dialog that was introduced in Vista using the new IFileSaveDialog COM interface instead of GetSaveFileName(). For that, you would have to uninstall and replace Microsoft's default FileDialog COM object with a custom implementation.
That does not count custom-made save dialogs, which you are not likely to hook.
If, by some miracle, you can hook the dialog and have it return a custom path of your own creation, you don't need to hook CreateFile() itself, Just monitor the folder that you create for your purposes. Place it where it is unlikely that any other app (or user) besides you will write files to. You can create a custom subfolder in the user's or system'ss AppData folder for that purpose. You can use SHGetSpecialFolderPath() and/or SHGetKnownFolderPath() to find those folders.
The tricky part will be detecting when the file is finished being written to and has been closed. You will have to monitor the folder for changes, such as with ReadDirectoryChangesW() or SHChangeNotifyRegister(), and periodically open new/modified files for exclusive access. If a file is still open by someone else, you won't be able to open it yourself. But once you do open it, you can do whatever you want with it.

Redirect default program to another program when a file opens in Windows OS

This is only under windows env.
As I know windows os identifies associated application of a particular file by file extension.
Like wise each file (binary) starting with corresponding symbols ("starting symbols"). For an example .JPG starts with ÿØÿà. Let say I open this .JPG file in a Hex editor or a Text editor and then I change that starting symbols into another file type. for an example I can change ÿØÿà to .Eߣ (.mkv). So when I double click on the .JPG the Windows Photo Viewer says there are some errors or similar message. So I need to get some information about the application that tries to open that kind of a file. If I can, I need to open that file using the application that associated with "starting symbols".
Briefly when I open .JPG I need to open a default video player .mkv files. But It may not work for this example. Because I changed only the "starting symbols" of my .JPG.
Please give me any idea to do this.
Thanks!
When you encrypt the file, give it a new extension. e.g. Picture.jpg becomes Picture.encrypted-jpg. You then register as the handler for encrypted-jpg, decrypt the file, then launch the normal jpg handler.
When the shell is asked to perform a verb on a file, the shell does not use the contents of the file to determine which app to pass it to. The file extension is what determines how the file will be treated.
You wish to use the contents of the file to influence which app processes a shell verb. In order to do so you would need to create a launcher app that reads the file header and then decides which app to pass the file on to. You would assign your launcher app as the handler app for all file extensions that you were interested in.
Although you could do this, it would be much easier just to set the file extension appropriately.
The proper way to do this sort of thing is to replace the files with reparse points.
The downside is that this involves writing a file system filter driver, i.e., an operating system extension, which is a whole level of trouble above and beyond ordinary application programming. (Since Windows already does file encryption, I doubt it would be worth the effort.)

Preferred path to applications on OSX?

I want to be able to run a text editor from my app, as given by the user in the TEXT_EDITOR environment variable. Now, assuming there is nothing in that variable, I want to default to the TextEdit program that ships with OSX. Is it kosher to hardcode /Applications/TextEdit.app/Contents/MacOS/TextEdit into my app, or is there a better way to call the program?
Edit: For the record, I am limited to running a specific application path, in C. I'm not opening a path to a text file.
Edit 2: Seriously people, I'm not opening a file here. I'm asking about an application path for a reason.
In your second edit it makes it sound like you just want to get the path to TextEdit, this can be done easily by using NSWorkspace method absolutePathForAppBundleWithIdentifier:
NSString *path = [[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:#"com.apple.TextEdit"];
Mac OS X has a mechanism called "uniform type identifiers" that it uses to track associations between data types and applications that can handle them. The subsystem that manages this is Launch Services. You can do one of two things:
If you have a file with a reasonably well-known path extension, e.g. .txt, you can just ask NSWorkspace to open the file in the appropriate application.
If you don't have a well-known path extension, but you know the type of data, you can ask Launch Services to look up the default application for that type, and then ask NSWorkspace to open the file in that specific application.
If you do it this way you'll get the same behavior as the Finder, and you won't have to fork()/exec() or use system() just to open a file.
I believe hardcoding "Applications" will not work if the user's language setting is not English. For example in Norsk the "Applications" folder is named "Programmer".
The Apple document on internationalization is here. Starting on page 45 is a section on handling localized path names.
I believe that Mac OS X provides a default application mechanism, so that .txt will open in TextEdit.app or Emacs or GVim or whatever the user has specified. I couldn't find anything online however.
You could run following command from your application:
open <full path to text file>
This will open the text file in the default text editor. You can open any file type using open command.

Resources