Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 77 additions & 65 deletions ProcessExtensions/ProcessExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,50 @@

namespace murrayju.ProcessExtensions
{
public enum SW
{
HIDE = 0,
SHOWNORMAL = 1,
NORMAL = 1,

SHOWMINIMIZED = 2,

SHOWMAXIMIZED = 3,
MAXIMIZE = 3,

SHOWNOACTIVATE = 4,
SHOW = 5,
MINIMIZE = 6,
SHOWMINNOACTIVE = 7,
SHOWNA = 8,
RESTORE = 9,
SHOWDEFAULT = 10,
MAX = 10
}

[StructLayout(LayoutKind.Sequential)]
public struct STARTUPINFO
{
public int cb;
public String lpReserved;
public String lpDesktop;
public String lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}

public class ProcessCreationException : Exception
{
public ProcessCreationException(string msg) : base(msg) { }
Expand All @@ -20,12 +64,12 @@ public static class ProcessExtensions

private const uint INVALID_SESSION_ID = 0xFFFFFFFF;
private static readonly IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
private const int STARTF_USESHOWWINDOW = 0x00000001;
private const int STARTF_USESHOWWINDOW = 0x00000001;
#endregion

#region DllImports

[DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
private static extern bool CreateProcessAsUser(
IntPtr hToken,
Expand Down Expand Up @@ -80,24 +124,6 @@ private static extern int WTSEnumerateSessions(

#region Win32 Structs

private enum SW
{
SW_HIDE = 0,
SW_SHOWNORMAL = 1,
SW_NORMAL = 1,
SW_SHOWMINIMIZED = 2,
SW_SHOWMAXIMIZED = 3,
SW_MAXIMIZE = 3,
SW_SHOWNOACTIVATE = 4,
SW_SHOW = 5,
SW_MINIMIZE = 6,
SW_SHOWMINNOACTIVE = 7,
SW_SHOWNA = 8,
SW_RESTORE = 9,
SW_SHOWDEFAULT = 10,
SW_MAX = 10
}

private enum WTS_CONNECTSTATE_CLASS
{
WTSActive,
Expand Down Expand Up @@ -127,31 +153,8 @@ private enum SECURITY_IMPERSONATION_LEVEL
SecurityIdentification = 1,
SecurityImpersonation = 2,
SecurityDelegation = 3,
}

[StructLayout(LayoutKind.Sequential)]
private struct STARTUPINFO
{
public int cb;
public String lpReserved;
public String lpDesktop;
public String lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}

}

private enum TOKEN_TYPE
{
TokenPrimary = 1,
Expand Down Expand Up @@ -217,29 +220,29 @@ private static bool GetSessionUserToken(ref IntPtr phUserToken)
}

return bResult;
}

public static bool StartProcessAsCurrentUser(string appPath, string cmdLine = null, string workDir = null, bool visible = true)
{
}
public static uint StartProcessAsCurrentUserEx(string appPath, string cmdLine = null, string workDir = null, uint creationFlags = 0, STARTUPINFO? startupInfo = null)
{
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))
{
throw new ProcessCreationException("StartProcessAsCurrentUser: GetSessionUserToken failed.");
}

uint dwCreationFlags = CREATE_UNICODE_ENVIRONMENT | (uint)(visible ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW);
startInfo.dwFlags = STARTF_USESHOWWINDOW;
startInfo.wShowWindow = (short)(visible ? SW.SW_SHOW : SW.SW_HIDE);
startInfo.lpDesktop = "winsta0\\default";
}

STARTUPINFO si = startupInfo ?? new STARTUPINFO()
{
wShowWindow = (short)SW.SHOW,
dwFlags = STARTF_USESHOWWINDOW
};
si.cb = Marshal.SizeOf(typeof(STARTUPINFO));
si.lpDesktop = "winsta0\\default";

if (!CreateEnvironmentBlock(ref pEnv, hUserToken, false))
{
Expand All @@ -257,17 +260,19 @@ public static bool StartProcessAsCurrentUser(string appPath, string cmdLine = nu
IntPtr.Zero,
IntPtr.Zero,
false,
dwCreationFlags,
CREATE_UNICODE_ENVIRONMENT | creationFlags,
pEnv,
workDir, // Working directory
ref startInfo,
ref si,
out procInfo))
{
iResultOfCreateProcessAsUser = Marshal.GetLastWin32Error();
throw new ProcessCreationException("StartProcessAsCurrentUser: CreateProcessAsUser failed. Error Code -" + iResultOfCreateProcessAsUser);
}

iResultOfCreateProcessAsUser = Marshal.GetLastWin32Error();

return procInfo.dwProcessId;
}
finally
{
Expand All @@ -279,9 +284,16 @@ public static bool StartProcessAsCurrentUser(string appPath, string cmdLine = nu
CloseHandle(procInfo.hThread);
CloseHandle(procInfo.hProcess);
}

return true;
}

public static uint StartProcessAsCurrentUser(string appPath, string cmdLine = null, string workDir = null, bool visible = true)
{
return StartProcessAsCurrentUserEx(
appPath,
cmdLine,
workDir,
(uint)(visible ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW)
);
}

}
}