Marketplace
最新
バナーの背景画像
Marketplace ユーザー ガイド
最終更新日 2024年4月16日

ライセンスの実装

ここでは、ライセンス SDK ライブラリをアクティビティ パッケージに埋め込むプロセスについて説明します。

パッケージが UiPath Activity Creator を使用して開発されているかどうかに応じて、次の手順を実行してください。

重要: VS ソリューションが .NET 4.6.1 に対応している必要があります。
注:

.NET 6 または Windows に対応したカスタム アクティビティのライセンス実装の責任はベンダーにあります。Marketplace では .NET 6 に対応したライセンス ライブラリは提供されていません。提供されているのは、Windows レガシ対応のライセンス ライブラリです。

パッケージが UiPath Activity Creator を使用して開発されている場合

  1. スコープ アクティビティのシナリオがない場合は、各アクティビティの ExecuteAsync メソッドに検証チェックを追加します。

    スコープ アクティビティのシナリオがあり、すべてのアクティビティがライセンス対象である場合は、該当するアクティビティにのみ検証チェックを追加できます。

    protected override async Task<Action<AsyncCodeActivityContext>> ExecuteAsync(AsyncCodeActivityContext context, CancellationToken cancellationToken)
            {
                // Inputs
                var firstNumber = FirstNumber.Get(context);
                var secondNumber = SecondNumber.Get(context);
                // License validation
                #if !DEBUG
                    //if your package is MyCompany.MyPackageName.Activities.1.0.0.nupkg
                    await Validator.ValidateAsync(context, "MyCompany.MyPackageName.Activities");
                #endif
                ///////////////////////////
                // Add execution logic HERE
                ///////////////////////////
                // Outputs
                return (ctx) => {
                };
            }protected override async Task<Action<AsyncCodeActivityContext>> ExecuteAsync(AsyncCodeActivityContext context, CancellationToken cancellationToken)
            {
                // Inputs
                var firstNumber = FirstNumber.Get(context);
                var secondNumber = SecondNumber.Get(context);
                // License validation
                #if !DEBUG
                    //if your package is MyCompany.MyPackageName.Activities.1.0.0.nupkg
                    await Validator.ValidateAsync(context, "MyCompany.MyPackageName.Activities");
                #endif
                ///////////////////////////
                // Add execution logic HERE
                ///////////////////////////
                // Outputs
                return (ctx) => {
                };
            }
    注:
    • コンテキスト オブジェクトは 1 回だけ渡すことが可能で、渡された先のメソッドでのみ使用できます。たとえば、Validator.ValidateAsync 呼び出しの後に ExecuteAsync メソッドで使用することはできません。
    • 上記の要件を考慮すると、コンテキストをライセンス メソッド/ライブラリに渡す前に入力変数を読み取る必要もあります。
  2. Licensing.dll ライブラリで .Activities プロジェクトを参照し、using ステートメントを追加します。



    using UiPath.Marketplace.License.Validations;

  3. 設定が完了しました。パッケージをビルドし、Licensing.dll ライブラリがパッケージの内容 (lib フォルダー内) に存在することを確認します。その後、Marketplace に提出できます。

パッケージが UiPath Activity Creator を使用して開発されていない場合

最初のアクティビティは次のようになります。

using System;
using System.Activities;
using System.ComponentModel;
    namespace ClassMathCustomActivity
{
    public class SimpleFormula : CodeActivity
    {
        [Category("Input")]
        [RequiredArgument]
        public InArgument<double> FirstNumber { get; set; }
        [Category("Input")]
        public InArgument<double> SecondNumber { get; set; }
        [Category("Output")]
        public OutArgument<double> ResultNumber { get; set; }
        protected override void Execute(CodeActivityContext context)
        {
            var firstNumber = FirstNumber.Get(context);
            var secondNumber = SecondNumber.Get(context);
            var result = System.Math.Pow(firstNumber + secondNumber, 2);
            ResultNumber.Set(context, result);
        }
    }
}using System;
using System.Activities;
using System.ComponentModel;
    namespace ClassMathCustomActivity
{
    public class SimpleFormula : CodeActivity
    {
        [Category("Input")]
        [RequiredArgument]
        public InArgument<double> FirstNumber { get; set; }
        [Category("Input")]
        public InArgument<double> SecondNumber { get; set; }
        [Category("Output")]
        public OutArgument<double> ResultNumber { get; set; }
        protected override void Execute(CodeActivityContext context)
        {
            var firstNumber = FirstNumber.Get(context);
            var secondNumber = SecondNumber.Get(context);
            var result = System.Math.Pow(firstNumber + secondNumber, 2);
            ResultNumber.Set(context, result);
        }
    }
}

