[C#] Windows にログインしている姓名フルネームを取得する

2023-03-26 (日)

Environment.UserName ではなく、姓名のフルネームを取得する方法です。
Win32 API の GetUserNameEx を使用して、高速に取得します。

環境

  • .NET 7.0.200
  • C# 11.0
  • Visual Studio 2022 Version 17.5.0
  • Windows 10 Pro 64bit 22H2 19045.2728

結論

一番高速な Win32 API を使用します。
この方法で求めていたフルネームが取得できない場合は、その他の方法を試してみてください。

using System;
using System.Runtime.InteropServices;

public static string? GetUserDisplayName()
{
    Span<char> buffer = stackalloc char[32];
    var size = buffer.Length;

    var success = NativeMethods.GetUserNameEx(EXTENDED_NAME_FORMAT.NameDisplay, buffer, ref size);
    if (success)
        return buffer[..size].ToString();

    if (buffer.Length <= size)
        return null;

    buffer = stackalloc char[size];
    success = NativeMethods.GetUserNameEx(EXTENDED_NAME_FORMAT.NameDisplay, buffer, ref size);

    return success ? buffer[..size].ToString() : null;
}

public enum EXTENDED_NAME_FORMAT
{
    NameUnknown = 0,
    NameFullyQualifiedDN = 1,
    NameSamCompatible = 2,
    NameDisplay = 3,
    NameUniqueId = 6,
    NameCanonical = 7,
    NameUserPrincipal = 8,
    NameCanonicalEx = 9,
    NameServicePrincipal = 10,
    NameDnsDomain = 12
}

internal partial class NativeMethods
{
    [LibraryImport("secur32.dll", EntryPoint = "GetUserNameExW", StringMarshalling = StringMarshalling.Utf16)]
    [return: MarshalAs(UnmanagedType.Bool)]
    internal static partial bool GetUserNameEx(EXTENDED_NAME_FORMAT nameFormat, Span<char> userName, ref int userNameSize);
}

その他の方法

以下の方法は実行速度が遅いため、使用しないことにしました。

方法1. System.DirectoryServices.DirectoryEntry を使用する

NuGet からインストールが必要です。
NuGet Gallery | System.DirectoryServices.AccountManagement

using System;
using System.DirectoryServices;

public static string? GetFullName()
{
    var domain = Environment.UserDomainName;
    var name = Environment.UserName;
    var path = $"WinNT://{domain}/{name}";

    using var entry = new DirectoryEntry(path);
    return entry.Properties["FullName"].Value?.ToString();
}

方法2. System.DirectoryServices.AccountManagement.UserPrincipal を使用する

Principal.DisplayName プロパティ (System.DirectoryServices.AccountManagement) | Microsoft Learn

NuGet からインストールが必要です。
NuGet Gallery | System.DirectoryServices.AccountManagement

using System.DirectoryServices.AccountManagement;

public static string? GetUserDisplayName()
{
    var userPrincipal = UserPrincipal.Current;
    return userPrincipal.DisplayName;
}

方法3. WMI (Windows Management Instrumentation) を使用する

Win32_UserAccount クラス - Win32 apps | Microsoft Learn

NuGet からインストールが必要です。
NuGet Gallery | System.Management

using System;
using System.Management;

public static string? GetUserFullName()
{
    var domain = Environment.UserDomainName;
    var name = Environment.UserName;
    var queryString = $"SELECT FullName FROM Win32_UserAccount WHERE Domain ='{domain}' AND Name = '{name}'";

    var query = new ManagementObjectSearcher(queryString);
    var collection = query.Get();
    foreach (var o in collection)
    {
        var mo = (ManagementObject)o;
        return mo["FullName"].ToString();
    }

    return null;
}

感謝

2023-03-26 (日)