5.8 KiB
5.8 KiB
Getting started
This walkthrough builds a plugin that draws a clock on the desktop, then adds a settings page and a tray command. Ten minutes, no LiveWall source needed.
1. Create the project
mkdir MyClock && cd MyClock
dotnet new classlib -n MyClock -f net8.0-windows
Edit MyClock.csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<UseWPF>true</UseWPF> <!-- overlays and pages are WPF elements -->
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<!-- Point this at LiveWall.Sdk.dll or its project. Private=false keeps the contract out of
your output: LiveWall supplies it at run time. -->
<ProjectReference Include="..\LiveWall.Sdk\LiveWall.Sdk.csproj">
<Private>false</Private>
<ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
</ItemGroup>
</Project>
If you only have the shipped binaries, reference the DLL instead:
<Reference Include="LiveWall.Sdk">
<HintPath>C:\path\to\LiveWall\LiveWall.Sdk.dll</HintPath>
<Private>false</Private>
</Reference>
Never ship
LiveWall.Sdk.dllin your plugin folder. LiveWall loads the contract itself; a second copy would give you a differentILiveWallPlugintype and the plugin would be rejected.
2. Write the plugin
ClockPlugin.cs:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using LiveWall.Sdk;
public sealed class ClockPlugin : ILiveWallPlugin
{
private TextBlock? _clock;
public void Initialize(IPluginContext context)
{
context.Log.Info("Clock plugin starting");
context.Extensions.AddOverlay(new ClockOverlay(this));
context.Extensions.AddCommand(new PluginCommand("clock.say", "Clock: say hello",
cmd => cmd.Host.ShowNotification("Clock", "Hello!"))
{
Category = "Clock"
});
context.Extensions.AddSettingsPage(new ClockSettingsPage(context));
}
public void Shutdown() => _clock = null;
private sealed class ClockOverlay : IWallpaperOverlay
{
private readonly ClockPlugin _plugin;
public ClockOverlay(ClockPlugin plugin) => _plugin = plugin;
public string Name => "Clock";
public FrameworkElement CreateView(OverlayContext context)
{
_plugin._clock = new TextBlock
{
Text = "12:00",
FontFamily = new FontFamily("Segoe UI Light"),
FontSize = 44,
Foreground = Brushes.White,
HorizontalAlignment = HorizontalAlignment.Right,
Margin = new Thickness(0, 24, 32, 0)
};
return _plugin._clock;
}
public void Update(OverlayState state) { /* wallpaper changed - optional */ }
}
private sealed class ClockSettingsPage : IPluginSettingsPage
{
private readonly IPluginContext _context;
public ClockSettingsPage(IPluginContext context) => _context = context;
public string Title => "Clock";
public string Description => "Colour of the desktop clock.";
public FrameworkElement CreateView()
{
var box = new TextBox { Text = _context.Storage.Get("colour", "#FFFFFF"), Width = 140 };
box.TextChanged += (_, _) => _context.Storage.Set("colour", box.Text);
return box;
}
}
}
plugin.json (copy it next to the assembly, and add
<None Include="plugin.json" CopyToOutputDirectory="PreserveNewest" /> to the csproj):
{
"id": "com.example.clock",
"name": "Desktop Clock",
"version": "1.0.0",
"author": "Your name",
"description": "Draws a clock on top of the wallpaper.",
"apiVersion": "1.0",
"entry": "MyClock.dll",
"type": "ClockPlugin",
"minHostVersion": "1.8.0",
"permissions": ["DesktopOverlay", "SettingsUi", "Commands"]
}
3. Build and install
dotnet build -c Release
mkdir "%APPDATA%\LiveWall\plugins\com.example.clock"
copy bin\Release\net8.0-windows\MyClock.dll "%APPDATA%\LiveWall\plugins\com.example.clock\"
copy bin\Release\net8.0-windows\plugin.json "%APPDATA%\LiveWall\plugins\com.example.clock\"
Then in LiveWall:
- Plugins tab → tick Enable the plugin system → read the warning → accept.
- Press Rescan plugins. Desktop Clock appears with an unverified badge.
- Press Enable → the per-plugin warning appears, listing the hash and the three permissions → accept. The clock appears on your desktop.
The folder can be opened from the app: Plugins ▸ Open plugin folder.
4. Debugging
- Everything you log goes to
%APPDATA%\LiveWall\logs\livewall-YYYYMMDD.log, prefixed with your plugin id:[com.example.clock] Clock plugin starting. Plugins ▸ Plugin logshows the same summary in the app, and Advanced ▸ Diagnostics includes a— Plugins —section with each plugin's state, hash and permissions.- Attach a debugger with Debug ▸ Attach to Process ▸ LiveWall.exe. Your plugin's exceptions are
visible in the Visual Studio exception window;
Initializeis called on the UI thread. - Edit → Rescan reloads your assembly without restarting LiveWall (the collectible load context really does unload — see troubleshooting.md).
- After changing code, rebuild, overwrite the DLL, and press Disable then Enable (or Rescan).
5. Next steps
- extension-points.md — every extension point, with the airspace and threading caveats you will hit as soon as you do something real.
- api-reference.md — the complete surface.
- examples.md — recipes: custom renderer, source resolver, playlist provider.