3

我正在使用以下代码来获取当前用户和我的应用程序进程的所有者。

当前用户:

CurrentUser = WindowsIdentity.GetCurrent().Name;

流程所有者:

String strQuery = String.Format("Select * From Win32_Process where Name='{0}'", ProcessName);
ObjectQuery oQuery = new ObjectQuery(strQuery);

ManagementObjectSearcher oManSearcher = new ManagementObjectSearcher(oQuery);

foreach (ManagementObject oManItem in oManSearcher.Get())
{
    String[] s = new String[2];

    oManItem.InvokeMethod("GetOwner", (object[])s);

    ProcessOwner = s[0];

    break;
}

我需要从语法上确定我的应用程序实例在哪个用户帐户中运行。

基本上,我允许每个登录用户使用一个我的应用程序实例。

当用户正常启动应用程序时,上述代码有效。当用户右键单击快捷方式(或使用类似方法)并选择“以管理员身份运行”时,代码会发生故障。在这种情况下,进程所有者将不是登录用户,而是管理员。

这对确定多个实例造成了严重破坏,更不用说正确的数据库路径等了。

从我的角度来看,正常启动的实例和以管理员身份启动的实例都是同一登录用户下的实例,只是所有者不同。

如何确定进程属于哪个登录用户?如前所述,检查当前用户的进程所有者并不总是最好的检查。

回答:

这是从所选答案开发的完整方法。

public static String GetUsernameBySessionId(int sessionId, Boolean prependDomain)
{
    IntPtr buffer;
    int strLen;
    String username = "SYSTEM";
    if (WTSQuerySessionInformation(IntPtr.Zero, sessionId, WtsInfoClass.WTSUserName, out buffer, out strLen) && strLen > 1)
    {
        username = Marshal.PtrToStringAnsi(buffer);
        WTSFreeMemory(buffer);
        if (prependDomain)
        {
            if (WTSQuerySessionInformation(IntPtr.Zero, sessionId, WtsInfoClass.WTSDomainName, out buffer, out strLen) && strLen > 1)
            {
                username = String.Format("{0}\\{1}", Marshal.PtrToStringAnsi(buffer), username);
                WTSFreeMemory(buffer);
            }
        }
    }

    return username;
}

当前进程SessionId为:

Process.GetCurrentProcess().SessionId
4

3 回答 3

1

要获取应用程序的登录用户,我建议读取当前进程的 SessionId,该进程独立于实际运行应用程序的用户。进程的 SessionId 可以通过以下方式读取:

System.Diagnostics.Process.GetCurrentProcess().SessionId

可以使用以下答案中的函数检索与 SessionId 关联的用户名:Get Windows user name from SessionID

该函数GetUsernameBySessionId还需要此枚举:

public enum WtsInfoClass
{
    WTSInitialProgram = 0,
    WTSApplicationName = 1,
    WTSWorkingDirectory = 2,
    WTSOEMId = 3,
    WTSSessionId = 4,
    WTSUserName = 5,
    WTSWinStationName = 6,
    WTSDomainName = 7,
    WTSConnectState = 8,
    WTSClientBuildNumber = 9,
    WTSClientName = 10,
    WTSClientDirectory = 11,
    WTSClientProductId = 12,
    WTSClientHardwareId = 13,
    WTSClientAddress = 14,
    WTSClientDisplay = 15,
    WTSClientProtocolType = 16,
    WTSIdleTime = 17,
    WTSLogonTime = 18,
    WTSIncomingBytes = 19,
    WTSOutgoingBytes = 20,
    WTSIncomingFrames = 21,
    WTSOutgoingFrames = 22,
    WTSClientInfo = 23,
    WTSSessionInfo = 24,
    WTSSessionInfoEx = 25,
    WTSConfigInfo = 26,
    WTSValidationInfo = 27,
    WTSSessionAddressV4 = 28,
    WTSIsRemoteSession = 29
}
于 2013-12-09T17:43:22.067 回答
0

System.Environment.UserName - 获取当前登录到 Windows 操作系统的人员的用户名。

那是你要找的吗?

编辑:如果您只需要在流程开始时获取值,则可能会起作用。如果他们切换用户并且该过程继续进行,则该值可能会改变。

于 2013-12-09T17:31:51.983 回答
0

您应该使用 Mutex 提供此功能:

改编自:在 C# 中使用 Global Mutex 的好模式是什么?

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
    // Get application GUID
    string appGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value.ToString();
    WindowsIdentity currentUser = WindowsIdentity.GetCurrent();
    // Get user SID
    string userSid = currentUser.User.ToString();

    // Construct application & user specific mutex ID
    string mutexID = string.Format(@"Global\{{{0}}}-{{{1}}}", appGuid, userSid);

    using (Mutex mutex = new Mutex(false, mutexID))
    {
        MutexAccessRule allowUserRule = new MutexAccessRule(currentUser.User, MutexRights.FullControl, AccessControlType.Allow);
        MutexSecurity securitySettings = new MutexSecurity();
        securitySettings.AddAccessRule(allowUserRule);
        mutex.SetAccessControl(securitySettings);

        bool hasHandle = false;

        try
        {
            try
            {
                hasHandle = mutex.WaitOne(5000, false);
            }
            catch (AbandonedMutexException)
            {
                // Log the fact the mutex was abandoned in another process, it will still get aquired
                hasHandle = true;
            }

            if (hasHandle == false) return;

            // Start application
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
        finally
        {
            if (hasHandle) mutex.ReleaseMutex();
        }
    }
}

将超时时间调整为mutex.WaitOne您希望应用程序在退出前等待独占访问的时间。

于 2013-12-09T18:10:08.067 回答