WyUpdate and new versions with Plugin

Hello-

I have created a plugin for an opensource software project. I released version 1.0 to users with WyUpdate and it works great. But now the opersource project has relased a version, and so I had to do an extensive rewrite of my plugin code to make it compatible with this new version, which means version 1.1 if my plugin will not be compatible for users that haven't upgraded the underlying opensource software yet. I currently have WyUpdate set to automatically download the latest version without user input. Of course I could change this back to manual updates, but I can just imagine the support calls I'll get when users update to the wrong version. Yuck.

I'm not sure how to proceed. Any suggestions?

This is an interesting problem. Before I can give you useful advice I have a couple of questions:

1. Is there any chance you could upgrade the base open source platform? Or would this be too destructive (i.e. angering users, breaking other plugins, breaking configuration, etc.)?

Because if you could do this, you could execute a bootstrap downloader to install it (see: Executing files in your update).

2. Could both plugins exist side-by-side? That is could you deliver 1.1 of your plugin to all users but it would only be loaded when they have newer version of the open source backend?

1. Changing the underlying source code for the project is out of the question, as the lead developer doesn't allow it. Hence the need for plugins if I want to modify the program's behavior for users. I create add-on modules that add functionality to the program.

2. I think #2 is a problem as well, unless the lead developer changes the way plugins are launched. There is a setup window where I have to have users enter the name of my .dll, which adds my plugin name to the list of .dlls that the base program can see. The name always has to be the same, so there's no way I can think of to have side by side versions. I can't think of any way around this, which is why I'm a bit stymied. Perhaps a kludgy way of doing it might be to have the versions uploaded with the version number of the base program number appended, have WyUpdate install them side by side, then have c# code that changes the name of the plugin version that matches the base program they've upgraded to to the proper .dll name, but that seems fraught with support headaches (eg., what happens if they downgrade the base program).

Thanks,

... have WyUpdate install them side by side, then have c# code that changes the name of the plugin version that matches the base program they've upgraded to to the proper .dll name, but that seems fraught with support headaches (eg., what happens if they downgrade the base program).

Well, you could just include 1.1+ of your plugin to the project as "YourPlugin-NewBackend.dll" (or something similar) along with "YourPlugin.dll". This would double the size of the initial distribution of your plugin, but subsequent updates will be tiny.

Unfortunately there's no graceful way to do this without modifying the base platform to be more flexible. That is, see if you can get the developer to add version detection & conditional dynamic loading (i.e. if a flag isn't set in your plugin, don't load the plugin). Something like how Firefox operates.

Or even better if the platform allowed you to write one plugin to target both versions of the backend would be an even better solution.

Sorry I couldn't be more help, but this is really a problem with how the open source platform is developed. If I were you I'd push for backward compatibility in the future so this doesn't happen the next update to the platform.

Thanks, that points me in the right direction.

OK, so I've managed to convince the lead developer to provide for different versions.

This code block below loops through all the files in the program's folder and changes the name of the version of my plugin that matches the version of the underlying program. There are quite a few other dlls in that folder, but I'm getting the following exception with only one - TurboActivate.dll (AutomaticUpdater.dll is in the same folder and does just fine):

"Could not load file or assembly 'C:\\Users\\wjs\\Desktop\\ODVersions\\opendental7.2b\\opendental7.2\\OpenDental\\bin\\Release\\TurboActivate.dll' or one of its dependencies. The module was expected to contain an assembly manifest."

Here's the code:

//for external plugins that need multiple versions in the OD folderstring[] fileEntries = Directory.GetFiles(Application.StartupPath);foreach (string fileName in fileEntries) { string pluginName = Path.GetFileNameWithoutExtension(fileName); string pluginFileName = pluginName; string isDll = Path.GetExtension(fileName); if (isDll == ".dll")//because this only works with .dlls, and there will be other extensions in this folder { AssemblyName assemblyName = AssemblyName.GetAssemblyName(Path.GetFileName(fileName));string aName = assemblyName.Name.ToString() + ".dll"; Version MainAppVersion = new Version(System.Windows.Forms.Application.ProductVersion);//eg. 6.8.0.0 Version MainAppMajMin = new Version(MainAppVersion.Major, MainAppVersion.Minor);//eg. 6.a string version = MainAppMajMin.ToString(); Regex regex = new Regex(version); if (regex.IsMatch(pluginFileName)) { File.Replace(pluginFileName + ".dll", aName, aName + POut.String(".old")); } } }

Google hasn't been much help. I found a few items on prebinding. Ay ideas?

That's because TurboActivate.dll is not a .NET assembly. It's a native dll. Just modify the loop to ignore TurboActivate.dll.

You might need to modify TurboActivate.cs in your project to load the .dll relative to the main executable path. That is, check if calling the TurboActivate functions causes an exception. If it does, then you'll either need to dynamically load the TurboActivate.dll, or change the "DllImport" attributes on the functions in TurboActivate.cs.

I'll help you out if this is the case.

Tell me if this helps.

Just modify the loop to ignore TurboActivate.dll.

Hehe...well, as usual I am unable to do that as that would be too specific in the underlying project's code as I'm coding a plugin.

You might need to modify TurboActivate.cs in your project to load the .dll relative to the main executable path. That is, check if calling the TurboActivate functions causes an exception. If it does, then you'll either need to dynamically load the TurboActivate.dll, or change the "DllImport" attributes on the functions in TurboActivate.cs.

All the TurboActivate functions work. The loop above was added to load the correct plugin after it's been downloaded by AutomaticUpdater. So am I stuck?

No, you're not stuck. You can do 1 of 2 things:

Option 1: (The best solution)

Modify the algorithm to only load .NET assemblies. This means fixing the algorithm to read more like this:

bool IsNETAssembly = CheckIfNetAssembly(filename);


if (isDll == ".dll" && IsNETAssembly){    ...}

We use similar code inside wyBuild to detect which assemblies to NGEN without bothering the users with the details. I have a blog post in queue explaining how we do this (with a full code sample). I'll post it this week if you want to include it with the open source platform.

Option 2: (less desirable - more hacky)

Move TurboActivate.* to a subdirectory. Then modify your code (the DllImport attributes and TurboActivate.exe references) to use TurboActivate from the subdirectory. This is hacky and really is a workaround to the problem in the plugin loading code.

Are you interested in the .NET detection code?

Option 1 looks perfect.

By all means I'd love to see the blog post.

Thank you very much.