简体   繁体   English

在Finder窗口OSX中打开文件

[英]Open file in Finder window OSX

My question is about opening a Finder window to show the file. 我的问题是打开Finder窗口来显示文件。

To open a single file, able to do by this : 要打开一个文件,可以这样做:

[[NSWorkspace sharedWorkspace] selectFile:file.path 
                 inFileViewerRootedAtPath:file.path];

Now I need to have a single Finder if user tries to open the same file.path . 现在,如果用户试图打开相同的file.path我需要一个Finder。

To achieve this, I add file.path in an array. 为此,我在数组中添加了file.path

But I am stuck when user closes the Finder window and again tries to open the file (as the active window has THE array with the path). 但是当用户关闭Finder窗口并再次尝试打开文件时,我陷入困境(因为活动窗口具有带路径的数组)。 Then Finder doesn't show :( 然后Finder没有显示:(

Any help how to proceed on this. 任何帮助如何继续这一点。


  1. Is there a way to check the path for which the Finder window is open? 有没有办法检查Finder窗口打开的路径?

  2. Is there a way to get a callback for the finder, so that I can remove the file.path from the array? 有没有办法获取finder的回调,以便我可以从数组中删除file.path

It is done by simply passing nil . 这是通过简单地传递nil来完成的。

[[NSWorkspace sharedWorkspace] selectFile:file.path inFileViewerRootedAtPath:nil];

Now same file / folder is selected even on multiple clicks. 现在,即使多次点击,也会选择相同的文件/文件夹。

My first choice would be creating finder like window in my application and open files in it, that would give you full control of your actions. 我的第一选择是在我的应用程序中创建像窗口一样的查找器,并在其中打开文件,这将使您完全控制您的操作。

Second option could be creating scriptable cocoa app. 第二个选项可能是创建脚本化的可可应用程序。 That could provide functionality what you describe in your question also it is compatible with sandboxing. 这可以提供您在问题中描述的功能,也可以与沙盒兼容。 From Apple: Gatekeeper and Signing Applets . 来自Apple: Gatekeeper和Signing Applets

Summary from the link above. 上面的链接摘要。

Gatekeeper and Signing Applets OS X Mountain Lion includes Gatekeeper, which protects users from malicious software by applying a policy about what downloaded software is allowed to run. Gatekeeper和签名小程序OS X Mountain Lion包括Gatekeeper,它通过应用允许运行下载软件的策略来保护用户免受恶意软件的攻击。 Gatekeeper relies on code signing to verify applications: a signed application is guaranteed to have been created by the signer and to have not been modified since it was signed. Gatekeeper依赖于代码签名来验证应用程序:签名的应用程序保证由签名者创建,并且自签名以来未被修改。 By default, Gatekeeper will allow running only applications that have been signed by the Mac App Store or an identified developer. 默认情况下,Gatekeeper将仅允许运行已由Mac App Store或已识别的开发人员签名的应用程序。 If you write script applications (“applets”) for distribution, then this policy applies to your applets. 如果您编写用于分发的脚本应用程序(“applet”),则此策略将应用于您的applet。 To sign your applets so Gatekeeper's default policy will not block them: 要签署您的applet,以便Gatekeeper的默认策略不会阻止它们:

What we need: 我们需要的:

  1. Create *.sdef file, which defines your application's scriptability information. 创建* .sdef文件,该文件定义应用程序的脚本信息。 Scriptability Information 可编写性信息
  2. Adding Cocoa scripting support to your app Cocoa Support for Scriptable Applications 将Cocoa脚本支持添加到您的应用程序Cocoa支持可编写脚本的应用程序
  3. Create Applescript to get open "named" Finder windows and send back information to your Cocoa app or vice versa. 创建Applescript以打开“命名”Finder窗口并将信息发送回您的Cocoa应用程序,反之亦然。
  4. Invoke Applescript from your app or vice versa. 从您的应用程序调用Applescript,反之亦然。

