Production-ready GNTP (Growl Notification Transport Protocol) client for .NET with full Windows/Android/macOS/Linux compatibility and callback support.
- β Full GNTP 1.0 protocol implementation
- β Async/await support for modern .NET
- β Callback support (click, close, timeout events)
- β Multiple icon delivery modes (Binary, File URL, Data URL, HTTP URL)
- β Cross-platform (Windows, macOS, Linux, Android)
- β Multi-targeting (.NET Standard 2.0/2.1, .NET 6/7/8)
- β Zero dependencies - pure .NET implementation
- β Fully documented with XML comments
dotnet add package Gntp.NetOr via NuGet Package Manager:
Install-Package Gntp.Net
using Gntp.Net;
// Create client
var client = new GntpClient("My Application");
// Define notification type
var notification = new NotificationType("alert")
.WithDisplayName("Alert Notification");
// Register
await client.RegisterAsync(notification);
// Send notification
await client.NotifyAsync("alert", "Hello", "This is a test notification");var client = new GntpClient("My App");
var notification = new NotificationType("alert");
await client.RegisterAsync(notification);
await client.NotifyAsync("alert", "Title", "Message");var client = new GntpClient("Icon App")
.WithIconMode(IconMode.Binary); // Best for Windows
var icon = GntpResource.FromFile("icon.png");
var notification = new NotificationType("alert")
.WithIcon(icon);
await client.RegisterAsync(notification);
await client.NotifyAsync("alert", "With Icon!", "This has an icon");var client = new GntpClient("Callback App");
await client.WithCallbackAsync(info =>
{
Console.WriteLine($"Event: {info.Type}");
Console.WriteLine($"Context: {info.Context}");
switch (info.Type)
{
case CallbackType.Click:
Console.WriteLine("User clicked!");
break;
case CallbackType.Close:
Console.WriteLine("User closed");
break;
case CallbackType.Timeout:
Console.WriteLine("Timed out");
break;
}
});
var notification = new NotificationType("alert");
await client.RegisterAsync(notification);
var options = new NotifyOptions()
.WithSticky(true)
.WithCallbackContext("user_data_123")
.WithCallbackTarget("https://example.com");
await client.NotifyAsync("alert", "Click Me!", "Message", options);
// Keep app running to receive callbacks
Console.ReadKey();
client.Dispose();var client = new GntpClient("Multi-Type App");
var info = new NotificationType("info").WithDisplayName("Information");
var warning = new NotificationType("warning").WithDisplayName("Warning");
var error = new NotificationType("error").WithDisplayName("Error");
await client.RegisterAsync(info, warning, error);
await client.NotifyAsync("info", "Info", "Something happened");
await client.NotifyAsync("warning", "Warning", "Be careful!");
await client.NotifyAsync("error", "Error", "Something went wrong!");var client = new GntpClient("Remote App")
.WithHost("192.168.1.100")
.WithPort(23053);var options = new NotifyOptions()
.WithSticky(true) // Stays until dismissed
.WithPriority(2) // Emergency priority (-2 to 2)
.WithIcon(icon) // Per-notification icon
.WithCallbackContext("data") // Custom callback data
.WithCallbackTarget("https://example.com"); // URL to open
await client.NotifyAsync("alert", "Title", "Text", options);var client = new GntpClient("App")
.WithIconMode(IconMode.Binary);Format: x-growl-resource://UUID + binary data
Best for: Windows Growl, macOS, Linux
β
Tested and working on all platforms
var client = new GntpClient("App")
.WithIconMode(IconMode.DataUrl);Format: data:image/png;base64,iVBORw0...
Best for: Android, fallback option
var client = new GntpClient("App")
.WithIconMode(IconMode.FileUrl);Format: file:///C:/full/path/to/icon.png
Best for: Shared icons on disk
var client = new GntpClient("App")
.WithIconMode(IconMode.HttpUrl);Format: http://example.com/icon.png
Best for: Web-hosted icons
| Platform | Binary Mode | DataURL Mode | Callbacks | Recommended |
|---|---|---|---|---|
| Windows (Growl for Windows) | β Works | β Works | Binary | |
| macOS (Growl) | β Works | β Works | β Works | Binary |
| Linux (Growl-compatible) | β Works | β Works | β Works | Binary |
| Android (Growl for Android) | β Works | β Works | β Works | Binary or DataURL |
Callbacks are triggered when users interact with notifications:
CallbackType.Click- User clicked the notificationCallbackType.Close- User closed the notificationCallbackType.Timeout- Notification timed out
await client.WithCallbackAsync(info =>
{
// info.Type - Event type
// info.NotificationId - Notification ID
// info.Context - Custom data
// info.Timestamp - Event time
});// Constructor
new GntpClient(string applicationName)
// Configuration
.WithHost(string host)
.WithPort(int port)
.WithIcon(GntpResource icon)
.WithIconMode(IconMode mode)
.WithDebug(bool debug)
.WithTimeout(int timeout)
.WithCallbackAsync(Action<CallbackInfo> handler)
// Operations
await RegisterAsync(params NotificationType[] notifications)
await NotifyAsync(string name, string title, string text)
await NotifyAsync(string name, string title, string text, NotifyOptions options)// Static factory methods
GntpResource.FromFile(string path)
GntpResource.FromBytes(byte[] data, string mimeType)
// Instance methods
string GetReference(IconMode mode)
string ToDataUrl()Try Binary mode (most reliable):
client.WithIconMode(IconMode.Binary);Ensure:
- Callback is set BEFORE
RegisterAsync() - App stays running to receive callbacks
- Call
client.Dispose()when done - Firewall allows incoming connections
Use longer timeout:
client.WithTimeout(15000); // 15 secondsContributions welcome! Please open an issue or PR.
MIT License - See LICENSE file for details.
- Rust gntp: https://github.com/cumulus13/gntp
- Go go-gntp: https://github.com/cumulus13/go-gntp
- Python gntplib: https://github.com/cumulus13/gntplib
Production-ready GNTP client for .NET with full cross-platform support and callback functionality!
