AzureTray.Plugin.Contracts 1.3.0

dotnet add package AzureTray.Plugin.Contracts --version 1.3.0
                    
NuGet\Install-Package AzureTray.Plugin.Contracts -Version 1.3.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="AzureTray.Plugin.Contracts" Version="1.3.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="AzureTray.Plugin.Contracts" Version="1.3.0" />
                    
Directory.Packages.props
<PackageReference Include="AzureTray.Plugin.Contracts" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add AzureTray.Plugin.Contracts --version 1.3.0
                    
#r "nuget: AzureTray.Plugin.Contracts, 1.3.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package AzureTray.Plugin.Contracts@1.3.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=AzureTray.Plugin.Contracts&version=1.3.0
                    
Install as a Cake Addin
#tool nuget:?package=AzureTray.Plugin.Contracts&version=1.3.0
                    
Install as a Cake Tool

AzureTray.Plugin.Contracts

The SDK package for building AzureTray plugins. Reference this package to implement ITrayPlugin and ship a plugin the host can load.

What's inside

  • ITrayPlugin — the top-level plugin contract.
  • IPluginContext — services the host hands to the plugin at initialization (logger, HTTP factory, clipboard, notifier, tenant list, badge surface, etc.).
  • PluginMenuItem, PluginPermissionRequirement, PluginOption, PluginTest, PluginTenant, NotificationRequest/NotificationResult — the supporting data types.
  • PluginApiVersion — the contract version your plugin must declare it was built against.

Minimum plugin csproj

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <IsPackable>true</IsPackable>
    <PackageId>YourOrg.AzureTray.Plugin.YourPlugin</PackageId>
    
    <PackageTags>proxylayer.azuretray-plugin;your;tags</PackageTags>
  </PropertyGroup>

  <ItemGroup>
    
    <PackageReference Include="AzureTray.Plugin.Contracts" Version="1.2.0" PrivateAssets="all" />
  </ItemGroup>
</Project>

Packaging & deployment

1. Add the required project property

Add <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> to your <PropertyGroup>. This copies every transitive NuGet dependency into the build output so the host can resolve them at runtime without a global package cache.

<PropertyGroup>
  <TargetFramework>net8.0</TargetFramework>
  <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
  ...
</PropertyGroup>
# Produces a self-contained output folder with a .deps.json — the preferred path.
dotnet publish YourPlugin.csproj -c Release -o ./out

# A plain build also works; the host falls back to sibling-DLL resolution
# when no .deps.json is present.
dotnet build YourPlugin.csproj -c Release

Do not ship AzureTray.Plugin.Contracts.dll in the output — the PrivateAssets="all" reference in your .csproj already excludes it. The host loads its own copy of that assembly; a second copy causes a type-identity mismatch and the ITrayPlugin cast silently fails.

3. Install into the plugins folder

The host scans %LOCALAPPDATA%\AzureTray.Data\plugins\ at startup using two layouts:

Layout When to use Steps
Subfolder (recommended) Any plugin with transitive deps Create plugins\<YourPackageId>\, copy your publish output there. The main DLL must be named <folder-name>.dll (e.g. plugins\Acme.Plugin.Foo\Acme.Plugin.Foo.dll).
Flat (legacy) Single-DLL plugins with no private deps Drop YourPlugin.dll directly in plugins\.

For the subfolder layout the loader first tries plugins\<folder>\<folder>.dll; if that name doesn't exist it scans for any DLL in the folder that contains an ITrayPlugin implementation. Framework assemblies whose name starts with System., Microsoft., Azure., or Newtonsoft. are skipped during the scan.

4. Runtime trust mode

The default trust mode is AllowUnsigned (development). For your own testing this means no signing is needed. Deployments configured with RequireSigned or RequireTrustedPublisher will reject the plugin unless it carries a valid Authenticode signature.

Version gate

Plugins declare ITrayPlugin.ApiVersion (the PluginApiVersion.Current value they were built against). The host loads a plugin when that value falls within its supported range [PluginApiVersion.MinSupported, PluginApiVersion.Current]; anything outside the range is rejected with a logged message naming the range. Use PluginApiVersion.IsSupported(int) to test a value.

Because the contracts assembly keeps a fixed AssemblyVersion, an old plugin always binds to the host's current contracts copy at runtime — the range is the only thing that decides whether that copy will load it.

How the range moves:

  • Additive, binary-compatible changes (a new default-interface member, a new optional capability interface, a new init-only property on a record) bump Current and leave MinSupported alone. Plugins built against any version still in the window keep loading — so you can build against an older API and keep running on newer hosts.
  • Breaking changes raise MinSupported, intentionally locking out the now-incompatible older plugins. These should be rare; prefer the additive techniques above.

To run a single plugin binary across a span of hosts, build against the lowest API you need and feature-detect newer host capabilities at runtime via IPluginContext.HostVersion.

More

See CONTRIBUTING.md in the host repo for the full plugin author guide, including how to submit a plugin to the curated registry the in-app browser pulls from.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.3.0 118 5/28/2026
1.2.0 106 5/27/2026
1.0.0 96 5/20/2026
0.2.0 101 5/12/2026
0.2.0-preview.202605120535 54 5/12/2026