You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C#或PowerShell获取本地机器上所有Microsoft账户及UPN?

获取本地机器所有用户的UPN及Microsoft账户信息(C#/PowerShell)

我需要用C#获取本地机器上所有用户的UPN(用户主体名称)和Microsoft账户信息。目前whoami命令能返回自身的相关信息,但无法获取所有用户的数据:

PS C:\Windows\system32> whoami /upn
my.name@mydomain.com
PS C:\Windows\system32> whoami
corp\my.name

我写的C#代码只能返回「计算机管理」控制台里的本地用户,拿不到Microsoft账户:

var searcher = new System.DirectoryServices.AccountManagement.PrincipalSearcher();
var userPrincipal = new UserPrincipal(new PrincipalContext(ContextType.Machine));
searcher.QueryFilter = userPrincipal;
var results = searcher.FindAll();

用PowerShell的Get-LocalUser也只能看到本地用户,没有Microsoft账户的相关信息:

Name               PrincipalSource
----               ---------------
Administrator                Local
DefaultAccount               Local
Guest                        Local
WDAGUtilityAccount           Local

我还尝试通过注册表Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList里的SID查找用户,但执行Get-localUser -SID S-1-12-1-1111111141-1234567891-3802628514-1659616000时提示用户未找到,即使管理员权限运行也没用。

需要能通过C#或C#可调用的PowerShell方式获取Microsoft账户的方案。


解决方案

方法1:通过Windows API直接获取(C#实现)

Microsoft账户属于「已联网用户」,可以通过NetUserGetInfo和NetUserEnumAPI获取这类用户的信息,包括UPN。以下是封装后的C#代码:

首先定义API相关的结构体和导入:

using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;

public class NetworkUserHelper
{
    private const int USER_INFO_LEVEL_10 = 10;

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    private struct USER_INFO_10
    {
        public string usri10_name;
        public string usri10_full_name;
        // 关键字段:用户主体名称(UPN)
        public string usri10_upn;
        // 省略其他不常用字段,完整结构体可参考MSDN文档
    }

    [DllImport("netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern int NetUserEnum(
        string servername,
        int level,
        int filter,
        out IntPtr bufptr,
        int prefmaxlen,
        out int entriesread,
        out int totalentries,
        IntPtr resume_handle);

    [DllImport("netapi32.dll", SetLastError = true)]
    private static extern int NetApiBufferFree(IntPtr buffer);

    // 用户类型过滤器:本地用户+联网账户(Microsoft账户)
    private const int FILTER_NORMAL_ACCOUNT = 0x00000002;
    private const int FILTER_TEMP_DUPLICATE_ACCOUNT = 0x00000004;

    public static List<UserInfo> GetAllUsersWithUPN()
    {
        var userList = new List<UserInfo>();
        IntPtr bufPtr = IntPtr.Zero;
        int entriesRead;
        int totalEntries;

        try
        {
            // 枚举所有符合条件的用户
            int result = NetUserEnum(null, USER_INFO_LEVEL_10, FILTER_NORMAL_ACCOUNT | FILTER_TEMP_DUPLICATE_ACCOUNT, out bufPtr, -1, out entriesRead, out totalEntries, IntPtr.Zero);

            if (result != 0)
            {
                throw new System.ComponentModel.Win32Exception(result);
            }

            IntPtr currentPtr = bufPtr;
            for (int i = 0; i < entriesRead; i++)
            {
                var userInfo = Marshal.PtrToStructure<USER_INFO_10>(currentPtr);
                userList.Add(new UserInfo
                {
                    Username = userInfo.usri10_name,
                    FullName = userInfo.usri10_full_name,
                    UPN = userInfo.usri10_upn,
                    IsMicrosoftAccount = !string.IsNullOrEmpty(userInfo.usri10_upn) && 
                                        (userInfo.usri10_upn.Contains("@outlook.com") || 
                                         userInfo.usri10_upn.Contains("@live.com") || 
                                         userInfo.usri10_upn.Contains("@hotmail.com") || 
                                         userInfo.usri10_upn.Contains("@microsoft.com"))
                });

                currentPtr = IntPtr.Add(currentPtr, Marshal.SizeOf(typeof(USER_INFO_10)));
            }
        }
        finally
        {
            if (bufPtr != IntPtr.Zero)
            {
                NetApiBufferFree(bufPtr);
            }
        }

        return userList;
    }

    public class UserInfo
    {
        public string Username { get; set; }
        public string FullName { get; set; }
        public string UPN { get; set; }
        public bool IsMicrosoftAccount { get; set; }
    }
}

使用示例:

var allUsers = NetworkUserHelper.GetAllUsersWithUPN();
foreach (var user in allUsers)
{
    Console.WriteLine($"用户名: {user.Username}");
    Console.WriteLine($"全名: {user.FullName}");
    Console.WriteLine($"UPN: {user.UPN}");
    Console.WriteLine($"是否为Microsoft账户: {user.IsMicrosoftAccount}");
    Console.WriteLine("---");
}

方法2:调用PowerShell获取(C#可执行)

通过PowerShell查询Win32_UserAccount类,该类包含本地和联网用户的完整信息:

PowerShell脚本内容:

Get-CimInstance Win32_UserAccount -Filter "LocalAccount=False OR LocalAccount=True" | Select-Object Name, FullName, UserPrincipalName, LocalAccount

C#调用该脚本的代码:

using System.Management.Automation;

public class PowerShellUserHelper
{
    public static void GetUsersViaPowerShell()
    {
        using (var ps = PowerShell.Create())
        {
            ps.AddCommand("Get-CimInstance")
              .AddParameter("ClassName", "Win32_UserAccount")
              .AddParameter("Filter", "LocalAccount=False OR LocalAccount=True");

            ps.AddCommand("Select-Object")
              .AddParameter("Property", new string[] { "Name", "FullName", "UserPrincipalName", "LocalAccount" });

            var results = ps.Invoke();

            foreach (var result in results)
            {
                Console.WriteLine($"用户名: {result.Members["Name"].Value}");
                Console.WriteLine($"全名: {result.Members["FullName"].Value}");
                Console.WriteLine($"UPN: {result.Members["UserPrincipalName"].Value}");
                Console.WriteLine($"是否本地账户: {result.Members["LocalAccount"].Value}");
                Console.WriteLine("---");
            }
        }
    }
}

注意:运行代码需要管理员权限,且项目需引用System.Management.Automation程序集(可通过NuGet安装Microsoft.PowerShell.SDK)。


关键说明

  • Microsoft账户在系统中标记为LocalAccount=False,本地用户为LocalAccount=True。
  • NetUserEnum的FILTER_TEMP_DUPLICATE_ACCOUNT过滤器专门匹配Microsoft账户这类联网账户。
  • 注册表ProfileList中的部分SID对应已登录过的联网用户,但这类用户不会出现在本地用户列表中,需通过WMI或NetAPI获取。

内容的提问来源于stack exchange,提问作者morleyc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 17:18:21