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#制作文字转换成声音程序 前言 随着人工智能的发展,语音技术的应用越来越广泛,其中一项核心技术就是文字转语音。本文将教你如何用C#制作一个文字转语音程序。 准备工作 在开始编写代码之前,我们需要安装.NET框架(如果还未安装的话),推荐安装.NET Framework 4.0及以上版本。 下载地址:https://dotnet.microsoft…

    C# 2023年6月6日
    00
  • C#中Hash table的一些操作方法讲解

    哈希表(Hash table)是一种常见的数据结构,用于存储键值对(key-value pairs)。在C#中,可以使用System.Collections.Hashtable类来创建一个哈希表对象,它提供了各种方法来管理键值对。 以下是一些C#中哈希表的操作方法的详细讲解: 创建哈希表对象 可以通过以下代码来创建一个哈希表对象: Hashtable has…

    C# 2023年5月31日
    00
  • WinForm实现鼠标拖动控件跟随效果

    为了实现WinForm中的鼠标拖动控件跟随效果,我们需要使用下述步骤: 1. 获取鼠标位置 鼠标在界面上移动时,我们需要获取其当前位置。可以通过下面的代码来获取: private void panel1_MouseMove(object sender, MouseEventArgs e) { Point point = Control.MousePositi…

    C# 2023年6月1日
    00
  • ASP.NET将Session保存到数据库中的方法

    需要将 ASP.NET 的 Session 保存到数据库中,可以通过如下步骤实现: 步骤1:创建 SQL 数据库表 首先需要在 SQL Server 中创建一个用于存储 Session 数据的表,该表至少需要三个字段: SessionId(nvarchar类型):Session的唯一标识符。 Expires(datetime类型):Session的过期时间。…

    C# 2023年5月31日
    00
  • C#装箱和拆箱操作实例分析

    C#装箱和拆箱操作实例分析 装箱(Boxing) 装箱指的是将值类型转换为对象类型,即将一个值类型的数据放到一个堆分配的对象中。我们知道,值类型的数据是直接存储在内存栈空间中的,而对象类型的数据则是存储在堆空间中的。因此,当我们需要将一个值类型作为对象类型来处理时,就需要进行装箱操作。 下面是一个装箱操作的示例: int i = 123; object ob…

    C# 2023年6月7日
    00
  • c# 实现发送邮件到指定邮箱

    C#实现发送邮件到指定邮箱的攻略可以分为以下几个步骤: 导入命名空间 在C#中,我们需要使用System.Net.Mail这个命名空间来实现邮件发送功能,因此需要在开头添加该命名空间的引用。 using System.Net.Mail; 配置SMTP服务器信息 在使用C#发送邮件前,我们需要先配置SMTP服务器的相关信息,包括SMTP服务器地址、端口号、用户…

    C# 2023年6月1日
    00
  • C#使用FileSystemWatcher控件实现的文件监控功能示例

    在C#中,可以使用FileSystemWatcher控件实现文件监控功能。FileSystemWatcher控件可以监视指定目录中的文件和子目录的更改,并在发生更改时引发事件。本文将提供详解如何使用FileSystemWatcher控件实现文件监控功能的完整攻略,包括如何创建FileSystemWatcher控件、如何设置监视目录和文件类型、如何处理File…

    C# 2023年5月15日
    00
  • .NET中的MassTransit分布式应用框架详解

    以下是“.NET中的MassTransit分布式应用框架详解”的完整攻略: 什么是MassTransit MassTransit是一个开源的分布式应用框架,用于构建可扩展的、高可用的、松耦合的分布式应用程序。它基于消息传递模式,支持多种消息传递协议,例如RabbitMQ、Azure Service Bus、Amazon SQS等。 MassTrans的核心概…

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