You need to create *.sdef file, which is an XML-based format that describes a set of scriptability terms and the commands, classes, constants, and other information that describe the application's scriptability. 您需要创建* .sdef文件,这是一种基于XML的格式,它描述了一组脚本性术语以及描述应用程序可编写脚本性的命令,类,常量和其他信息。 You need to add this file into your project. 您需要将此文件添加到项目中。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">
<dictionary title="YOUR_APP_NAME">
    <suite name="scriptTest Suite" code="MApN" description="YOUR_APP_NAME Scripts">
        <command name="myFirstCommand" code="lkpstrng" description="The array to lookup">
            <cocoa class="MyLookupCommand"/> 
            <direct-parameter description="The array to lookup">
                <type type="any" list="yes"/>
            </direct-parameter>
            <result description="returns and array" type="text"/>
        </command>
    </suite>
</dictionary>

After included the *.sdef file into your project you need to add two new keys to info.plist. 将* .sdef文件包含到项目中后,您需要向info.plist添加两个新密钥。 Scriptable = YES and Scripting definition filename. Scriptable = YES和脚本定义文件名。

在此输入图像描述

In scripting definition file cocoa class defined as MyLookupCommand , we need to create this class in Cocoa app. 在定义为MyLookupCommand脚本定义文件cocoa class ,我们需要在Cocoa应用程序中创建此类。 MyLookupCommand class it is subclass of NSScriptCommand MyLookupCommand类它是NSScriptCommand子类

.h 。H

#import <Foundation/Foundation.h>
@interface MyLookupCommand : NSScriptCommand
@end

.m .M

#import "MyLookupCommand.h"

@implementation MyLookupCommand

-(id)performDefaultImplementation {

    // get the arguments
    NSDictionary *args = [self evaluatedArguments];
    NSString *stringToSearch = @"";
    if(args.count)
    {
        stringToSearch = [args valueForKey:@""];
    }
    else
    {
        //  error
        [self setScriptErrorNumber:-50];
        [self setScriptErrorString:@"Parameter Error......."];
    }
    // Implement your code logic
    [[NSNotificationCenter defaultCenter] postNotificationName:@"AppShouldLookupStringNotification" object:stringToSearch];

    return [NSString stringWithFormat:@"result: %@", [NSDate date]];
}
@end

And this is how you capture communication from Applescript. 这就是你从Applescript捕获通信的方式。

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    [textbox1 setStringValue:[NSString stringWithFormat:@"%05d", 1]];
    [[NSNotificationCenter defaultCenter]
     addObserver:self
     selector:@selector(getValueFromScript:)
     name:@"AppShouldLookupStringNotification"
     object:nil];
}

-(void)getValueFromScript:(NSNotification *)notification
{
    [yourTextbox setStringValue:[NSString stringWithFormat:@"from notification center %@", notification.object]];
}

Next step, we need a Applescript to get/set command from/to a Cocoa app. 下一步,我们需要一个Applescript来获取/设置来自/到Cocoa应用程序的命令。

//In SDEF file we declared return type as array, here we created one.
set groceryList to {"eggs", "milk", "bread"} //the variable which you want to send to your app.

//Scripting language is pretty straight forward. If "named" window exists invoke the command and send return type to your Cocoa app.
tell application "Finder"
    activate
    if ((count of windows) > 0) then
        if name of front window is "YOUR_DESIRED_FINDER_WINDOW_NAME" then

            tell application "System Events"
                set running_apps to every application process's name
                if running_apps does not contain "YOUR_COCOA_APP_NAME" then
                    tell application "AppleScript Editor" to activate
                end if
            end tell

            tell application "AppleScript Editor"
                if it is running then
                    tell application "AppleScript Editor"
                        myFirstCommand groceryList //Updated this line. 
                    end tell
                end if
            end tell

        end if
    end if
end tell

Of course you need to call Applescript applet from your Cocoa app as well. 当然,您还需要从Cocoa应用程序调用Applescript applet。 Please have a look at How to call Applescript from cocoa App - regulus6633's answer 请看一下如何从cocoa App调用Applescript - regulus6633的答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM