1. 製品設定とテストライセンスを準備する
C#・.NET または WinForms アプリに、顧客のライセンスキー認証と機能制御を追加します。このガイドは商用アプリの利用権を管理するもので、ソースコードのオープンソースライセンス選定とは別です。まず端末固定ライセンスと、回数を消費しないエクスポート機能を実装します。
デバイス枠は現在のアクティベーション数で計算し、解除すると返却されます。通常ライセンスはオフラインでも枠を使用し、フローティングライセンスはリース満了時にも自動返却されます。
- [コンソール] > [製品] から製品 ID をコピーします。その製品の署名公開鍵を開き、すべてのキー ID/公開鍵のペアを初期化コードに貼り付けて、YOUR_PRODUCT_ID、YOUR_KEY_ID、および YOUR_PUBLIC_KEY を置き換えます。迅速な統合により、これらのパブリック コード定数を生成できます。製品構成ファイルは必要ありません。 SDK のデフォルトは https://www.licentivo.com. です
- .NET 8 SDK 以降をインストールします。 Licentivo クイック統合では、製品を作成または選択し、そのポリシーとライセンスでエクスポート機能を許可します。
2. 固定された .NET パッケージをインストールします
アプリのプロジェクトで以下のコマンドを実行するか、ビルド依存関係を追加して SDK 0.11.6 を導入します。パッケージマネージャーが SDK を取得するため、ソース ZIP の取得、手動展開、ローカルソースパスの指定は不要です。
dotnet add package Licentivo.SDK --version 0.11.6dotnet new console --name LicensedApp --framework net8.0
cd LicensedApp
dotnet add package Licentivo.SDK --version 0.11.63. 1 つの実際の操作をアクティブ化して保護する
SDK スタートアップをアプリケーションのスタートアップ ハンドラーまたはアクティベーション ハンドラーに移動します。アクティベーション フォームからカスタマー キーを読み取り、自分の製品 ID と信頼できるキーを渡し、シャットダウンするまでクライアントを存続させます。実際のビジネス エントリ ポイントに RunFeature を置きます。レポート ライターを独自の操作に置き換えます。
using Licentivo;
// BEGIN LICENTIVO PRODUCT
// Copy Product ID and all key ID/public key pairs from Console > Products > Signing public keys.
const string ProductId = "YOUR_PRODUCT_ID";
var TrustedKeys = new Dictionary<string,string> { ["YOUR_KEY_ID"] = "YOUR_PUBLIC_KEY" };
// END LICENTIVO PRODUCT
static string Setting(string name, string fallback) => Environment.GetEnvironmentVariable(name) ?? fallback;
// Call at the business entry point, including shortcuts and alternate menu actions.
static async Task ExportReport(string path)
{
// Replace this write with your existing, non-metered export operation.
await File.WriteAllTextAsync(path, "A report generated by the licensed application.\n");
}
try
{
// In a GUI, read the activation input. Later starts pass an empty key.
await using var client = await LicentivoClient.OpenProduct(
ProductId, TrustedKeys, Setting("LICENTIVO_LICENSE_KEY", ""),
error => Console.Error.WriteLine($"Background verification: {error.Message}"));
var feature = Setting("LICENTIVO_FEATURE", "export");
var path = Setting("LICENTIVO_OUTPUT", "licensed-report.txt");
if (Setting("LICENTIVO_METERED", "") == "1")
await client.RunMeteredFeature(feature, 1, Setting("LICENTIVO_OPERATION_ID", ""), () => ExportReport(path));
else
await client.RunFeature(feature, () => ExportReport(path));
Console.WriteLine($"License OK: {feature} is available\nExport completed: {path}");
// Keep client alive in your real app; disposal belongs in app shutdown.
}
catch (Exception error)
{
Console.Error.WriteLine(error.Message);
Environment.ExitCode = 2;
}
$env:LICENTIVO_LICENSE_KEY = 'YOUR_TEST_LICENSE_KEY'
dotnet run
# On later starts, restore the saved device credential:
Remove-Item Env:LICENTIVO_LICENSE_KEY
dotnet runexport LICENTIVO_LICENSE_KEY='YOUR_TEST_LICENSE_KEY'
dotnet run
# On later starts, restore the saved device credential:
unset LICENTIVO_LICENSE_KEY
dotnet run4. Connect のアクティブ化と WinForms へのエクスポート
すべてのエクスポート エントリ ポイントで、client.RunFeature("export", ExportReport) を待ちます。メニュー項目とショートカットを含めます。操作の実行中に開始ボタンを無効にし、エラーを検出して、別の試行を許可する前に拒否を表示します。
SDK ハートビートで認証を更新できるように、ウィンドウが開いている間はクライアントを存続させておきます。 Invoke または BeginInvoke を使用して、バックグラウンド エラー メッセージを UI スレッドにマーシャリングします。アプリケーションのシャットダウン時に DisposeAsync を待ちます。通常の処分では、デバイスに関連付けられた登録が保持され、同時接続枠の返却が試行されます。
デスクトップアプリのサンプルは、下のドキュメントリンクから別途取得できます。WinForms には Windows が必要です。上のコンソールサンプルは Linux と macOS でも実行できます。
dotnet new winforms --name LicensedWinForms --framework net8.0
cd LicensedWinForms
dotnet add package Licentivo.SDK --version 0.11.6using Licentivo;
namespace LicensedWinForms;
sealed class DemoForm : Form {
// BEGIN LICENTIVO PRODUCT
// Console > Products > Signing public keys: paste Product ID and every key ID/public key pair.
const string ProductId = "YOUR_PRODUCT_ID";
static readonly Dictionary<string,string> TrustedKeys = new() { ["YOUR_KEY_ID"] = "YOUR_PUBLIC_KEY" };
// END LICENTIVO PRODUCT
readonly TextBox key = new() { Width = 380, UseSystemPasswordChar = true };
readonly Label status = new() { AutoSize = true, MaximumSize = new Size(550, 0), Text = "Enter a key, or leave empty to restore this device." };
readonly CancellationTokenSource lifetime = new();
LicentivoClient? client;
bool busy;
[STAThread] static void Main() { ApplicationConfiguration.Initialize(); Application.Run(new DemoForm()); }
DemoForm() {
Text = "Licentivo · Report export"; ClientSize = new Size(600, 220);
var panel = new FlowLayoutPanel { Dock = DockStyle.Fill, Padding = new Padding(20), FlowDirection = FlowDirection.TopDown, WrapContents = false, AutoScroll = true };
Controls.Add(panel); panel.Controls.Add(new Label { Text = "Customer license key", AutoSize = true }); panel.Controls.Add(key);
Add(panel, "Activate / restore", async () => {
if (client is not null) { await client.DisposeAsync(); client = null; }
client = await LicentivoClient.OpenProduct(ProductId, TrustedKeys, key.Text, ct: lifetime.Token);
key.Clear(); status.Text = client.Status().State;
});
var buttons = new FlowLayoutPanel { AutoSize = true, AutoSizeMode = AutoSizeMode.GrowAndShrink, WrapContents = false }; panel.Controls.Add(buttons);
Add(buttons, "Export CSV", () => Export("export", "report.csv"));
Add(buttons, "Pro export", () => Export("pro", "pro-report.csv"));
Add(buttons, "Refresh license", async () => { await Require().RefreshOnline(lifetime.Token); status.Text = Require().Status().State; });
panel.Controls.Add(status);
FormClosed += async (_, _) => { lifetime.Cancel(); if (client is not null) await client.DisposeAsync(); };
}
LicentivoClient Require() => client ?? throw new InvalidOperationException("Activate the application first.");
async Task Export(string feature, string filename) {
using var save = new SaveFileDialog { FileName = filename, Filter = "CSV report|*.csv" };
await Require().RunFeature(feature, async () => {
if (save.ShowDialog(this) != DialogResult.OK) return;
await File.WriteAllTextAsync(save.FileName, "Item,Quantity,Price\nNotebook,2,12.50\nPen,5,3.00\n");
status.Text = "Saved: " + save.FileName;
});
}
void Add(Control panel, string title, Func<Task> action) {
var button = new Button { Text = title, AutoSize = true }; panel.Controls.Add(button);
button.Click += async (_, _) => {
if (busy) return; busy = true; status.Text = "Working…";
try { await action(); } catch (Exception error) { if (!IsDisposed) status.Text = error.Message; }
finally { busy = false; }
};
}
}
dotnet run5. アクティブ化、再起動、拒否を確認する
- テスト キーを使用して実行し、ライセンスが OK でエクスポートが完了したことを確認してから、レポートの内容を検査します。
- 主要な環境変数を削除し、同じオペレーティング システム ユーザーで再起動します。既存のデバイス認証情報は、新しく登録されたデバイスなしで復元される必要があります。
- ライセンスにない機能を選択するには LICENTIVO_FEATURE を使用し、新しいファイル名を選択するには LICENTIVO_OUTPUT を使用します。ゼロ以外の終了コードと、この新しいファイルが作成されないことを確認してください。
- オフライン起動を許可するポリシーと有効な署名付きキャッシュを使用してのみ、オフライン起動を確認してください。フローティングおよびオンラインのみの起動にはサーバーの承認が必要です。
ライセンスチェックのトラブルシューティング
製品 ID、すべてのキー ID/公開鍵のペア、および顧客のライセンス入力を確認します。公開検証キーは製品に属します。顧客のライセンスと保存されたデバイスの認証情報は別のものです。開発テスト キーやベンダー管理 API キーを配布しないでください。
ライセンスの有効期限が切れている場合、デバイスの制限がある場合、または機能が欠落している場合は、認証が拒否されます。 RunFeature をバイパスする代わりに、エラーとリクエスト ID を表示し、コンソールでライセンスまたはポリシーを解決します。
月ごとの使用量制限については、RunMeteredFeature を呼び出すときに安定したジョブ ID と永続的なビジネス結果を保持します。通常のアプリのシャットダウンと顧客要求による非アクティブ化は目的が異なります。終了するたびにデバイスにバインドされた登録を解放しないでください。