1
votes

I have a Windows Service setup in the following path:

C:\Avalanche\Services\Avalanche.EXE
C:\Avalanche\Services\Core.DLL

Core.DLL is important. It is delay signed; it contains the interfaces that are to be exported for any plugins

Next, I have a folder for plugins to go:

C:\Avalanche\Snowballs\

The plugins I drop in here are delay signed and built against the correct version of Core.DLL, the same one in the Services folder.

My issue is, at runtime, MEF doesn't seem to see the plugins at all. It loads them, but can't seem to do anything with it. But if I don't sign anything, then there's no issue. The reason I'm signing the plugins is for version reasons. If I make v1 of a plugin and install it, then build v2 of the same plugin and install it (without bouncing the service), MEF will load v1 twice; this is not what I want. This normally isn't an issue, but this service is designed to stay up for quite some time (days, months at a time).

How can I get MEF to see these delay-signed assemblies? It doesn't seem to even pick them up.

Note: I've already tried to not delay-sign the assemblies. That yields a FileLoadException. I've also registered the assemblies for verification skipping (via sn and had it also export reg files which I've installed).

Here's the code inside Core.DLL that loads the plugins.

// Setup
iCatalog = new AggregateCatalog();
iWatcher = new List<FileSystemWatcher>();
List<DirectoryCatalog> oDirectories = new List<DirectoryCatalog>();

// Make sure all the folders exist; add them to the aggregate catalog.
// NOTE: aLocations is a string[] of directories that are to be used.
foreach (String sFolder in aLocations)
{
if (Directory.Exists(sFolder))
    {
        DirectoryCatalog oDirectoryCatalog = new DirectoryCatalog(sFolder);
        iCatalog.Catalogs.Add(oDirectoryCatalog);        
        oDirectories.Add(oDirectoryCatalog);
    }
}

iDirectories = oDirectories as IEnumerable<DirectoryCatalog>;

// Now then, create our CompositionContainer and compose the parts
iContainer = new CompositionContainer(iCatalog);
iContainer.ComposeParts(this);

Here's a sample plugin:

[Export(typeof(Core.Contracts.ISnowballPlugin))]
public class CSharpSample : Core.Contracts.ISnowballPlugin
{
    private CSharpSampleSnowball iSnowball = new CSharpSampleSnowball();
    public Core.Snowball.Snowball Snowball
    {
        get { return iSnowball; }
    }

    public TimeSpan Frequency
    {
        get { return TimeSpan.FromSeconds(2); }
    }

    public string Grouping
    {
        get { return "None"; }
    }

    public TimeSpan? Timeout
    {
        get { return null; }
    }
}

public class CSharpSampleSnowball : Core.Snowball.Snowball
{
    public CSharpSampleSnowball()
        : base("CSharp Example Version 2.0", "An example C# snowball")
    {

    }

    protected override void Run()
    {
        return;
    }
}
1

1 Answers

1
votes

Okay. I solved the solution for the moment. The fact that the plugins were signed seems to be a bit of a red herring.

Core.DLL being signed was a bigger problem than the plugins being signed. The Core.DLL file was failing to load properly (if at all). As a result, everything else after that fact is up for debate and question.

For now, I've used sn.exe to skip verification for Core.DLL. I'm marking this as the answer for now. I'd like to know why I have to skip verification for Core.DLL; is it because the EXE isn't signed as well?