【C#】IppAttributeError クラス解説|IPP属性エラーの理由・取得方法・実装例

当ページのリンクには広告が含まれています。
IppAttributeError
目次

IppAttributeErrorとは何か

ppAttributeError は、IPP プリンターやプリンター ジョブに対して属性(document-format-defaultやprinter-resolution-defaultなど)を設定する際に、個々の属性レベルで発生したエラーを表すクラスです。

あわせて読みたい
IppAttributeError クラス (Windows.Devices.Printers) - Windows apps プリンターまたはプリンター ジョブの属性セット操作のエラーを表します。

典型的には、次のような流れで使われます。

  1. IppPrintDevice.SetPrinterAttributes()やSetJobAttributes()を呼び出す
  2. 戻り値からSucceededフラグを確認する
  3. falseの場合、AttributeErrorsプロパティにDictionary<string, IppAttributeError>のような形でエラー詳細が時入っている。
  4. 各IppAttributeErrorを見て、
    ・なぜ失敗したか
    ・どの値がサポートされていなかったか
    ・追加のエラー情報
    を確認して、ログ出力やフォールバックに利用する

MS のデザインガイドにあるサンプルコードも、このクラスを使って属性ごとのエラーを処理しています。

あわせて読みたい
印刷サポート アプリ v1 および v2 設計ガイド - Windows drivers デバイスの v1 および v2 印刷サポート アプリ (PSA) を実装しているプリンター OEM および IHV のガイダンスと例を示します。

どこで IppAttributeError が取れるのか

IppAttributeError 自体はnewして直接使うものではなく、SetXXXAttributesの結果オブジェクトから辿る形で取得します。

代表的なAPI

  • IppPrintDevice.SetPrinterAttributes(IDictionary<string, IppAttributeValue>)
  • IppPrintDevice.SetPrinterAttributesFromBuffer(IBuffer)
  • IppPrintDevice.SetJobAttributes()

これらは「成功/失敗」と、失敗したときのAttributeErrorを返します。

プロパティ

ExtendedError プロパティ

public Exception ExtendedError { get; }

このプロパティは、プリンターまたはプリンタージョブ属性セット操作エラーに関する拡張情報を取得します。
リンク

また以下のような特徴があります。

  • 実際の C# からは System.Exception として見えます。
  • 通常は Reason や GetUnsupportedValues() だけでは分からない、より低レベルなエラー情報(HRESULT や詳細メッセージ)を含みます。
  • 例えば、IPP レスポンスのパースエラーや通信エラーなど、単純な「値がサポートされない」以外のケースで役立ちます。

使い方の例

foreach (var kvp in result.AttributeErrors)
{
    string attributeName = kvp.Key;
    IppAttributeError error = kvp.Value;

    Log($"Attribute '{attributeName}' failed. Reason={error.Reason}");

    if (error.ExtendedError != null)
    {
        Log($"ExtendedError: {error.ExtendedError.HResult:X8} {error.ExtendedError.Message}");
    }
}

ExtendedError の内容はプリンターやドライバー実装に依存するので、

「ユーザー表示」よりも「開発/サポート用ログ」に向いています。

Reasonプロパティ

public IppAttributeErrorReason Reason { get; }

プリンターまたはプリンタージョブに対して属性セット操作が失敗した理由を示す値
リンク

IppAttributeErrorReasonは列挙体で代表的なものは公開されているサンプルコードから読み取ることができます。

  • AttributeValuesNotSupported
    • 指定した値の一部がプリンターでサポートされていない場合
    • このとき GetUnsupportedValues() で具体的な値を取得可能
  • AttributeNotSettable
    • その属性は読み取り専用、あるいは現在の状態では変更不可
  • AttributeNotSupported
    • その属性自体がプリンターでサポートされていない
  • RequestEntityTooLarge
    • 送ったデータ(値の数・サイズなど)が大きすぎる
  • ConflictingAttributes
    • 他の属性と矛盾がある(例: 用紙サイズと解像度の組み合わせなど)

使い方の例

foreach (var attributeError in result.AttributeErrors)
{
    var attributeName = attributeError.Key;
    var error = attributeError.Value;

    switch (error.Reason)
    {
        case IppAttributeErrorReason.AttributeValuesNotSupported:
            var unsupportedValues = error.GetUnsupportedValues();
            LogUnsupportedValues(attributeName, unsupportedValues);
            break;

        case IppAttributeErrorReason.AttributeNotSettable:
            LogAttributeNotSettable(attributeName);
            break;

        case IppAttributeErrorReason.AttributeNotSupported:
            LogAttributeNotSupported(attributeName);
            break;

        case IppAttributeErrorReason.RequestEntityTooLarge:
            LogRequestEntityTooLarge(attributeName);
            break;

        case IppAttributeErrorReason.ConflictingAttributes:
            LogConflictingAttributes(attributeName);
            break;

        default:
            LogUnknownReason(attributeName, error.Reason);
            break;
    }
}

このReasonをベースに、「ユーザーへメッセージを出すか/サイレントにフォールバックするか」などのポリシーを決めるイメージです。

メソッド

GetUnsupportedValues()

public IReadOnlyList<IppAttributeValue> GetUnsupportedValues();

現在のプリンターまたはプリンタージョブでサポートされていない属性の一覧を取得します。
リンク

  • 主に Reason == AttributeValuesNotSupported のときに意味を持ちます
  • 返ってくるのは IppAttributeValue のリストです。値の種類は IppAttributeValue.Kind によって異なります(Integer, Keyword, Boolean など)。
  • エラーの原因となった「どの値」がダメだったのかを特定できます。

