我的设置是:
- 视窗服务器 2008、IIS 7
我想完成的事情:
- IIS 7 从我的网站接收到执行一些 3D 操作(在 WPF 中)的请求,最后 IIS 7 应该渲染图像并将其存储在磁盘上的某个位置以加载到网站中
我所知道的以及我已经测试过的:
- IIS 7 在 Windows Server 2008 上的会话 0 中作为服务运行
- 会话 0 中的任何服务都无法访问视频驱动程序,即会话 0 中的任何服务都无法执行任何渲染任务(此处解释:会话 0 隔离)
- 微软在另一篇论文中建议在用户会话中创建一个进程(通过 CreateProcessAsUser)以成功执行渲染。
到目前为止我取得的成就:
- LogonUser 运行良好
- CreateProcessAsUser 运行良好
唯一(但重要的)部分不起作用:当我使用用户名和密码登录并以用户身份创建进程时,该进程仍处于会话 0 中,因此渲染失败。用户成功登录(我检查了它)。根据微软的说法,它必须可以在用户会话(而不是会话 0)中创建一个进程。
- 如何在 0 以外的其他会话中以用户身份创建进程?
- 我是否必须自己创建一个新会话或类似的东西?
谢谢!
我的代码:
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);
}