Вопрос:

Получение авторизованного пользователя в Powershell

c# powershell

359 просмотра

1 ответ

8096 Репутация автора

Я написал этот скрипт Powershell для активных пользователей, вошедших в систему. Он отлично работает в исполняемом файле (C #), когда я запускаю то же самое из Powershell, я получаюArithmetic operation resulted in an overflow.

Не удалось найти проблему. В чем проблема?

function IsUserCurrentlyLoggedIn($UserDomain, $UserName)
{
    Add-Type -Language CSharp -TypeDefinition @'
using System;
using System.Runtime.InteropServices;

namespace Test
{
    public static class EnumerateUsers
    {
        [DllImport("wtsapi32.dll")]
        static extern IntPtr WTSOpenServer([MarshalAs(UnmanagedType.LPStr)] String pServerName);

        [DllImport("wtsapi32.dll")]
        static extern void WTSCloseServer(IntPtr hServer);

        [DllImport("wtsapi32.dll")]
        static extern Int32 WTSEnumerateSessions(
            IntPtr hServer,
            [MarshalAs(UnmanagedType.U4)] Int32 Reserved,
            [MarshalAs(UnmanagedType.U4)] Int32 Version,
            ref IntPtr ppSessionInfo,
            [MarshalAs(UnmanagedType.U4)] ref Int32 pCount);

        [DllImport("wtsapi32.dll")]
        static extern void WTSFreeMemory(IntPtr pMemory);

        [DllImport("Wtsapi32.dll")]
        static extern bool WTSQuerySessionInformation(
            System.IntPtr hServer, int sessionId, WTS_INFO_CLASS wtsInfoClass, out System.IntPtr ppBuffer, out uint pBytesReturned);

        [StructLayout(LayoutKind.Sequential)]
        private struct WTS_SESSION_INFO
        {
            public Int32 SessionID;

            [MarshalAs(UnmanagedType.LPStr)]
            public String pWinStationName;

            public WTS_CONNECTSTATE_CLASS State;
        }

        public enum WTS_INFO_CLASS
        {
            WTSInitialProgram,
            WTSApplicationName,
            WTSWorkingDirectory,
            WTSOEMId,
            WTSSessionId,
            WTSUserName,
            WTSWinStationName,
            WTSDomainName,
            WTSConnectState,
            WTSClientBuildNumber,
            WTSClientName,
            WTSClientDirectory,
            WTSClientProductId,
            WTSClientHardwareId,
            WTSClientAddress,
            WTSClientDisplay,
            WTSClientProtocolType
        }
        public enum WTS_CONNECTSTATE_CLASS
        {
            WTSActive,
            WTSConnected,
            WTSConnectQuery,
            WTSShadow,
            WTSDisconnected,
            WTSIdle,
            WTSListen,
            WTSReset,
            WTSDown,
            WTSInit
        }

        public static IntPtr OpenServer(String Name)
        {
            IntPtr server = WTSOpenServer(Name);
            return server;
        }
        public static void CloseServer(IntPtr ServerHandle)
        {
            WTSCloseServer(ServerHandle);
        }
        public static bool IsActiveSessionExists(string UserDomain, string Username)
        {
            IntPtr serverHandle = IntPtr.Zero;
            serverHandle = OpenServer(Environment.MachineName);
            IntPtr SessionInfoPtr = IntPtr.Zero;

            try
            {
                IntPtr userPtr = IntPtr.Zero;
                IntPtr domainPtr = IntPtr.Zero;
                Int32 sessionCount = 0;
                Int32 retVal = WTSEnumerateSessions(serverHandle, 0, 1, ref SessionInfoPtr, ref sessionCount);
                Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO));
                Int32 currentSession = (int)SessionInfoPtr;
                uint bytes = 0;

                if (retVal != 0)
                {
                    for (int i = 0; i < sessionCount; i++)
                    {
                        WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)currentSession, typeof(WTS_SESSION_INFO));
                        currentSession += dataSize;

                        WTSQuerySessionInformation(serverHandle, si.SessionID, WTS_INFO_CLASS.WTSUserName, out userPtr, out bytes);
                        WTSQuerySessionInformation(serverHandle, si.SessionID, WTS_INFO_CLASS.WTSDomainName, out domainPtr, out bytes);

                        var domain = Marshal.PtrToStringAnsi(domainPtr);
                        var username = Marshal.PtrToStringAnsi(userPtr);

                        if (UserDomain.Equals(domain, StringComparison.OrdinalIgnoreCase) &&
                            Username.Equals(username, StringComparison.OrdinalIgnoreCase) &&
                            si.State == WTS_CONNECTSTATE_CLASS.WTSActive)
                        {
                            WTSFreeMemory(userPtr);
                            WTSFreeMemory(domainPtr);
                            return true;
                        }
                        WTSFreeMemory(userPtr);
                        WTSFreeMemory(domainPtr);
                    }
                }
            }
            finally
            {
                WTSFreeMemory(SessionInfoPtr);
                CloseServer(serverHandle);
            }
            return false;
        }
    }
}
'@
    return [Test.EnumerateUsers]::IsActiveSessionExists($UserDomain, $UserName)
}
Автор: Reddy Источник Размещён: 10.03.2017 06:18

Ответы (1)


5 плюса

9151 Репутация автора

Решение

Я скопировал свои C # код для визуального проекта студии 2015 и обнаружил , что отключение Prefer 32-bitили изменение Platform targetк x64в Buildсвойствах проекта производит то же исключение в этой строке:

Int32 currentSession = (int)SessionInfoPtr;

IntPtr32-битный в 32-битном процессе и 64-битный в 64-битном процессе, но этот код предполагает, что он является 32-битным путем приведения к int( Int32). В 64-разрядной версии Windows версия PowerShell по умолчанию $Env:SystemRoot\system32\WindowsPowerShell\v1.0\powershell.exeтакже является 64-разрядной, что подтверждается тем фактом, что [IntPtr]::Sizeвозвращается 8 (байт). Изменение кода на следующее устраняет исключение как в 64-битном проекте C #, так и в PowerShell:

IntPtr currentSession = SessionInfoPtr;
Автор: BACON Размещён: 10.03.2017 07:22
Вопросы из категории :
32x32