WESL_UserSettingをC#から参照する

Windows OS 搭載端末をシンクライアント化(キオスク モード化)するようなシェルランチャーを指定する場合などには WESL_UserSetting を使用します。

これを C# の ManagementObject を通じて設定を参照する方法の紹介です。

前提条件として OS の「シェル ランチャー機能」が有効であることが必須です。

この記事内のコードをシェルランチャーが無効の状態で実行した場合以下例外が発生するので注意してください。

// シェル ランチャー機能が無効の場合エラーが発生する
System.Management.ManagementException: 無効なクラスです
   場所 System.Management.ManagementException.ThrowWithExtendedInfo(ManagementStatus errorCode)
   場所 System.Management.ManagementObjectCollection.ManagementObjectEnumerator.MoveNext()
   場所 System.Management.ManagementObjectCollection.get_Count()
   場所 ConsoleApp12.AppMain.Main(String[] args)

実装例

using System;
using System.Management;

var searcher = new ManagementObjectSearcher(
    "root\\standardcimv2\\embedded", "SELECT * FROM WESL_UserSetting");
foreach (ManagementObject obj in searcher.Get())
{
    Console.WriteLine("[SystemProperties]");
    foreach (PropertyData sp in obj.SystemProperties)
    {
        Console.WriteLine($"  {sp.Name}={sp.Value}");
    }
    Console.WriteLine("[Properties]");
    foreach (PropertyData p in obj.Properties)
    {
        Console.WriteLine($"  {p.Name}={p.Value}");
    }
    Console.WriteLine("[IsEnabled]");
    {
        // シェル起動ツールが有効か無効かを示す値を取得する
        ManagementBaseObject inParams = obj.GetMethodParameters("IsEnabled");
        ManagementBaseObject outParams = obj.InvokeMethod("IsEnabled", inParams, null);
        Console.WriteLine($"  Enabled={outParams["Enabled"]}");
    }
    Console.WriteLine("[GetCustomShell]");
    {
        // 既定のシェル起動ツールの構成を取得する
        ManagementBaseObject inParams = obj.GetMethodParameters("GetCustomShell");
        var account = new NTAccount("xxxxx");
        var idRef = account.Translate(typeof(SecurityIdentifier));

        string sid = idRef.Value;
        
        inParams["Sid"] = sid;

        ManagementBaseObject outParams = obj.InvokeMethod("GetCustomShell", inParams, null);
        Console.WriteLine($"  Shell={outParams["Shell"]}");
    }
}

//  [SystemProperties]
//    __GENUS=2
//    __CLASS=WESL_UserSetting
//    __SUPERCLASS=
//    __DYNASTY=WESL_UserSetting
//    __RELPATH=WESL_UserSetting.Sid="***"
//    __PROPERTY_COUNT=5
//    __DERIVATION=System.String[]
//    __SERVER=LASERMEISTER
//    __NAMESPACE=root\standardcimv2\embedded
//    __PATH=\\LASERMEISTER\root\standardcimv2\embedded:WESL_UserSetting.Sid="****"
//  [Properties]
//    CustomReturnCodes=
//    CustomReturnCodesAction=
//    DefaultAction=0
//    Shell=X:\*****\****\***.exe
//    Sid=****
//  [IsEnabled]
//    Enabled=True
//  [GetCustomShell]
//    Shell=X:\*****\****\***.exe

ManagementObjectSearcher で検索するのがポイント。直アクセスしようとすると無効なオブジェクトと例外が出る(もしかしたら取れる指定があるかもしれないが現状不明)

どうやら、IsEnabled はシェル ランチャー機能を有効にしている場合常にtrue、RemoveCustomShell してもいちど SetCustomShell したら Shell に値が残るようなので有効・無効状態を何らかの値で判定することができないようです。

なので RemoveCustomShell する前に SetCustomShell(${sid}, "", null, null) と指定してから RemoveCustomShell すると Shell の有無が判定できるようになるのかもしれませんが確認していません。

参考資料

MSDN: WESL_UserSetting

https://learn.microsoft.com/ja-jp/windows-hardware/customize/enterprise/wesl-usersetting

MSDN: シェル ランチャーを使って Windows クライアント キオスクを作成する

https://learn.microsoft.com/ja-jp/windows/configuration/kiosk-shelllauncher

StackOverflow: Setting Custom Shell via WMI

https://stackoverflow.com/questions/35345116/setting-custom-shell-via-wmi