添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Hi guys,

I am looking for a script that will allow my users to find remote desktops that aren’t in an active session, or to list the active session on a set of computers – similar to what PSLogged in does. For us, PSLoggedin doesn’t work anymore – instead of listing active sessions, it lists EVERY user who has ever logged into the machine, making it useless. Any help you guys could provide would be greatly appreciated. Thanks.

You can use PowerShell if you have version 4.0 there are RDP cmdlets: RemoteDesktop Module | Microsoft Learn

Or I had found a C# based script that will grab some information, then I added a piece of PowerShell script to ask you what Terminal Server you wanted to check

Here it is if you’re interested:

# QuerySessionInformation.ps1
# Written by Ryan Ries, Jan. 2013, with help from MSDN and Stackoverflow.
# http://serverfault.com/questions/342533/wmi-object-to-get-current-sessions-with-client-name
$Code = @'
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
public class RDPInfo
    [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 void ListUsers(String ServerName)
        IntPtr serverHandle = IntPtr.Zero;
        List<String> resultList = new List<string>();
        serverHandle = OpenServer(ServerName);
            IntPtr SessionInfoPtr = IntPtr.Zero;
            IntPtr userPtr = IntPtr.Zero;
            IntPtr domainPtr = IntPtr.Zero;
            IntPtr clientNamePtr = 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);
                    WTSQuerySessionInformation(serverHandle, si.SessionID, WTS_INFO_CLASS.WTSClientName, out clientNamePtr, out bytes);
                    if(Marshal.PtrToStringAnsi(domainPtr).Length > 0 && Marshal.PtrToStringAnsi(userPtr).Length > 0)
                        if(Marshal.PtrToStringAnsi(clientNamePtr).Length < 1)                       
                            Console.WriteLine(Marshal.PtrToStringAnsi(domainPtr) + "\\" + Marshal.PtrToStringAnsi(userPtr) + "\tSessionID: " + si.SessionID + "\tClientName: n/a");
                            Console.WriteLine(Marshal.PtrToStringAnsi(domainPtr) + "\\" + Marshal.PtrToStringAnsi(userPtr) + "\tSessionID: " + si.SessionID + "\tClientName: " + Marshal.PtrToStringAnsi(clientNamePtr));
                    WTSFreeMemory(clientNamePtr);
                    WTSFreeMemory(userPtr);
                    WTSFreeMemory(domainPtr);
                WTSFreeMemory(SessionInfoPtr);
        catch(Exception ex)
            Console.WriteLine("Exception: " + ex.Message);
        finally
            CloseServer(serverHandle);
# This section was added by Matt Bergeron (Chamele0n on Spiceworks community) on Mar. 2013
# Asks for user input of servers hostname to be queried
[console]::ForegroundColor = "green"
[console]::BackgroundColor= "black"
$Server = Read-Host 'Please enter the HostName of the server you want to query. (e.g. TerminalServer1) Leave blank for localhost'
if ($Server -eq $null){
	$Server = (Get-Childitem env:computername)
[console]::ResetColor()
Add-Type $Code
[console]::ForegroundColor = "yellow"
[console]::BackgroundColor= "black"
[RDPInfo]::ListUsers($Server)
[console]::ResetColor()
              

I’m not sure if this would work for you, but I just look for the owner of the explorer.exe process to see who’s logged on:

(Get-WmiObject Win32_Process -ComputerName computer | ?{ $_.ProcessName -match "explorer" }).getowner() | Select-object "User"

This might be helpful also:

learn.microsoft.com