最も重要な変更として、Execute メソッドを変更する必要があり、ExecuteAsync にする必要があります。

解決策として、次のような AsyncTaskCodeActivity.cs クラス を作成することをお勧めします。

using System;
using System.Activities;
using System.Runtime.ExceptionServices;
using System.Threading;
using System.Threading.Tasks;
namespace ClassMathCustomActivity
{
  internal struct AsyncTaskCodeActivityImplementation : IDisposable
  {
    private CancellationTokenSource _cancellationTokenSource;
    private bool _tokenDisposed;
    public void Cancel()
    {
      if (!_tokenDisposed)
      {
        _cancellationTokenSource?.Cancel();
        _cancellationTokenSource?.Dispose();
        _tokenDisposed = true;
      }
    }
    public IAsyncResult BeginExecute(AsyncCodeActivityContext context
      , Func<AsyncCodeActivityContext, CancellationToken, Task<Action<AsyncCodeActivityContext>>> onExecute
      , AsyncCallback callback, object state)
    {
      if (!_tokenDisposed)
      {
        _cancellationTokenSource?.Dispose();
      }
      _cancellationTokenSource = new CancellationTokenSource();
      _tokenDisposed = false;
      TaskCompletionSource<Action<AsyncCodeActivityContext>> taskCompletionSource = new TaskCompletionSource<Action<AsyncCodeActivityContext>>(state);
      Task<Action<AsyncCodeActivityContext>> task = onExecute(context, _cancellationTokenSource.Token);
      var cancellationTokenSource = _cancellationTokenSource;
      task.ContinueWith(t =>
      {
        if (t.IsFaulted)
        {
          taskCompletionSource.TrySetException(t.Exception.InnerException);
        }
        else if (t.IsCanceled || cancellationTokenSource.IsCancellationRequested)
        {
          taskCompletionSource.TrySetCanceled();
        }
        else
        {
          taskCompletionSource.TrySetResult(t.Result);
        }
        callback?.Invoke(taskCompletionSource.Task);
      });
      return taskCompletionSource.Task;
    }
    public void EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
    {
      Task<Action<AsyncCodeActivityContext>> task = (Task<Action<AsyncCodeActivityContext>>)result;
      if (task.IsFaulted)
      {
        ExceptionDispatchInfo.Capture(task.Exception.InnerException).Throw();
      }
      if (task.IsCanceled)
      {
        context.MarkCanceled();
      }
      task.Result?.Invoke(context);
      if (!_tokenDisposed)
      {
        _cancellationTokenSource?.Dispose();
        _tokenDisposed = true;
      }
    }
    private bool _disposed; // To detect redundant calls
    public void Dispose()
    {
      if (!_disposed)
      {
        if (!_tokenDisposed)
        {
          if (_cancellationTokenSource != null)
            _cancellationTokenSource.Dispose();
          _tokenDisposed = true;
        }
        _disposed = true;
      }
    }
  }
  public abstract class AsyncTaskCodeActivity : AsyncCodeActivity, IDisposable
  {
    private AsyncTaskCodeActivityImplementation _impl = new AsyncTaskCodeActivityImplementation();
    protected override void Cancel(AsyncCodeActivityContext context)
    {
      _impl.Cancel();
      base.Cancel(context);
    }
    protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
    {
      return _impl.BeginExecute(context, ExecuteAsync, callback, state);
    }
    protected override void EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
    {
      _impl.EndExecute(context, result);
    }
    protected abstract Task<Action<AsyncCodeActivityContext>> ExecuteAsync(AsyncCodeActivityContext context, CancellationToken cancellationToken);
    #region IDisposable Support
    private bool _disposed = false; // To detect redundant calls
    protected virtual void Dispose(bool disposing)
    {
      if (!_disposed)
      {
        if (disposing)
        {
        }
        _impl.Dispose(); //structs are not garbage collected so they fit in the unmanaged bucket
        _disposed = true;
      }
    }
    public void Dispose()
    {
      // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
      Dispose(true);
      GC.SuppressFinalize(this);
    }
    #endregion
  }
  public abstract class AsyncTaskCodeActivity<T> : AsyncCodeActivity<T>, IDisposable
  {
    private AsyncTaskCodeActivityImplementation _impl = new AsyncTaskCodeActivityImplementation();
    protected override void Cancel(AsyncCodeActivityContext context)
    {
      _impl.Cancel();
      base.Cancel(context);
    }
    protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
    {
      return _impl.BeginExecute(context, ExecuteAsync, callback, state);
    }
    protected override T EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
    {
      _impl.EndExecute(context, result);
      return Result.Get(context);
    }
    protected abstract Task<Action<AsyncCodeActivityContext>> ExecuteAsync(AsyncCodeActivityContext context, CancellationToken cancellationToken);
    #region IDisposable Support
    private bool _disposed = false; // To detect redundant calls
    protected virtual void Dispose(bool disposing)
    {
      if (!_disposed)
      {
        if (disposing)
        {
        }
        _impl.Dispose(); //structs are not garbage collected so they fit in the unmanaged bucket
        _disposed = true;
      }
    }
    public void Dispose()
    {
      // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
      Dispose(true);
      GC.SuppressFinalize(this);
    }
    #endregion
  }
}using System;
using System.Activities;
using System.Runtime.ExceptionServices;
using System.Threading;
using System.Threading.Tasks;
namespace ClassMathCustomActivity
{
  internal struct AsyncTaskCodeActivityImplementation : IDisposable
  {
    private CancellationTokenSource _cancellationTokenSource;
    private bool _tokenDisposed;
    public void Cancel()
    {
      if (!_tokenDisposed)
      {
        _cancellationTokenSource?.Cancel();
        _cancellationTokenSource?.Dispose();
        _tokenDisposed = true;
      }
    }
    public IAsyncResult BeginExecute(AsyncCodeActivityContext context
      , Func<AsyncCodeActivityContext, CancellationToken, Task<Action<AsyncCodeActivityContext>>> onExecute
      , AsyncCallback callback, object state)
    {
      if (!_tokenDisposed)
      {
        _cancellationTokenSource?.Dispose();
      }
      _cancellationTokenSource = new CancellationTokenSource();
      _tokenDisposed = false;
      TaskCompletionSource<Action<AsyncCodeActivityContext>> taskCompletionSource = new TaskCompletionSource<Action<AsyncCodeActivityContext>>(state);
      Task<Action<AsyncCodeActivityContext>> task = onExecute(context, _cancellationTokenSource.Token);
      var cancellationTokenSource = _cancellationTokenSource;
      task.ContinueWith(t =>
      {
        if (t.IsFaulted)
        {
          taskCompletionSource.TrySetException(t.Exception.InnerException);
        }
        else if (t.IsCanceled || cancellationTokenSource.IsCancellationRequested)
        {
          taskCompletionSource.TrySetCanceled();
        }
        else
        {
          taskCompletionSource.TrySetResult(t.Result);
        }
        callback?.Invoke(taskCompletionSource.Task);
      });
      return taskCompletionSource.Task;
    }
    public void EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
    {
      Task<Action<AsyncCodeActivityContext>> task = (Task<Action<AsyncCodeActivityContext>>)result;
      if (task.IsFaulted)
      {
        ExceptionDispatchInfo.Capture(task.Exception.InnerException).Throw();
      }
      if (task.IsCanceled)
      {
        context.MarkCanceled();
      }
      task.Result?.Invoke(context);
      if (!_tokenDisposed)
      {
        _cancellationTokenSource?.Dispose();
        _tokenDisposed = true;
      }
    }
    private bool _disposed; // To detect redundant calls
    public void Dispose()
    {
      if (!_disposed)
      {
        if (!_tokenDisposed)
        {
          if (_cancellationTokenSource != null)
            _cancellationTokenSource.Dispose();
          _tokenDisposed = true;
        }
        _disposed = true;
      }
    }
  }
  public abstract class AsyncTaskCodeActivity : AsyncCodeActivity, IDisposable
  {
    private AsyncTaskCodeActivityImplementation _impl = new AsyncTaskCodeActivityImplementation();
    protected override void Cancel(AsyncCodeActivityContext context)
    {
      _impl.Cancel();
      base.Cancel(context);
    }
    protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
    {
      return _impl.BeginExecute(context, ExecuteAsync, callback, state);
    }
    protected override void EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
    {
      _impl.EndExecute(context, result);
    }
    protected abstract Task<Action<AsyncCodeActivityContext>> ExecuteAsync(AsyncCodeActivityContext context, CancellationToken cancellationToken);
    #region IDisposable Support
    private bool _disposed = false; // To detect redundant calls
    protected virtual void Dispose(bool disposing)
    {
      if (!_disposed)
      {
        if (disposing)
        {
        }
        _impl.Dispose(); //structs are not garbage collected so they fit in the unmanaged bucket
        _disposed = true;
      }
    }
    public void Dispose()
    {
      // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
      Dispose(true);
      GC.SuppressFinalize(this);
    }
    #endregion
  }
  public abstract class AsyncTaskCodeActivity<T> : AsyncCodeActivity<T>, IDisposable
  {
    private AsyncTaskCodeActivityImplementation _impl = new AsyncTaskCodeActivityImplementation();
    protected override void Cancel(AsyncCodeActivityContext context)
    {
      _impl.Cancel();
      base.Cancel(context);
    }
    protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
    {
      return _impl.BeginExecute(context, ExecuteAsync, callback, state);
    }
    protected override T EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
    {
      _impl.EndExecute(context, result);
      return Result.Get(context);
    }
    protected abstract Task<Action<AsyncCodeActivityContext>> ExecuteAsync(AsyncCodeActivityContext context, CancellationToken cancellationToken);
    #region IDisposable Support
    private bool _disposed = false; // To detect redundant calls
    protected virtual void Dispose(bool disposing)
    {
      if (!_disposed)
      {
        if (disposing)
        {
        }
        _impl.Dispose(); //structs are not garbage collected so they fit in the unmanaged bucket
        _disposed = true;
      }
    }
    public void Dispose()
    {
      // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
      Dispose(true);
      GC.SuppressFinalize(this);
    }
    #endregion
  }
}

