Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何获取当前用户的唯一ID';windows-c中的s登录会话#_C#_.net_Windows - Fatal编程技术网

C# 如何获取当前用户的唯一ID';windows-c中的s登录会话#

C# 如何获取当前用户的唯一ID';windows-c中的s登录会话#,c#,.net,windows,C#,.net,Windows,我需要获取唯一标识当前windows用户登录会话的值。这适用于winforms应用程序,而不是ASP.NET。我将从多个进程中检索此文件,因此在同一登录会话中检索时需要返回相同的值。它只需要在所有用户会话期间(例如,直到下次重新启动机器)在当前机器上是唯一的 我认为这是正确的事情,但似乎有点难以挽回。有没有其他更简单的方法 我将使用ID包含在命名管道服务的地址中,以便在计算机上运行的两个进程之间进行通信。我希望包含登录Id,以避免多个用户登录时发生冲突,可能包括同一用户的多个会话。如果我理解正确

我需要获取唯一标识当前windows用户登录会话的值。这适用于winforms应用程序,而不是ASP.NET。我将从多个进程中检索此文件,因此在同一登录会话中检索时需要返回相同的值。它只需要在所有用户会话期间(例如,直到下次重新启动机器)在当前机器上是唯一的

我认为这是正确的事情,但似乎有点难以挽回。有没有其他更简单的方法


我将使用ID包含在命名管道服务的地址中,以便在计算机上运行的两个进程之间进行通信。我希望包含登录Id,以避免多个用户登录时发生冲突,可能包括同一用户的多个会话。

如果我理解正确,您可以生成一个


要确保每个用户会话都有一个唯一的id,我想您必须使用您提到的痛苦方法-。

获取会话id的最简单方法是查看属性:

System.Diagnostics.Process.GetCurrentProcess().SessionId
该值与GetTokenInformation(…,TokenSessionId,…)返回的值相同

注意:您应该记住的一点是,会话Id不是。 例如,在Win7上,在同一会话中由同一用户启动的提升进程将具有不同的LogonId(从copmaring到非提升的LogonId),但将具有相同的SessionId。 即使runniung非提升进程使用RunAs显式指定同一用户的凭据,也会创建新的登录Sesison Id。 例如,当您映射网络驱动器时,这种行为具有意义。自Vista以来,具有一个标记LogonId的进程将不会看到与另一个LogonId映射的网络目录,即使进程在同一会话中并在同一用户下运行

以下是您可以在不同会话/凭据上启动的示例应用程序,以查看差异:

using System;
using System.Runtime.InteropServices;

namespace GetCurrentSessionId
{
    class Program
    {

        enum TokenInformationClass
        {
            TokenUser = 1,
            TokenGroups,
            TokenPrivileges,
            TokenOwner,
            TokenPrimaryGroup,
            TokenDefaultDacl,
            TokenSource,
            TokenType,
            TokenImpersonationLevel,
            TokenStatistics,
            TokenRestrictedSids,
            TokenSessionId,
            TokenGroupsAndPrivileges,
            TokenSessionReference,
            TokenSandBoxInert,
            TokenAuditPolicy,
            TokenOrigin
        }

        enum TokenType
        {
            TokenPrimary = 1, 
            TokenImpersonation
        }

        enum SecurityImpersonationLevel 
        { 
            SecurityAnonymous,
            SecurityIdentification,
            SecurityImpersonation,
            SecurityDelegation
        }

        [StructLayout(LayoutKind.Sequential)]
        struct TokenStatistics
        {
            public Int64 TokenId;
            public Int64 AuthenticationId;
            public Int64 ExpirationTime;
            public TokenType TokenType;
            public SecurityImpersonationLevel ImpersonationLevel;
            public Int32 DynamicCharged;
            public Int32 DynamicAvailable;
            public Int32 GroupCount;
            public Int32 PrivilegeCount;
            public Int64 ModifiedId;
        }

        struct TokenOrigin
        {
            public Int64 OriginatingLogonSession;
        }

        [DllImport("advapi32.dll", EntryPoint = "GetTokenInformation", SetLastError = true)]
        static extern bool GetTokenInformation(
            IntPtr tokenHandle,
            TokenInformationClass tokenInformationClass,
            IntPtr tokenInformation,
            int tokenInformationLength,
            out int ReturnLength);

        public const int ERROR_INSUFFICIENT_BUFFER = 0x7a;

        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Session Id: {0}", System.Diagnostics.Process.GetCurrentProcess().SessionId);

                IntPtr tokenInfo;
                bool result;
                int infoSize;

