是否可以以编程方式更改Mac OS X上已安装驱动器上的音量图标?

时间:2012-02-10 09:51:09

标签: objective-c macos macfuse

我想以编程方式更改使用OSXFUSE(以前称为MacFUSE)实现的堆叠文件系统的音量图标。该图标需要反映已安装文件系统的状态。

我一直在尝试的方法是将/.VolumeIcon.icns的请求映射到应用程序包中的相应图标。然后将更改通知发送到文件系统,以获取实际路径(路径)和装载路径(mountPath)。

    [[NSWorkspace sharedWorkspace] noteFileSystemChanged: @"/Volumes"]; 
    [[NSWorkspace sharedWorkspace] noteFileSystemChanged: [mountPath stringByDeletingLastPathComponent]];
    [[NSWorkspace sharedWorkspace] noteFileSystemChanged: mountPath];
    [[NSWorkspace sharedWorkspace] noteFileSystemChanged: [path stringByDeletingLastPathComponent]];
    [[NSWorkspace sharedWorkspace] noteFileSystemChanged: path];

    FNNotifyByPath([[[mountPath stringByDeletingLastPathComponent] dataUsingEncoding:NSUTF8StringEncoding] bytes], kFNDirectoryModifiedMessage, kNilOptions);
    FNNotifyByPath([[[path stringByDeletingLastPathComponent] dataUsingEncoding:NSUTF8StringEncoding] bytes], kFNDirectoryModifiedMessage, kNilOptions);
    FNNotifyByPath([[@"/Volumes" dataUsingEncoding:NSUTF8StringEncoding] bytes], kFNDirectoryModifiedMessage, kNilOptions);

单步调试我可以看到这个代码被点击但是映射/.VolumeIcon.icns的代码很少被调用,而且从不响应这些通知。

2 个答案:

答案 0 :(得分:3)

我认为简短的回答是,你运气不好。很长的答案是,虽然OSXFUSE项目与Fuse4X项目不同,但它们都来自相同的来源,而Fuse4X在其常见问题解答中有关于音量图标的说法:

  

问题4.1。为什么Fuse4X卷显示“服务器”(或“网络”)   卷“)图标?

     

答:确切地说,默认情况下,Fuse4X卷显示为非本地   不幸的是,Finder将其视为“服务器”。   这是一个很好的问题,为什么Fuse4X通常将其卷标记为   外地。有些人认为在基于磁盘的文件的情况下   系统,Fuse4X必须将音量标记为本地。好吧,让我们看看。

     

对于在Mac OS X上本地的vfs,您需要一个“真正的”磁盘设备 - a   / dev / disk *样式节点。在Fuse4X的情况下,这样一个真正的磁盘设备节点   有问题:在挂载时,对于本地卷,内核会   本身打开设备节点并将其传递给Fuse4X。这样做,   内核将确保该设备当前未被使用(for   一,禁止多个相同设备的安装)。有时候是这样的   在控制传递到Fuse4X之前,可以继续安装。这个会   如果整个文件系统都存在于内核中,那就没问题了   Fuse4X的情况下,用户空间文件系统程序也想要   (专门)打开磁盘设备。

答案 1 :(得分:1)

看看path finder source code

- (BOOL)setAsCustomIconForVolume:(NString *)path;
{
    FSref FSRefpath = convertoFsref(path);
    // filename for custom icon is ".VolumeIcon.icns"
    NSString *iconPath = [path stringByAppendingPathComponent:@".VolumeIcon.icns"];

    // remove any existing file first.

    [self writeToFile:iconPath];
    FSSetHasCustomIcon(FSRefpath);

    // rebuild volumeList


    return YES;
}
OSErr FSSetHasCustomIcon(
                   const FSRef *ref)
{
    return ( FSChangeFinderFlags(ref, true, kHasCustomIcon) );
}
OSErr FSChangeFinderFlags(
                    const FSRef *ref,
                    Boolean setBits,
                    UInt16 flagBits)
{
    OSErr           result;
    FSCatalogInfo   catalogInfo;
    FSRef           parentRef;

    /* get the current finderInfo */
    result = FSGetCatalogInfo(ref, kFSCatInfoFinderInfo, &catalogInfo, NULL, NULL, &parentRef);
    require_noerr(result, FSGetCatalogInfo);

    /* set or clear the appropriate bits in the finderInfo.finderFlags */
    if ( setBits )
    {
        /* OR in the bits */
        ((FileInfo *)&catalogInfo.finderInfo)->finderFlags |= flagBits;
    }
    else
    {
        /* AND out the bits */
        ((FileInfo *)&catalogInfo.finderInfo)->finderFlags &= ~flagBits;
    }

    /* save the modified finderInfo */
    result = FSSetCatalogInfo(ref, kFSCatInfoFinderInfo, &catalogInfo);
    require_noerr(result, FSSetCatalogInfo);

FSSetCatalogInfo:
FSGetCatalogInfo:

        return ( result );
}  

NTVolumeNotificationMgr
NTIconFamily