CreateProcessAsUser в пользовательском сеансе (кроме 0) из службы (IIS 7)
Моя настройка:
- Windows Server 2008, IIS 7
Чего я хотел бы достичь:
- IIS 7 получает запрос от моего веб-сайта на выполнение некоторых 3D-операций (в WPF), и в конце IIS 7 должен отобразить изображение и сохранить его где-нибудь на диске для загрузки на веб-сайт.
Что я знаю и что уже проверил:
- IIS 7 работает как служба в сеансе 0 в Windows Server 2008
- ни одна служба в сеансе 0 не имеет доступа к видеодрайверу, то есть никакая служба в сеансе 0 не может выполнять какие-либо задачи рендеринга (объяснение здесь: изоляция сеанса 0)
- Microsoft предлагает в другом документе создать процесс в пользовательском сеансе (CreateProcessAsUser) для успешного выполнения рендеринга.
Чего я достиг до сих пор:
- LogonUser работает хорошо
- CreateProcessAsUser работает хорошо
Единственная (но важная) часть, которая не работает: когда я вхожу в систему с именем пользователя и паролем и создаю процесс как пользователь, процесс все еще находится в сеансе 0, и, следовательно, рендеринг не выполняется. Пользователь успешно вошел в систему (я это проверил). Согласно Microsoft, должна быть возможность создать процесс в сеансе пользователя (не в сеансе 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);
}
1 ответ
Я не являюсь экспертом в этой области, просто выполнил некоторые поиски, и кажется, что вы не можете на самом деле изменить уровень сеанса, скорее, вы должны включить пользователя с автоматическим входом в систему и общаться с процессом, запущенным под этим пользователем.
Это казалось наиболее полезным: Windows 2008 RenderFarm Service: CreateProcessAsUser "Session 0 Isolation" и OpenGL