@@ -104,11 +104,9 @@ public static nint OpenInputDesktop()
104
104
105
105
public static bool CreateInteractiveSystemProcess (
106
106
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 )
112
110
{
113
111
uint winlogonPid = 0 ;
114
112
var hUserTokenDup = nint . Zero ;
@@ -117,21 +115,7 @@ public static bool CreateInteractiveSystemProcess(
117
115
118
116
procInfo = new PROCESS_INFORMATION ( ) ;
119
117
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 ) ;
135
119
136
120
// Obtain the process ID of the winlogon process that is running within the currently active session.
137
121
var processes = Process . GetProcessesByName ( "winlogon" ) ;
@@ -171,7 +155,7 @@ public static bool CreateInteractiveSystemProcess(
171
155
// interaction with the new process.
172
156
var si = new STARTUPINFO ( ) ;
173
157
si . cb = Marshal . SizeOf ( si ) ;
174
- si . lpDesktop = @"winsta0\" + desktopName ;
158
+ si . lpDesktop = @"winsta0\" + ResolveDesktopName ( dwSessionId ) ;
175
159
176
160
// Flags that specify the priority and creation method of the process.
177
161
uint dwCreationFlags ;
@@ -208,6 +192,53 @@ public static bool CreateInteractiveSystemProcess(
208
192
return result ;
209
193
}
210
194
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
+
211
242
public static void SetMonitorState ( MonitorState state )
212
243
{
213
244
SendMessage ( 0xFFFF , 0x112 , 0xF170 , ( int ) state ) ;
0 commit comments