C# 获取系统进程的用户名

下面是关于如何用C#获取系统进程的用户名的完整攻略。

1. 获取系统进程列表

首先,我们需要获取当前系统中的进程列表。可以使用Process类的GetProcesses()方法来完成这个任务。该方法会返回一个Process类型的数组,其中每个元素表示一个系统进程。

下面是一个简单的示例代码:

Process[] processlist = Process.GetProcesses();
foreach (Process process in processlist)
{
    Console.WriteLine("Process: {0}  ID: {1}", process.ProcessName, process.Id);
}

上述代码将会打印出系统中当前运行的每个进程的名称和ID。

2. 获取进程的安全描述符

然后,我们需要获取每个进程的安全描述符,以便进一步获得进程所属的用户或组。

首先,我们需要声明必要的API函数和结构体。这些函数和结构体在System.DiagnosticsSystem.Security.Principal命名空间下都有定义。

using System.Diagnostics;
using System.Security.Principal;
using System.Runtime.InteropServices;

public static class ProcessUtils
{
    // 获取进程的安全描述符
    [DllImport("kernel32.dll")]
    public static extern bool OpenProcessToken(IntPtr ProcessHandle, uint DesiredAccess, out IntPtr TokenHandle);

    // 获得普通用户的SID
    [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
    public static extern bool ConvertSidToStringSid(IntPtr pSid, out string strSid);

    // 根据指定的用户名和计算机名获取用户的SID
    public static SecurityIdentifier GetSid(string userName, string computerName)
    {
        NTAccount account = new NTAccount(computerName, userName);
        return (SecurityIdentifier)account.Translate(typeof(SecurityIdentifier));
    }
}

接下来,我们可以使用OpenProcessToken函数通过进程句柄获取进程的安全描述符。此函数的输入参数DesiredAccess将指定所需的访问级别。在本例中,我们需要读取进程的安全描述符,因此我们将使用TOKEN_QUERY。目前需要使用以下常量:

const uint TOKEN_QUERY = 0x0008;
const int ERROR_NO_TOKEN = 1008;
const int ERROR_INSUFFICIENT_BUFFER = 122;

下面是示例代码:

// 获得进程的安全描述符
IntPtr tokenHandle;
if (OpenProcessToken(process.Handle, TOKEN_QUERY, out tokenHandle))
{
    try
    {
        // 获取安全描述符的长度
        int tokenInfLength = 0;
        if (!GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenUser, IntPtr.Zero, 0, out tokenInfLength) && Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
        {
            IntPtr tokenInformation = Marshal.AllocHGlobal(tokenInfLength);
            try
            {
                // 获取安全描述符
                bool success = GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenUser, tokenInformation, tokenInfLength, out tokenInfLength);
                if (success)
                {
                    // 获取安全描述符中的用户SID
                    TOKEN_USER tokenUser = (TOKEN_USER)Marshal.PtrToStructure(tokenInformation, typeof(TOKEN_USER));
                    string sidString;
                    if (ConvertSidToStringSid(tokenUser.User.Sid, out sidString))
                    {
                        SecurityIdentifier sid = new SecurityIdentifier(sidString);
                        Console.WriteLine("Process {0} belongs to user {1}", process.ProcessName, sid.Translate(typeof(NTAccount)).Value);
                    }
                    else
                    {
                        Console.WriteLine("Error converting SID to string: {0}", Marshal.GetLastWin32Error());
                    }
                }
                else
                {
                    Console.WriteLine("Error getting token information: {0}", Marshal.GetLastWin32Error());
                }
            }
            finally
            {
                Marshal.FreeHGlobal(tokenInformation);
            }
        }
        else
        {
            Console.WriteLine("Error getting token information: {0}", Marshal.GetLastWin32Error());
        }
    }
    finally
    {
        CloseHandle(tokenHandle);
    }
}
else
{
    Console.WriteLine("Error opening process token: {0}", Marshal.GetLastWin32Error());
}