                IntPtr hToken = System.Security.Principal.WindowsIdentity.GetCurrent().Token;

                result = GetTokenInformation(hToken, TokenInformationClass.TokenStatistics, IntPtr.Zero, 0, out infoSize);
                if (!result && Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
                {
                    tokenInfo = Marshal.AllocHGlobal(infoSize);
                    result = GetTokenInformation(hToken, TokenInformationClass.TokenStatistics, tokenInfo, infoSize, out infoSize);
                    if (result)
                    {
                        TokenStatistics tokenStats = (TokenStatistics)Marshal.PtrToStructure(tokenInfo, typeof(TokenStatistics));
                        Console.WriteLine("LogonId: 0x{0:X16}", tokenStats.AuthenticationId);
                    }
                    else
                    {
                        Console.Error.WriteLine("LogonId: FAILED with 0x{0:X08}", Marshal.GetLastWin32Error());
                    }
                    Marshal.FreeHGlobal(tokenInfo);
                }
                else
                {
                    Console.Error.WriteLine("LogonId: FAILED with 0x{0:X08}", Marshal.GetLastWin32Error());
                }


                tokenInfo = Marshal.AllocHGlobal(sizeof (Int32));
                result = GetTokenInformation(hToken, TokenInformationClass.TokenSessionId, tokenInfo, sizeof (Int32), out infoSize);
                if (result)
                {
                    int tokenSessionId = Marshal.ReadInt32(tokenInfo);
                    Console.WriteLine("TokenSessionId: {0}", tokenSessionId);
                }
                else
                {
                    Console.Error.WriteLine("TokenSessionId: FAILED with 0x{0:X08}", Marshal.GetLastWin32Error());
                }

                Marshal.FreeHGlobal(tokenInfo);


                result = GetTokenInformation(hToken, TokenInformationClass.TokenOrigin, IntPtr.Zero, 0, out infoSize);
                if (!result && Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
                {
                    tokenInfo = Marshal.AllocHGlobal(infoSize);
                    result = GetTokenInformation(hToken, TokenInformationClass.TokenOrigin, tokenInfo, infoSize, out infoSize);
                    if (result)
                    {
                        TokenOrigin tokenOrigin = (TokenOrigin) Marshal.PtrToStructure(tokenInfo, typeof (TokenOrigin));
                        Console.WriteLine("OriginatingSessionId: 0x{0:X16}", tokenOrigin.OriginatingLogonSession);
                    }
                    else
                    {
                        Console.WriteLine("OriginatingSessionId: FAILED with 0x{0:X08}", Marshal.GetLastWin32Error());
                    }
                    Marshal.FreeHGlobal(tokenInfo);
                }
                else
                {
                    Console.WriteLine("OriginatingSessionId: FAILED with 0x{0:X08}", Marshal.GetLastWin32Error());
                }

                Console.WriteLine("Press any key...");
                Console.ReadKey();

            }
            catch (Exception ex)
            {
                Console.Error.WriteLine("Unexpected error: {0}", ex);
                Console.ReadKey();
            }
        }
    }
}

据我所知,您需要的是:

SID:S-1-5-5-X-Y 名称:登录会话 描述:登录会话。对于每个会话,这些SID的X和Y值都不同

Windows操作系统中的已知安全标识符

有人在这里要求类似的东西:

他们有一个很好的答案,但我想补充我自己的

这是我的解决方案:

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;


namespace TestLogonSid
{
    public partial class Form1 : Form
    {

        private delegate bool EnumDesktopProc(string lpszDesktop, IntPtr lParam);

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click_1(object sender, EventArgs e)
        {

            this.textBox1.Text = GetLogonSid.getLogonSid();
        }


    }

    public class GetLogonSid
    {
        //The SID structure that identifies the user that is currently associated with the specified object. 
        //If no user is associated with the object, the value returned in the buffer pointed to by lpnLengthNeeded is zero. 
        //Note that SID is a variable length structure. 
        //You will usually make a call to GetUserObjectInformation to determine the length of the SID before retrieving its value.
        private const int UOI_USER_SID = 4;

        //GetUserObjectInformation function
        //Retrieves information about the specified window station or desktop object.
        [DllImport("user32.dll")]
        static extern bool GetUserObjectInformation(IntPtr hObj, int nIndex, [MarshalAs(UnmanagedType.LPArray)] byte[] pvInfo, int nLength, out uint lpnLengthNeeded);


        //GetThreadDesktop function
        //Retrieves a handle to the desktop assigned to the specified thread.
        [DllImport("user32.dll")]
        private static extern IntPtr GetThreadDesktop(int dwThreadId);


