65.9K
CodeProject 正在变化。 阅读更多。
Home

如何获取进程所有者 ID 和当前用户 SID

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.52/5 (11投票s)

2006年7月16日

CPOL

1分钟阅读

viewsIcon

287780

downloadIcon

3856

本文解释了如何获取进程所有者 ID 和当前用户 SID。

引言

本文档解释了如何获取进程所有者 ID 和当前用户 SID。这在开发终端服务应用程序时很有用。 有两种主要方法可以通过进程 ID (PID) 获取进程所有者 SID:

  1. 使用 Windows 管理工具 (WMI)。 这是获取信息的最慢方法。
  2. 使用 Win32 API。

如何使用 WMI 获取进程所有者 SID

使用 WMI 获取进程所有者 SID 的方法是最短但最慢的方法。 代码非常简单,不需要注释。

public static string GetProcessInfoByPID(int PID, out string User, out string Domain)
{
    User = String.Empty;
    Domain = String.Empty;
    OwnerSID = String.Empty;
    string processname = String.Empty;
    try
    {
        ObjectQuery sq = new ObjectQuery
            ("Select * from Win32_Process Where ProcessID = '" + PID + "'");
        ManagementObjectSearcher searcher = new ManagementObjectSearcher(sq);
        if (searcher.Get().Count == 0)
            return OwnerSID;
        foreach (ManagementObject oReturn in searcher.Get())
        {
            string[] o = new String[2];
            //Invoke the method and populate the o var with the user name and domain
            oReturn.InvokeMethod("GetOwner", (object[])o);

            //int pid = (int)oReturn["ProcessID"];
            processname = (string)oReturn["Name"];
            //dr[2] = oReturn["Description"];
            User = o[0];
            if (User == null)
                User = String.Empty;
            Domain = o[1];
            if (Domain == null)
                Domain = String.Empty;
            string[] sid = new String[1];
            oReturn.InvokeMethod("GetOwnerSid", (object[])sid);
            OwnerSID = sid[0];
     return OwnerSID;
        }
    }
    catch
    {
        return OwnerSID;
    }
    return OwnerSID;
}

如何使用 Win32 API 获取进程所有者 SID

使用 Win32 API 的方法稍微复杂一些,但效果更好(更快)。

public const int TOKEN_QUERY = 0X00000008;

const int ERROR_NO_MORE_ITEMS = 259;

enum TOKEN_INFORMATION_CLASS                           
{
    TokenUser = 1,
    TokenGroups,
    TokenPrivileges,
    TokenOwner,
    TokenPrimaryGroup,
    TokenDefaultDacl,
    TokenSource,
    TokenType,
    TokenImpersonationLevel,
    TokenStatistics,
    TokenRestrictedSids,
    TokenSessionId
}

[DllImport("advapi32")]
static extern bool OpenProcessToken(
    HANDLE ProcessHandle, // handle to process
    int DesiredAccess, // desired access to process
    ref IntPtr TokenHandle // handle to open access token
);

[DllImport("kernel32")]
static extern HANDLE GetCurrentProcess();

[DllImport("advapi32", CharSet = CharSet.Auto)]
static extern bool GetTokenInformation(
    HANDLE hToken,
    TOKEN_INFORMATION_CLASS tokenInfoClass,
    IntPtr TokenInformation,
    int tokeInfoLength,
    ref int reqLength
);

[DllImport("kernel32")]
static extern bool CloseHandle(HANDLE handle);

[DllImport("advapi32", CharSet = CharSet.Auto)]
static extern bool ConvertSidToStringSid(
    IntPtr pSID,
    [In, Out, MarshalAs(UnmanagedType.LPTStr)] ref string pStringSid
);

[DllImport("advapi32", CharSet = CharSet.Auto)]
static extern bool ConvertStringSidToSid(
    [In, MarshalAs(UnmanagedType.LPTStr)] string pStringSid,
    ref IntPtr pSID
);

/// <summary>
/// Collect User Info
/// </summary>
/// <param name="pToken">Process Handle</param>
public static bool DumpUserInfo(HANDLE pToken, out IntPtr SID)
{
    int Access = TOKEN_QUERY;
    HANDLE procToken = IntPtr.Zero;
    bool ret = false;
    SID = IntPtr.Zero;
    try
    {
        if (OpenProcessToken(pToken, Access, ref procToken))
        {
            ret = ProcessTokenToSid(procToken, out SID);
            CloseHandle(procToken);
        }
        return ret;
    }
    catch (Exception err)
    {
        return false;
    }
}

private static bool ProcessTokenToSid(HANDLE token, out IntPtr SID)
{
    TOKEN_USER tokUser;
    const int bufLength = 256;            
    IntPtr tu = Marshal.AllocHGlobal(bufLength);
    bool ret = false;
    SID = IntPtr.Zero;
    try
    {
        int cb = bufLength;
        ret = GetTokenInformation(token, 
                TOKEN_INFORMATION_CLASS.TokenUser, tu, cb, ref cb)
        if (ret)
        {
            tokUser = (TOKEN_USER)Marshal.PtrToStructure(tu, typeof(TOKEN_USER));
            SID = tokUser.User.Sid;
        }
        return ret;
    }
    catch (Exception err)
    {
        return false;
    }
    finally
    {
        Marshal.FreeHGlobal(tu);
    }
}

public static string ExGetProcessInfoByPID
    (int PID, out string SID)//, out string OwnerSID)
{                                                                  
    IntPtr _SID = IntPtr.Zero;                                       
    SID = String.Empty;                                             
    try                                                             
    {                                                                
        Process process = Process.GetProcessById(PID);
        if (DumpUserInfo(process.Handle, out _SID))
        {                                                                    
            ConvertSidToStringSid(_SID, ref SID);
        }
        return process.ProcessName;                                          
    }                                                                           
    catch
    {                                                                           
        return "Unknown";
    }
}

如何获取当前用户 SID

如何使用所有者 SID 信息? 想象一个简单的场景,您需要显示当前用户的进程列表。 这在开发要在终端服务器上使用的应用程序时很常见,在终端服务器上,许多用户使用具有相同名称的应用程序。

private WindowsIdentity _user = WindowsIdentity.GetCurrent();

...

public bool IsCurrentUserProcess(int ProcessID)
{
    string stringSID = String.Empty;
    string process = Utils.ExGetProcessInfoByPID(ProcessID, out stringSID);
    return String.Compare(stringSID, this._user.User.Value, true) == 0);
}

结论

这只是 WMI 可以做的一小部分示例。 不幸的是,WMI 的运行速度比较慢,因此目前没有比使用 Win32 API 更快的方法来获取所需的信息。

参考文献

历史

  • 2006年7月16日:初始发布
© . All rights reserved.