変更後のアクティビティは次のようになります。

using System;
using System.Threading.Tasks;
using UiPath.Marketplace.License.Validations;
using System.ComponentModel;
using System.Activities;
using System.Threading;
namespace ClassMathCustomActivity
{
  public class SimpleFormula : AsyncTaskCodeActivity
  {
    [Category("Input")]
    [RequiredArgument]
    public InArgument<double> FirstNumber { get; set; }
    [Category("Input")]
    public InArgument<double> SecondNumber { get; set; }
    [Category("Output")]
    public OutArgument<double> ResultNumber { get; set; }
    protected override async Task<Action<AsyncCodeActivityContext>> ExecuteAsync(AsyncCodeActivityContext context, CancellationToken cancellationToken)
    {
      var firstNumber = FirstNumber.Get(context);
      var secondNumber = SecondNumber.Get(context);
      // check for license after reading input arguments
      #if !DEBUG
                //if your package is MyCompany.MyPackageName.Activities.1.0.0.nupkg
                await Validator.ValidateAsync(context, "MyCompany.MyPackageName.Activities");
      #endif
      return (ctx) =>
      {
        var result = System.Math.Pow(firstNumber + secondNumber, 2);
        ResultNumber.Set(ctx, result);
      };
    }
  }
}using System;
using System.Threading.Tasks;
using UiPath.Marketplace.License.Validations;
using System.ComponentModel;
using System.Activities;
using System.Threading;
namespace ClassMathCustomActivity
{
  public class SimpleFormula : AsyncTaskCodeActivity
  {
    [Category("Input")]
    [RequiredArgument]
    public InArgument<double> FirstNumber { get; set; }
    [Category("Input")]
    public InArgument<double> SecondNumber { get; set; }
    [Category("Output")]
    public OutArgument<double> ResultNumber { get; set; }
    protected override async Task<Action<AsyncCodeActivityContext>> ExecuteAsync(AsyncCodeActivityContext context, CancellationToken cancellationToken)
    {
      var firstNumber = FirstNumber.Get(context);
      var secondNumber = SecondNumber.Get(context);
      // check for license after reading input arguments
      #if !DEBUG
                //if your package is MyCompany.MyPackageName.Activities.1.0.0.nupkg
                await Validator.ValidateAsync(context, "MyCompany.MyPackageName.Activities");
      #endif
      return (ctx) =>
      {
        var result = System.Math.Pow(firstNumber + secondNumber, 2);
        ResultNumber.Set(ctx, result);
      };
    }
  }
}
注:

すべての入力引数を読み取った後すぐに行 24 を実行することが重要です。上の例では、行 20 と 21 を入力引数の読み取りに使用し、行 26 から 30 を出力引数の設定に使用しています。

最後にもう 1 つ重要なことがあります。.nupkg パッケージを作成する際は、Licensing.dll ライブラリがパッケージの内容 (lib フォルダー内) に存在することを確認してください。

よくある質問

これらの変更を実装した後はどうなりますか?

変更を実装し、.nupkg をビルドしたら、Marketplace に提出して公開する必要があります。

ライセンス ファイルをテスト目的で取得できますか?

いいえ。アクティビティをテストする場合、デバッグ用の C# プリプロセッサ ディレクティブ (#if !DEBUG) を使用できます。

顧客はどのようにしてライセンス ファイルを取得するのですか?

ユーザーが購入後、ライセンス .licファイルが生成され、Marketplace で入手できるようになります。ユーザーはこのファイルをダウンロードし、アクティビティを使用するために必要な手順を実行できます。

Was this page helpful?

サポートを受ける
RPA について学ぶ - オートメーション コース
UiPath コミュニティ フォーラム
UiPath ロゴ (白)
信頼とセキュリティ
© 2005-2024 UiPath. All rights reserved.