my code:
public static bool StartProcessAsCurrentUser(string appPath, string cmdLine, string currentUserName, string workDir = null, bool visible = true)
{
var hUserToken = IntPtr.Zero;
var startInfo = new STARTUPINFO();
var procInfo = new PROCESS_INFORMATION();
var pEnv = IntPtr.Zero;
int iResultOfCreateProcessAsUser;
startInfo.cb = Marshal.SizeOf(typeof(STARTUPINFO));
try
{
if (!GetSessionUserToken(ref hUserToken, currentUserName))
{
throw new Exception("StartProcessAsCurrentUser: GetSessionUserToken failed.");
}
uint dwCreationFlags = CREATE_UNICODE_ENVIRONMENT | (uint)(visible ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW);
startInfo.wShowWindow = (short)(visible ? SW.SW_SHOW : SW.SW_HIDE);
startInfo.lpDesktop = "winsta0\\default";
if (!CreateEnvironmentBlock(ref pEnv, hUserToken, false))
{
throw new Exception("StartProcessAsCurrentUser: CreateEnvironmentBlock failed.");
}
if (!CreateProcessAsUser(hUserToken,
appPath, // Application Name
cmdLine, // Command Line
IntPtr.Zero,
IntPtr.Zero,
false,
dwCreationFlags,
pEnv,
workDir, // Working directory
ref startInfo,
out procInfo))
{
iResultOfCreateProcessAsUser = Marshal.GetLastWin32Error();
throw new Exception("StartProcessAsCurrentUser: CreateProcessAsUser failed. Error Code -" + iResultOfCreateProcessAsUser);
}
iResultOfCreateProcessAsUser = Marshal.GetLastWin32Error();
}
catch(Exception ex)
{
log.Info("StartProcessAsCurrentUser exeption msg:"+ex.Message +" stacktrace:"+ex.StackTrace);
}
finally
{
CloseHandle(hUserToken);
if (pEnv != IntPtr.Zero)
{
DestroyEnvironmentBlock(pEnv);
}
CloseHandle(procInfo.hThread);
CloseHandle(procInfo.hProcess);
}
return true;
}
}
private static bool GetSessionUserToken(ref IntPtr phUserToken, string currentUserName)
{
var bResult = false;
var hImpersonationToken = IntPtr.Zero;
var activeSessionId = INVALID_SESSION_ID;
try
{
ITerminalServicesManager manager = new TerminalServicesManager();
using (ITerminalServer server = manager.GetLocalServer())
{
server.Open();
foreach (ITerminalServicesSession session in server.GetSessions())
{
if (session.UserName.ToUpper() == currentUserName.ToUpper())
{
activeSessionId = (uint)session.SessionId;
break;
}
}
}
// If enumerating did not work, fall back to the old method
if (activeSessionId == INVALID_SESSION_ID)
{
activeSessionId = WTSGetActiveConsoleSessionId();
}
log.Info("Method GetSessionUserToken: activeSessionId:" + activeSessionId);
if (WTSQueryUserToken(activeSessionId, ref hImpersonationToken) != 0)
{
// Convert the impersonation token to a primary token
bResult = DuplicateTokenEx(hImpersonationToken, 0, IntPtr.Zero,
(int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, (int)TOKEN_TYPE.TokenPrimary, ref phUserToken);
CloseHandle(hImpersonationToken);
}
log.Info("GetSessionUserToken ends.");
}
catch(Exception ex)
{
log.Info("GetSessionUserToken exception:." + ex.Message);
}
return bResult;
}