上面这段代码将会获取进程的安全描述符,并将其转换为可读的SecurityIdentifier,然后将其转换为用户帐户。

3. 示例代码

最后,让我们来看一下两个具体的样例代码。第一个示例代码将遍历系统中的所有进程,并输出每个进程所属的用户。

Process[] processlist = Process.GetProcesses();
foreach (Process process in processlist)
{
    IntPtr tokenHandle;
    if (OpenProcessToken(process.Handle, TOKEN_QUERY, out tokenHandle))
    {
        try
        {
            int tokenInfLength = 0;
            if (!GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenUser, IntPtr.Zero, 0, out tokenInfLength) && Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
            {
                IntPtr tokenInformation = Marshal.AllocHGlobal(tokenInfLength);
                try
                {
                    bool success = GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenUser, tokenInformation, tokenInfLength, out tokenInfLength);
                    if (success)
                    {
                        TOKEN_USER tokenUser = (TOKEN_USER)Marshal.PtrToStructure(tokenInformation, typeof(TOKEN_USER));
                        string sidString;
                        if (ConvertSidToStringSid(tokenUser.User.Sid, out sidString))
                        {
                            SecurityIdentifier sid = new SecurityIdentifier(sidString);
                            Console.WriteLine("Process {0} belongs to user {1}", process.ProcessName, sid.Translate(typeof(NTAccount)).Value);
                        }
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(tokenInformation);
                }
            }
        }
        finally
        {
            CloseHandle(tokenHandle);
        }
    }
}

第二个示例代码则是查找某个指定进程的用户。在这个样例中,我们将从命令行接收一个进程名称,然后输出它所属的用户。

string processName = args.Length > 0 ? args[0] : null;
if (processName != null)
{
    Process[] processlist = Process.GetProcessesByName(processName);
    if (processlist.Length > 0)
    {
        Process process = processlist[0];
        IntPtr tokenHandle;
        if (OpenProcessToken(process.Handle, TOKEN_QUERY, out tokenHandle))
        {
            try
            {
                int tokenInfLength = 0;
                if (!GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenUser, IntPtr.Zero, 0, out tokenInfLength) && Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
                {
                    IntPtr tokenInformation = Marshal.AllocHGlobal(tokenInfLength);
                    try
                    {
                        bool success = GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenUser, tokenInformation, tokenInfLength, out tokenInfLength);
                        if (success)
                        {
                            TOKEN_USER tokenUser = (TOKEN_USER)Marshal.PtrToStructure(tokenInformation, typeof(TOKEN_USER));
                            string sidString;
                            if (ConvertSidToStringSid(tokenUser.User.Sid, out sidString))
                            {
                                SecurityIdentifier sid = new SecurityIdentifier(sidString);
                                Console.WriteLine("Process {0} belongs to user {1}", process.ProcessName, sid.Translate(typeof(NTAccount)).Value);
                            }
                        }
                    }
                    finally
                    {
                        Marshal.FreeHGlobal(tokenInformation);
                    }
                }
            }
            finally
            {
                CloseHandle(tokenHandle);
            }
        }
        else
        {
            Console.WriteLine("Error opening process token: {0}", Marshal.GetLastWin32Error());
        }
    }
    else
    {
        Console.WriteLine("Process {0} not found.", processName);
    }
}
else
{
    Console.WriteLine("Please specify a process name.");
}

这个样例代码将会查找指定进程名的进程,然后输出它所属的用户。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C# 获取系统进程的用户名 - Python技术站

(0)
上一篇 2023年6月7日
下一篇 2023年6月7日