        //GetCurrentThreadId function
        //Retrieves the thread identifier of the calling thread.
        [DllImport("kernel32.dll")]
        public static extern int GetCurrentThreadId();

        //ConvertSidToStringSid function
        //The ConvertSidToStringSid function converts a security identifier (SID) to a string format suitable for display, storage, or transmission.
        //To convert the string-format SID back to a valid, functional SID, call the ConvertStringSidToSid function.

        [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)]
        static extern bool ConvertSidToStringSid(
            [MarshalAs(UnmanagedType.LPArray)] byte[] pSID,
            out IntPtr ptrSid);


        /// <summary>
        /// The getLogonSid function returns the Logon Session string
        /// </summary>
        /// <returns></returns>
        public static string getLogonSid()
        {
            string sidString = "";
            IntPtr hdesk = GetThreadDesktop(GetCurrentThreadId());
            byte[] buf = new byte[100];
            uint lengthNeeded;
            GetUserObjectInformation(hdesk, UOI_USER_SID, buf, 100, out lengthNeeded);
            IntPtr ptrSid;
            if (!ConvertSidToStringSid(buf, out ptrSid))
                throw new System.ComponentModel.Win32Exception();
            try
            {
                sidString = Marshal.PtrToStringAuto(ptrSid);
            }
            catch
            {
            }
            return sidString;
        }

    }
}
使用系统;
使用System.Windows.Forms;
使用System.Runtime.InteropServices;
命名空间TestLogonSid
{
公共部分类Form1:Form
{
私有委托bool EnumDesktopProc(字符串lpszDesktop,IntPtr lpram);
公共表格1()
{
初始化组件();
}
私有无效按钮1\u单击\u 1(对象发送者,事件参数e)
{
this.textBox1.Text=GetLogonSid.GetLogonSid();
}
}
公共类GetLogonSid
{
//标识当前与指定对象关联的用户的SID结构。
//如果没有用户与对象关联,则lpnLengthNeeded指向的缓冲区中返回的值为零。
//请注意,SID是一个可变长度的结构。
//在检索SID的值之前,通常会调用GetUserObjectInformation来确定SID的长度。
私有常量int UOI\U USER\U SID=4;
//GetUserObjectInformation函数
//检索有关指定窗口站或桌面对象的信息。
[DllImport(“user32.dll”)]
静态外部bool GetUserObjectInformation(IntPtr hObj,int nIndex,[marshallas(UnmanagedType.LPArray)]字节[]pvInfo,int nLength,out uint lpnlength needed);
//GetThreadDesktop函数
//检索分配给指定线程的桌面句柄。
[DllImport(“user32.dll”)]
私有静态外部IntPtr GetThreadDesktop(intdwthreadid);
//GetCurrentThreadId函数
//检索调用线程的线程标识符。
[DllImport(“kernel32.dll”)]
public static extern int GetCurrentThreadId();
//ConvertSidToStringSid函数
//ConvertSidToStringSid函数将安全标识符(SID)转换为适合显示、存储或传输的字符串格式。
//要将字符串格式SID转换回有效的功能SID,请调用ConvertStringSidToSid函数。
[DllImport(“advapi32”,CharSet=CharSet.Auto,SetLastError=true)]
静态外部布尔转换器SIDTOSTRINGSID(
[Marshallas(UnmanagedType.LPArray)]字节[]pSID,
out IntPtr ptrSid);
/// 
///getLogonSid函数返回登录会话字符串
/// 
/// 
公共静态字符串getLogonSid()
{
字符串sidString=“”;
IntPtr hdesk=GetThreadDesktop(GetCurrentThreadId());
字节[]buf=新字节[100];
需要的单位长度;
GetUserObjectInformation(hdesk、UOI_用户_SID、buf、100、需要的输出长度);
IntPtr-ptrSid;
如果(!ConvertSidToStringSid(buf,out ptrSid))
抛出新的System.ComponentModel.Win32Exception();
尝试
{
sidString=Marshal.PtrToStringAuto(ptrSid);
}
抓住
{
}
返回字符串;
}
}
}

如果用户登录两次怎么办?同一用户是否可以使用相同的凭据登录计算机两次?我一直认为你会被重定向回你现有的会话。我想需要测试。:)@扎克:是的,我想你可以。虽然使用rdp,但它会将您踢到原始帐户。但是,一个使用用户凭据运行的服务,以及一个登录到计算机的用户如何。@YetAnotherUser我想我不会以实际用户的身份运行服务,而是以一个服务帐户(域或本地)运行服务。:)想知道你能不能从温斯顿得到这个?大概是e