My setting is:
- Windows Server 2008, IIS 7
What I would like to accomplish:
- IIS 7 receives a request from my website to do some 3D operations (in WPF) and in the end IIS 7 should render an image and store it somewhere on the disk to get loaded into the website
What I know and what I already have tested yet:
- IIS 7 runs as service in session 0 on Windows Server 2008
- no service in session 0 has access to the video driver, that is no service in session 0 can perform any rendering tasks (explained here: Session 0 Isolation)
- Microsoft proposes in another paper to create a process in a user session (by CreateProcessAsUser) to perform rendering sucessfully.
What I achieved up until now:
- LogonUser works well
- CreateProcessAsUser works well
The only (but important) part that doesn't work: When I logon with username and password and create a process as user, the process is still in session 0 and therefore rendering fails. The user logged on successfully (I checked it). According to Microsoft it must be possible to create a process in a user session (not session 0).
- How can I create a process as user in other session than 0?
- Do I have to create a new session myself or something like this?
Thank you!
My code:
PROCESS_INFORMATION processInfo = new PROCESS_INFORMATION();
STARTUPINFO startInfo = new STARTUPINFO();
Boolean bResult = false;
IntPtr hToken = IntPtr.Zero;
UInt32 uiResultWait = WAIT_FAILED;
int processCreationFlags;
try
{
// Logon user
bResult = Win32.LogonUser(
strName,
strDomain,
strPassword,
Win32.LogonType.LOGON32_LOGON_BATCH,
Win32.LogonProvider.LOGON32_PROVIDER_DEFAULT,
out hToken
);
if (!bResult) { throw new Exception("Logon error #" + Marshal.GetLastWin32Error()); }
CheckPrivileges(hToken);
// Create process
startInfo.cb = Marshal.SizeOf(startInfo);
startInfo.lpDesktop = null;
startInfo.dwFlags = Convert.ToInt32(STARTF.STARTF_USESHOWWINDOW);
startInfo.wShowWindow = Convert.ToInt16(SHOWWINDOW.SW_HIDE);
processCreationFlags = Convert.ToInt32(CreateProcessFlags.CREATE_BREAKAWAY_FROM_JOB);
retStr += "command line: " + strCommand + Environment.NewLine;
bResult = Win32.CreateProcessAsUser(
hToken,
null, //application name
strCommand, //command line
IntPtr.Zero, //process attributes
IntPtr.Zero, //thread attributes
false, //inherit handles
processCreationFlags, //process creation flags
IntPtr.Zero, //environment
curDir, //current directory
ref startInfo,
out processInfo
);
if (!bResult) { throw new Exception("CreateProcessAsUser error #" + Marshal.GetLastWin32Error()); }
// Wait for process to end
uiResultWait = WaitForSingleObject(processInfo.hProcess, INFINITE);
if (uiResultWait == WAIT_FAILED) { throw new Exception("WaitForSingleObject error #" + Marshal.GetLastWin32Error()); }
}
finally
{
// Close all handles
CloseHandle(hToken);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}