[英]Getting the logged in user in Powershell
我已编写此Powershell脚本来获取“活动登录用户”。 它在exe文件(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)
}
我将您的C#代码复制到Visual Studio 2015项目中,发现在项目的Build
属性中禁用“ Prefer 32-bit
或将Platform target
更改为x64
会在此行上产生相同的异常:
Int32 currentSession = (int)SessionInfoPtr;
IntPtr
在32位进程中是32位,在64位进程中是64位,但是此代码通过转换为int
( Int32
)来假定它是32位。 在64位Windows上, $Env:SystemRoot\\system32\\WindowsPowerShell\\v1.0\\powershell.exe
的PowerShell的“默认”版本也是64位,您可以通过[IntPtr]::Size
返回的事实来确认8(字节)。 将代码更改为以下代码可以消除64位C#项目和PowerShell中的异常:
IntPtr currentSession = SessionInfoPtr;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.