Error with [pluginBundle infoDictionary]

  • My app searches through its PlugIns folder to load Bundles.

    My basic code looks like:

    - (void)loadPlugins

    // some stuff removed

    NSString  *appSupportSubpath = @"Application Support/MyApp/PlugIns";

    libraryPaths = NSSearchPathForDirectoriesInDomains (NSLibraryDirectory,
    NSAllDomainsMask - NSSystemDomainMask, YES);

    libraryPathsEnum = [libraryPaths objectEnumerator];
    while (currPath = [libraryPathsEnum nextObject])
    {
      [bundlePaths addObject:[currPath
    stringByAppendingPathComponent:appSupportSubpath]];
    }

    bundlePathsEnum = [bundlePaths objectEnumerator];
    while (folderPath = [bundlePathsEnum nextObject])
    {
      NSEnumerator*    enumerator = [[NSBundle
    pathsForResourcesOfType:@"plugin" inDirectory:folderPath] objectEnumerator];
        NSString*        pluginPath;

        while ((pluginPath = [enumerator nextObject]))
        {
            [self activatePlugin:pluginPath];
        }
    }

    - (void)activatePlugin:(NSString*)path
    {
        NSBundle* pluginBundle = [NSBundle bundleWithPath:path];
        if (pluginBundle)
        {
            NSDictionary*    pluginDict = [pluginBundle infoDictionary];

    When I get here, pluginDict  normally has 17 keys, 13 of which are from the
    Info.plist, but if I copy a new Plugin to the proper folder and rerun
    loadPlugins, the new one I added ends up with only 4 keys as follows:

    type = mutable, count = 4, capacity = 4, pairs = (
    {contents = "NSBundleResolvedPath"} =
    /Users/trygve/Library/Application Support/pzizz/PlugIns/MyPlugin.plugin

    {contents = "NSBundleResourcePath"} =
    /Users/trygve/Library/Application/Support/pzizz/PlugIns/
    MyPlugin.plugin/Contents/Resources

    {contents = "NSBundleLanguagesList"} = <CFArray 0x31ef00 [0xa08011c0]>{type
    = mutable-small, count = 1, values = (
    {contents = "English.lproj"}
    )}

    {contents = "NSBundleInitialPath"} = /Users/trygve/Library/Application
    Support/pzizz/PlugIns/MyPlugin.plugin
    )}

    It is not reading the actual Info.plist from the new bundle, even though is
    sees the correct path information.

    Any ideas?

    I don't want to make the user quit the app to load new plugins.

    Thanks,

    Trygve
  • A follow up here....

    - (void)testLoadPlugins
    {
        NSEnumerator*
        enu = [[NSBundle pathsForResourcesOfType:@"plugin"
                        inDirectory:[[NSBundle mainBundle] builtInPlugInsPath]]
                objectEnumerator];

        NSString*        pluginPath;

    while ((pluginPath = [enu nextObject]))
    {
      NSBundle* pluginBundle = [NSBundle bundleWithPath:pluginPath];
      if (pluginBundle)
      {
      NSDictionary* pluginDict = [pluginBundle infoDictionary];
      NSString*    pluginName = [pluginDict objectForKey:@"NSPrincipalClass"];
      }
    }

    }

    If I run this method once with a single plugin in the /Contents/PlugIns
    folder of my app bundle, it works fine... pluginDict  ends up with 17 keys.

    However, if I then add a second plugin file to the /Contents/PlugIns folder,
    and run this method again, the original plugin still shows 17 keys, but the
    new plugin only shows 4 keys which is wrong - its Info.plist also has 17
    keys.

    Note the same thing happens is I run it once with zero plugins and than run
    it again with plugins present... They only show 4 keys and do not as
    NSPrincipalClass is not one of them, it fails.

    What is wrong here?

    Is pathsForResourcesOfType somehow caching things so I can't rescan a folder
    to load plugins?

    Trygve
  • Sorry,

    The explanation below is fixed... The previous one was all wonky.  :-)

    - (void)testLoadPlugins
    {
        NSEnumerator*
        enu = [[NSBundle pathsForResourcesOfType:@"plugin"
                        inDirectory:[[NSBundle mainBundle] builtInPlugInsPath]]
                objectEnumerator];

        NSString*        pluginPath;

    while ((pluginPath = [enu nextObject]))
    {
      NSBundle* pluginBundle = [NSBundle bundleWithPath:pluginPath];
      if (pluginBundle)
      {
      NSDictionary* pluginDict = [pluginBundle infoDictionary];
      NSString*    pluginName = [pluginDict objectForKey:@"NSPrincipalClass"];
      }
    }

    }

    If I run this method once with a single plugin in the /Contents/PlugIns
    folder of my app bundle, it works fine... pluginDict gets 17 keys.

    However, if I add a second plugin file to the /Contents/PlugIns folder,
    and run this method again, the original plugin still shows 17 keys, but the
    new plugin only shows 4 keys which is wrong - its Info.plist also has 17
    keys.

    Note that the same thing happens if I run it once with zero plugins and then
    run it again with plugins present... pluginDict only gets 4 keys and since
    NSPrincipalClass is not one of them, it fails.

    What is wrong here?

    Is pathsForResourcesOfType somehow caching things so I can't rescan a folder
    to load plugins?

    Trygve
  • No solution, but I'm also experiencing the exact same problem. In my
    case no plugin located with pathsForResourcesOfType has a proper
    infoDictionary. Though the NSBundle instances for each plugin claim to
    be correct.

    -Corey

    On 10/15/06, Trygve Inda <cocoa...> wrote:
    > Sorry,
    >
    > The explanation below is fixed... The previous one was all wonky.  :-)
    >
    > - (void)testLoadPlugins
    > {
    > NSEnumerator*
    > enu = [[NSBundle pathsForResourcesOfType:@"plugin"
    > inDirectory:[[NSBundle mainBundle] builtInPlugInsPath]]
    > objectEnumerator];
    >
    > NSString*        pluginPath;
    >
    > while ((pluginPath = [enu nextObject]))
    > {
    > NSBundle* pluginBundle = [NSBundle bundleWithPath:pluginPath];
    > if (pluginBundle)
    > {
    > NSDictionary* pluginDict = [pluginBundle infoDictionary];
    > NSString*    pluginName = [pluginDict objectForKey:@"NSPrincipalClass"];
    > }
    > }
    >
    > }
    >
    > If I run this method once with a single plugin in the /Contents/PlugIns
    > folder of my app bundle, it works fine... pluginDict gets 17 keys.
    >
    > However, if I add a second plugin file to the /Contents/PlugIns folder,
    > and run this method again, the original plugin still shows 17 keys, but the
    > new plugin only shows 4 keys which is wrong - its Info.plist also has 17
    > keys.
    >
    > Note that the same thing happens if I run it once with zero plugins and then
    > run it again with plugins present... pluginDict only gets 4 keys and since
    > NSPrincipalClass is not one of them, it fails.
    >
    > What is wrong here?
    >
    > Is pathsForResourcesOfType somehow caching things so I can't rescan a folder
    > to load plugins?
    >
    > Trygve
    >
    >
    > _______________________________________________
    > Do not post admin requests to the list. They will be ignored.
    > Cocoa-dev mailing list      (<Cocoa-dev...>)
    > Help/Unsubscribe/Update your Subscription:
    > http://lists.apple.com/mailman/options/cocoa-dev/<coreyoconnor...>
    >
    > This email sent to <coreyoconnor...>
    >

    --
    -Corey O'Connor
  • > No solution, but I'm also experiencing the exact same problem. In my
    > case no plugin located with pathsForResourcesOfType has a proper
    > infoDictionary. Though the NSBundle instances for each plugin claim to
    > be correct.
    >
    > -Corey

    It looks like I have to use NSFileManager for the directory contents and
    then manually determine the extension name... pathsForResourcesOfType does
    something to mess this all up.

    Trygve
  • On 10/16/06, Trygve Inda <cocoa...> wrote:
    >
    > It looks like I have to use NSFileManager for the directory contents and
    > then manually determine the extension name... pathsForResourcesOfType does
    > something to mess this all up.
    >
    > Trygve

    I tried switching to using NSFileManager but the infoDictionary for
    any found bundle is still missing all of the attributes in the
    Info.plist. The entire dictionary is something like:
    NSBundleResolvedPath = /Users/coconnor/Development/Pie
    Menus/build/Debug/Needs More
    Switches.app/Contents/Resources/Themes/Horizontal.nmstheme;
    NSBundleResourcePath = /Users/coconnor/Development/Pie
    Menus/build/Debug/Needs More
    Switches.app/Contents/Resources/Themes/Horizontal.nmstheme/Resources;
    NSBundleLanguagesList = <NSCFArray 0x35c610>(
    )
    ;
    NSBundleInitialPath = /Users/coconnor/Development/Pie
    Menus/build/Debug/Needs More
    Switches.app/Contents/Resources/Themes/Horizontal.nmstheme;
    }

    Which does not contain the 5 other properties that are in the
    Info.plist. Does anybody know another reason NSBundle's infoDictionary
    method would not return the actual Info.plist? Should I assume it's
    broken and just manually load the Info.plist file?

    -Corey
    --
    -Corey O'Connor
  • > On 10/16/06, Trygve Inda <cocoa...> wrote:
    >>
    >> It looks like I have to use NSFileManager for the directory contents and
    >> then manually determine the extension name... pathsForResourcesOfType does
    >> something to mess this all up.
    >>
    >> Trygve
    >
    > I tried switching to using NSFileManager but the infoDictionary for
    > any found bundle is still missing all of the attributes in the
    > Info.plist. The entire dictionary is something like:
    > NSBundleResolvedPath = /Users/coconnor/Development/Pie
    > Menus/build/Debug/Needs More
    > Switches.app/Contents/Resources/Themes/Horizontal.nmstheme;
    > NSBundleResourcePath = /Users/coconnor/Development/Pie
    > Menus/build/Debug/Needs More
    > Switches.app/Contents/Resources/Themes/Horizontal.nmstheme/Resources;
    > NSBundleLanguagesList = <NSCFArray 0x35c610>(
    > )
    > ;
    > NSBundleInitialPath = /Users/coconnor/Development/Pie
    > Menus/build/Debug/Needs More
    > Switches.app/Contents/Resources/Themes/Horizontal.nmstheme;
    > }
    >
    > Which does not contain the 5 other properties that are in the
    > Info.plist. Does anybody know another reason NSBundle's infoDictionary
    > method would not return the actual Info.plist? Should I assume it's
    > broken and just manually load the Info.plist file?
    >
    > -Corey

    Hi Corey,

    NSFileManager worked for me.... And I had the same results as you list above
    with pathforResourcesOfType.

    bundlePathsEnum = [bundlePaths objectEnumerator];
    while (folderPath = [bundlePathsEnum nextObject])
    {
        NSEnumerator*    enumerator = [[[NSFileManager defaultManager]
                        directoryContentsAtPath:folderPath] objectEnumerator];
        NSString*        pluginPath;

        while ((pluginPath = [enumerator nextObject]))
        {
          if ([[pluginPath pathExtension] isEqualToString:@"myextension"])
          {
            pluginPath = [[folderPath stringByAppendingString:@"/"]
                          stringByAppendingString:pluginPath];

            // Then this can be called
            NSBundle* pluginBundle = [NSBundle bundleWithPath:path];
            NSDictionary*    pluginDict = [pluginBundle infoDictionary];

          }
        }
      }
    }
  • On 10/16/06, Trygve Inda <cocoa...> wrote:
    >>
    >> I tried switching to using NSFileManager but the infoDictionary for
    >> any found bundle is still missing all of the attributes in the
    >> Info.plist. The entire dictionary is something like:
    ...
    >> Info.plist. Does anybody know another reason NSBundle's infoDictionary
    >> method would not return the actual Info.plist? Should I assume it's
    >> broken and just manually load the Info.plist file?
    >
    > Hi Corey,
    >
    > NSFileManager worked for me.... And I had the same results as you list above
    > with pathforResourcesOfType.
    >
    > bundlePathsEnum = [bundlePaths objectEnumerator];
    > while (folderPath = [bundlePathsEnum nextObject])
    > {
    > NSEnumerator*    enumerator = [[[NSFileManager defaultManager]
    > directoryContentsAtPath:folderPath] objectEnumerator];
    > NSString*        pluginPath;
    >
    > while ((pluginPath = [enumerator nextObject]))
    > {
    > if ([[pluginPath pathExtension] isEqualToString:@"myextension"])
    > {
    > pluginPath = [[folderPath stringByAppendingString:@"/"]
    > stringByAppendingString:pluginPath];
    >
    > // Then this can be called
    > NSBundle* pluginBundle = [NSBundle bundleWithPath:path];
    > NSDictionary*    pluginDict = [pluginBundle infoDictionary];
    >
    >
    > }
    > }
    > }
    > }

    That's about what I ended up using, except I still had to load the
    Info.plist manually. So where:
    NSDictionary* pluginDict = [pluginBundle infoDictionary];

    I have:
    NSString* info_path = [[pluginBundle bundlePath]
    stringByAppendingPathComponent: @"Info.plist"];
    NSDictionary* pluginDict = [NSDictionary
    dictionaryWithContentsOfFile: info_path];

    I have no idea why this was required, but otherwise I can't read the
    properties out of the Info.plist. Ah well.

    --
    -Corey O'Connor
previous month october 2006 next month
MTWTFSS
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          
Go to today