基本的な使い方

if (error.Reason == IppAttributeErrorReason.AttributeValuesNotSupported)
{
    var unsupportedValues = error.GetUnsupportedValues();

    foreach (var value in unsupportedValues)
    {
        switch (value.Kind)
        {
            case IppAttributeValueKind.Keyword:
                foreach (var keyword in value.GetKeywordArray())
                {
                    Log($"Unsupported keyword for {attributeName}: {keyword}");
                }
                break;

            case IppAttributeValueKind.Integer:
                foreach (var intVal in value.GetIntegerArray())
                {
                    Log($"Unsupported integer for {attributeName}: {intVal}");
                }
                break;

            // 必要に応じて他の Kind も処理
        }
    }
}

よくあるパターン

  • 解像度(printer-resolution-default)で 2400dpi を指定したが、プリンターは 600/1200dpi しかサポートしていない
  • メディアサイズやカスタムサイズがサポート範囲外

こういったときに、GetUnsupportedValues() で NG 値を列挙し、

「OK な値」に置き換えて再度 SetPrinterAttributes する、といったリトライロジックが組めます。

実践的なコード例

MSのデザインガイドに載っているC#のサンプルコードにコメントを補いながらIppAttributeErrorの使い方を整理してみます。

int defaultResolutionX = 1200;
int defaultResolutionY = 1200;
string pdlFormat = "image/pwg-raster";

private void SetPrinterAttributes()
{
    var attributes = new Dictionary<string, IppAttributeValue>();

    // 例: デフォルト PDL フォーマットを設定
    attributes.Add(
        "document-format-default",
        IppAttributeValue.CreateKeyword(this.pdlFormat));

    // 例: デフォルト解像度を設定
    var resolution = new IppResolution(
        this.defaultResolutionX,
        this.defaultResolutionY,
        IppResolutionUnit.DotsPerInch);

    attributes.Add(
        "printer-resolution-default",
        IppAttributeValue.CreateResolution(resolution));

    // 実際にプリンターに属性をセット
    var result = this.printer.SetPrinterAttributes(attributes);

    // 全体として成功したか?
    if (!result.Succeeded)
    {
        // 属性ごとのエラーを列挙
        foreach (var attributeError in result.AttributeErrors)
        {
            var attributeName = attributeError.Key;
            var error = attributeError.Value;

            switch (error.Reason)
            {
                case IppAttributeErrorReason.AttributeValuesNotSupported:
                    // サポートされない値の一覧を取得
                    var unsupportedValues = error.GetUnsupportedValues();
                    LogUnSupportedValues(attributeName, unsupportedValues);
                    break;

                case IppAttributeErrorReason.AttributeNotSettable:
                    LogAttributeNotSettable(attributeName);
                    break;

                case IppAttributeErrorReason.AttributeNotSupported:
                    LogAttributeNotSupported(attributeName);
                    break;

                case IppAttributeErrorReason.RequestEntityTooLarge:
                    LogRequestEntityTooLarge(attributeName);
                    break;

                case IppAttributeErrorReason.ConflictingAttributes:
                    LogConflictingAttributes(attributeName);
                    break;
            }

            // ExtendedError があれば開発用ログに出す
            if (error.ExtendedError != null)
            {
                LogExtendedError(attributeName, error.ExtendedError);
            }
        }
    }
}

このように、

  • result.Succeeded … 全体成功/失敗
  • result.AttributeErrors[attributeName] … 属性ごとのエラー詳細
  • IppAttributeError.Reason … 失敗理由の分類
  • IppAttributeError.GetUnsupportedValues() … 実際にダメだった値
  • IppAttributeError.ExtendedError … 低レベルな追加情報

という多段構造でエラー情報が取得できるようになっています。

設計上のポイント・ベストプラクティス

最後に、PSA 実装で IppAttributeError を活用する際のポイントをまとめます。

  1. 「落ちない」実装にする
    • SetPrinterAttributes / SetJobAttributes は失敗しても例外ではなく結果オブジェクトで返ってくる前提です。
    • IppAttributeError をしっかり見て、UI 上は「警告表示+安全なデフォルトに戻す」など、ユーザーに優しいふるまいを心がけます。
  2. Reason でエラー分類し、メッセージや自動修正ポリシーを分ける
    • AttributeNotSupported → UI からその機能を非表示にする・グレーアウトする
    • AttributeNotSettable → 設定画面では編集不可にする
    • AttributeValuesNotSupported → 最も近いサポート値へのフォールバック+ユーザーへ説明
  3. GetUnsupportedValues で「ダメだった値」を特定
    • ログに残すだけでなく、「指定した 2400dpi はサポートされていないため、1200dpi に変更しました」のようにユーザーへフィードバックすることも可能です。
  4. ExtendedError は「開発/検証フェーズでフル活用」
    • 実機テスト時に ExtendedError をログに出しておくと、特定の機種でのみ起きる微妙な IPP 実装差異を調査しやすくなります。

このようにIppAttributeErrorは、

「IPP 属性をセットしたときの“属性ごとのエラー詳細オブジェクト”

+失敗理由の分類(Reason)+具体的な NG 値(GetUnsupportedValues)」

として捉えておくとわかりやすいと思います。

tenjiprogramming
20代エンジニア。
メインで使用している言語はJava/JavaScript/TyoeScript/react/C言語
AWSなどクラウド周りも経験あり。
楽しいをモットーに記事を書いています。
Noteではサンプルコード付きのゲームの作り方など様々な内容を公開しています。
そちらも是非ご覧ください!
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA


目次