views:

392

answers:

1

I am developing a windows 7 gadget.I am creating an activex object and loading the assembly.I am following the methodlogy mentioned here at codeproject (GadgetInterop). One of the tasks of the gadget is to interface with Facebook.

This is how I am referencing: Javascript creates a GadgetBuilder object. From here I load the my library. say "MyLibrary.dll".

  • When I call method say MyLibrary.GetCount(), (just return some integer) it works.
  • But when I call some facebook function inside the method say MyLibrary.GetFaceBookFeeds() it throws an error.I reference "facebook.dll" from CodePlex

If I test my code from a ASP.NET form it works perfectly. However, When I run it from my html page by trying to load it using javascript, I get the following error:

Could not load file or assembly 'facebook, Version=2.1.3654.38113, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

I verified that the dll's are in the same folder as "MyLibrary.dll".

  1. Why is this error coming?
  2. How do I go about achieving my task? (I need to use calling a dll from javascript as we are doing a lot of other things in the dll).
+1  A: 

You're not forced to use a reflection-based assembly loader for .net code in desktop gadgets, you can write the assembly to be com visible, using class ids, etc. This article provides an example of using .net to achieve what you're trying to do without the "adapter".

That being said, there are various problems with activex based desktop gadgets that you should be aware of:

  • When an ActiveX instance is created in the gadget, the assembly dll will be "locked open" by sidebar.exe and the file cannot be deleted, even after the gadget has been closed. Unfortunately the gadget uninstallation process doesn't account for this and an uninstallation of the gadget will result in sidebar.exe copping out of the file deletion when it fails to delete the assembly, leaving the assembly and any other remaining files that hadn't been deleted up to that point. There's also no error message displayed. The same is true of overwriting a gadget (with a new version, for instance) - sidebar.exe attempts to delete the folder completely before installing the new gadget package, resulting in a failed installation in most cases.
  • The registration of such an activex control can be very tricky. The registry script given in the CodeProject article you provided does not work on my Windows 7 x64, for instance. The only way to work around this is to use WMI to write to the registry.
  • In a similar fashion, unregistration of the ActiveX control is also an issue. When the user uninstalls the gadget, the registry entries are left behind. Not a problem for a lot of people I suppose, but imagine a gadget enthusiast who tries every gadget he finds suddenly discovering the many unused registry entries. You can get around this by removing the registry entries directly after instantiating the object (since it's cached by the sidebar process anyway) and re-registering it again next startup.

So really although you can do it without reflection, using reflection can be a better option because you can copy the adapter assembly to an alternative folder, use it to load the current assembly and then unload it when the gadget is closed or finished using it. This eliminates the first issue of not being able to uninstall the gadget because the hosting assembly is located in a different folder and the reflected assembly is unloaded when the gadget is closed anyway.

The reason facebook.dll isn't loading is because the loader you're using doesn't correctly resolve dependencies (it can't find the file because it doesn't know where to look). You're welcome to try our reflection-based assembly loader called PluginLoader and see if that works. We haven't had an official release for it yet but we were intending to make it widely available and recommended for use by all developers to try and eliminate the problems with ActiveX and Windows Desktop Gadgets. Because we haven't officially released it you'll have to install our gadget, Auction Sidebar Tool which will install the plugin loader ready for use with the following code:

var plLoader = new ActiveXObject("Sidebar.PluginLoader");
var myLibrary = plLoader.LoadAssembly(classToLoad, 
                                System.Gadget.path+"\\path\\to\\MyLibrary.dll");
myLibrary.GetFaceBookFeeds();

Where class to load is the class you need to load in the format Namespace.Class (ie MyLibrary.MyClass). We specifically coded it to correctly resolve any dependencies so it should work for you just fine. If it does work for you, you're welcome to include it with your gadget. All you need is the PluginLoader.js and PluginLoader.dll files from the AuctionSidebarTool folder, but you'll need to edit the PluginLoader.js file to remove the parts that reference our assembly (line 110 onwards). If you include this in your project, it will check for an existing PluginLoader.dll and if it fails, it will copy it to the Windows Sidebar folder in local AppData, register it and provide the AddInLoader object with the methods LoadAssembly and UnloadAssembly. If you need any extra help just let me know in the comments.

Hope that helps. That's probably the longest answer I've written so far on SO :)

Andy E
Hi Andy,Thanks a lot for the detailed explanation. Agree with the points you made. I haven't gotten around to check/ use your solution. Will do that and update you.Thanks for one of the best replies.
rAm
No worries, I'm glad it helped. I'll update this answer in the future when I can get my .net dev to do a writeup on our plugin loader.
Andy E