@@ -104,11 +104,9 @@ public static nint OpenInputDesktop()
104104
105105 public static bool CreateInteractiveSystemProcess (
106106 string commandLine ,
107- int targetSessionId ,
108- bool forceConsoleSession ,
109- string desktopName ,
110- bool hiddenWindow ,
111- out PROCESS_INFORMATION procInfo )
107+ int targetSessionId ,
108+ bool hiddenWindow ,
109+ out PROCESS_INFORMATION procInfo )
112110 {
113111 uint winlogonPid = 0 ;
114112 var hUserTokenDup = nint . Zero ;
@@ -117,21 +115,7 @@ public static bool CreateInteractiveSystemProcess(
117115
118116 procInfo = new PROCESS_INFORMATION ( ) ;
119117
120- // If not force console, find target session. If not present,
121- // use last active session.
122- var dwSessionId = Kernel32 . WTSGetActiveConsoleSessionId ( ) ;
123- if ( ! forceConsoleSession )
124- {
125- var activeSessions = GetActiveSessions ( ) ;
126- if ( activeSessions . Any ( x => x . Id == targetSessionId ) )
127- {
128- dwSessionId = ( uint ) targetSessionId ;
129- }
130- else
131- {
132- dwSessionId = activeSessions . Last ( ) . Id ;
133- }
134- }
118+ var dwSessionId = ResolveWindowsSession ( targetSessionId ) ;
135119
136120 // Obtain the process ID of the winlogon process that is running within the currently active session.
137121 var processes = Process . GetProcessesByName ( "winlogon" ) ;
@@ -171,7 +155,7 @@ public static bool CreateInteractiveSystemProcess(
171155 // interaction with the new process.
172156 var si = new STARTUPINFO ( ) ;
173157 si . cb = Marshal . SizeOf ( si ) ;
174- si . lpDesktop = @"winsta0\" + desktopName ;
158+ si . lpDesktop = @"winsta0\" + ResolveDesktopName ( dwSessionId ) ;
175159
176160 // Flags that specify the priority and creation method of the process.
177161 uint dwCreationFlags ;
@@ -208,6 +192,53 @@ public static bool CreateInteractiveSystemProcess(
208192 return result ;
209193 }
210194
195+ public static string ResolveDesktopName ( uint targetSessionId )
196+ {
197+ var winDir = Environment . GetFolderPath ( Environment . SpecialFolder . Windows ) ;
198+ var logonUiPath = Path . Combine ( winDir , "System32" , "LogonUI.exe" ) ;
199+ var consentPath = Path . Combine ( winDir , "System32" , "consent.exe" ) ;
200+
201+ var isLogonScreenVisible = Process
202+ . GetProcessesByName ( "LogonUI" )
203+ . Any ( x => x . SessionId == targetSessionId && x . MainModule ? . FileName . Equals ( logonUiPath , StringComparison . OrdinalIgnoreCase ) == true ) ;
204+
205+ var isSecureDesktopVisible = Process
206+ . GetProcessesByName ( "consent" )
207+ . Any ( x => x . SessionId == targetSessionId && x . MainModule ? . FileName . Equals ( consentPath , StringComparison . OrdinalIgnoreCase ) == true ) ;
208+
209+ if ( isLogonScreenVisible || isSecureDesktopVisible )
210+ {
211+ return "Winlogon" ;
212+ }
213+
214+ return "Default" ;
215+ }
216+
217+ public static uint ResolveWindowsSession ( int targetSessionId )
218+ {
219+ var activeSessions = GetActiveSessions ( ) ;
220+ if ( activeSessions . Any ( x => x . Id == targetSessionId ) )
221+ {
222+ // If exact match is found, return that session.
223+ return ( uint ) targetSessionId ;
224+ }
225+
226+ if ( Shlwapi . IsOS ( OsType . OS_ANYSERVER ) )
227+ {
228+ // If Windows Server, default to console session.
229+ return Kernel32 . WTSGetActiveConsoleSessionId ( ) ;
230+ }
231+
232+ // If consumer version and there's an RDP session active, return that.
233+ if ( activeSessions . Find ( x => x . Type == WindowsSessionType . RDP ) is { } rdSession )
234+ {
235+ return rdSession . Id ;
236+ }
237+
238+ // Otherwise, return the console session.
239+ return Kernel32 . WTSGetActiveConsoleSessionId ( ) ;
240+ }
241+
211242 public static void SetMonitorState ( MonitorState state )
212243 {
213244 SendMessage ( 0xFFFF , 0x112 , 0xF170 , ( int ) state ) ;
0 commit comments