相关文章

  • C#调用微信接口的相关代码

    关于C#调用微信接口的代码,我们可以通过微信官方提供的开发者文档来进行了解和学习。具体流程可以按照以下步骤操作: 1.注册微信开放平台账号并创建应用 在微信公众平台官网上注册开放平台账号,并创建一个应用。在创建应用时,需要提供应用名称、应用类型和应用描述。同时,需要获取到应用的AppID和AppSecret,这是后续调用微信接口时所必须要使用到的。 2.使用…

    C# 2023年5月31日
    00
  • Android编程实现google消息通知功能示例

    这里是关于“Android编程实现google消息通知功能示例”的完整攻略。 什么是Google消息通知功能? Google消息通知是Android系统提供的一种通知机制,通过它可以在屏幕上显示异步事件的消息提醒。这些消息会在事件发生时,通过通知栏等界面进行展示,从而让用户更方便快捷地查看和处理各种消息。 Google消息通知功能实现步骤 在Android中…

    C# 2023年6月6日
    00
  • C#利用Windows自带gdi32.dll实现抓取屏幕功能实例

    下面是C#利用Windows自带gdi32.dll实现抓取屏幕功能的完整攻略: 第一步:导入gdi32.dll库 要使用gdi32.dll中的函数,我们需要手动导入该库,首先需要在原生方法前加入[DllImport(“gdi32.dll”)],以便让.NET框架能够找到该库。然后需要在代码开头添加命名空间:using System.Runtime.Inter…

    C# 2023年5月31日
    00
  • C#简单爬虫案例分享

    下面我将为你详细讲解有关“C#简单爬虫案例分享”的完整攻略。 1. 爬虫原理 爬虫是指程序自动化地访问互联网资源并提取信息。其基本原理是通过HTTP请求,获取服务器返回的HTML页面,并解析其中的内容进行采集、处理和格式化。通常,爬虫程序的实现过程可以分为以下几个步骤: 发送HTTP请求,并获取服务器返回的HTML页面。 解析HTML页面中的内容,识别其中的…

    C# 2023年6月1日
    00
  • asp.net Split分割字符串的方法

    当使用ASP.NET进行开发时,分割字符串是一项非常常见的任务。ASP.NET中的Split()方法是一种简单有效的将字符串分成单独纯文本段的方法。 Split()方法的基本用法 Split()方法可以用于按照指定的分隔符将一个字符串分割成多个子串。其基本用法如下所示: string str = "apple, banana, cherry, da…

    C# 2023年6月3日
    00
  • asp.net创建位图生成验证图片类(验证码类)

    下面是“ASP.NET创建位图生成验证图片类(验证码类)”的完整攻略: 什么是验证码 验证码是为了防止机器人恶意攻击而设置的一种机制。它一般是一张由数字或字母组成的随机图片,用户需要在文本框中输入正确的验证码,才能通过验证并继续执行后续的操作。所以,验证码一般被用于用户登录、注册、评论等操作中,以保障网站安全。 创建验证码类 1. 准备工作 准备一个名为“V…

    C# 2023年5月31日
    00
  • Win Form 的 Splitter 使用心得与技巧

    Win Form 中的 Splitter 控件可以很方便地实现分割窗口的效果,常用于界面布局、调整窗口尺寸等场景。在使用 Splitter 过程中,我们可以注意以下几点心得与技巧。 界面布局 当我们需要在一个窗口中分割出两个或多个区域时,可以使用 Splitter 控件。首先在窗口上放置一个 Splitter 控件,并将 Dock 属性设置为 Left、Ri…

    C# 2023年6月7日
    00
  • asp.net Execl的添加,更新操作实现代码

    接下来我会详细讲解如何在ASP.NET中进行Excel的添加和更新操作。 准备工作 在进行Excel操作之前,我们需要安装EPPlus包,它是一个免费的开源库,可以让我们在ASP.NET中轻松地操作Excel文件。在Visual Studio中,可以通过NuGet包管理器安装EPPlus。 添加Excel文件 要向Excel文件中添加数据,我们需要使用EPP…

    C# 2023年5月31日
    00
合作推广
合作推广
分享本页
返回顶部