Skip to content

Building and Distributing Plugins

Jamie Head edited this page Aug 5, 2026 · 4 revisions

Building and Distributing Plugins

Copy after build

Place this target near the end of the plugin .csproj:

<Target Name="CopyPluginToSimulcastUtility" AfterTargets="Build">
  <PropertyGroup>
    <PluginName Condition="'$(SolutionName)' != ''">$(SolutionName)</PluginName>
    <PluginName Condition="'$(PluginName)' != ''">$(AssemblyName)</PluginName>
    <PluginName Condition="'$(PluginName)' == '' and '$(SolutionName)' == ''">Example_Plugin_Name</PluginName>
    <PluginDirectory>$(LOCALAPPDATA)\SimulcastUtility\Plugins\$(PluginName)</PluginDirectory>
  </PropertyGroup>

  <MakeDir Directories="$(PluginDirectory)" />

  <ItemGroup>
    <PluginFiles Include="$(TargetPath)" />
    <PluginFiles Include="$(TargetDir)$(AssemblyName).pdb" Condition="'$(Configuration)' == 'Debug' and Exists('$(TargetDir)$(AssemblyName).pdb')" />
    <PluginFiles Include="$(TargetDir)Your.Private.Dependency.dll" Condition="Exists('$(TargetDir)Your.Private.Dependency.dll')" />
  </ItemGroup>

  <Copy SourceFiles="@(PluginFiles)" DestinationFolder="$(PluginDirectory)" SkipUnchangedFiles="true" />
</Target>

Do not copy $(TargetDir)*.*; it includes host contracts and framework assemblies that should not be packaged.

Contract references

Set host references to Private=false:

<Reference Include="SimulcastUtility.Plugins">
  <HintPath>lib\SimulcastUtility.Plugins.dll</HintPath>
  <Private>false</Private>
</Reference>

Do the same for SimulcastUtility.Application and SimulcastUtility.Core. The host must supply these assemblies so plugin types share the same identity as application interfaces.

Include

  • Main plugin DLL.
  • Plugin-owned WPF resources not embedded as Page/Resource.
  • Private managed dependencies not supplied by the host.
  • Native runtime files required by private dependencies.
  • .deps.json when required for dependency discovery.
  • PDB files only in debug/developer packages.

Exclude

  • SimulcastUtility.Plugins.dll
  • SimulcastUtility.Application.dll
  • SimulcastUtility.Core.dll
  • Microsoft.Extensions.* assemblies already supplied by the target application unless a truly private/version-specific dependency requires otherwise
  • WPF and .NET runtime assemblies
  • Test assemblies, XML docs you do not intend to ship, and unrelated build output
  • User data or developer-specific settings
  • Plugin .pdb files if not in a debug environment

Package formats

Manage Plugins accepts a single DLL, a selected collection of DLLs, or a ZIP archive. Prefer ZIP for plugins with dependencies or native assets. Use one clearly named top-level folder and keep the main DLL easy to identify.

Example:

MyPlugin/
  MyPlugin.dll
  MyPlugin.deps.json
  ThirdParty.Library.dll
  runtimes/
    win-x64/
      native/
        native-library.dll

Release checklist

  • Build Release for net10.0-windows and the target architecture requirements.
  • Test import from a clean plugin directory.
  • Test enable, disable, re-enable, refresh, directory reload, and deletion.
  • Confirm no contract DLLs are included.
  • Confirm settings survive restart and plugin-data directory changes.
  • Confirm all UI follows default and custom themes.
  • Confirm logs contain useful structured messages without secrets.
  • Test with no receivers and with the selected receiver changing.
  • Document application compatibility and plugin version.

Clone this wiki locally