He escrito un motor de renderizado basado en Direct3D 9 en C# usando SlimDX. En un nuevo proyecto, ahora necesito distribuir imágenes de una escena 3D cargada usando un servicio web. El problema es que para poder renderizar algo necesito un dispositivo Direct3d. ¿Hay alguna manera de crear un dispositivo direct3d sin que el usuario inicie sesión en el sistema y el escritorio no esté bloqueado?Renderizar escena 3D en el sistema bloqueado
Si eso no es posible, ¿alguien sabe de alguna solución? Al final, necesito un ejecutable que se pueda ejecutar desde el planificador de tareas usando alguna cuenta de usuario local o un servicio, que periódicamente muestra imágenes de la escena desde ciertos puntos de vista.
El motor se divide en dos partes: el motor en sí y el renderizador. Entonces, si no hay otra manera, entonces también podría implementar un renderizador nuevo usando OpenGL o cualquier otra tecnología que permita renderizar sin tener una forma visible.
Editar:
Lo que tengo hasta ahora es la siguiente:
protected override void OnContinue() {
base.OnContinue();
NativeFunctions.SafeWindowStationHandle hwinsta = NativeFunctions.WindowStation.OpenWindowStation(
"WinSta0",
true,
NativeFunctions.AccessMask.WINSTA_ALL_ACCESS);
if(hwinsta == null || hwinsta.IsClosed || hwinsta.IsInvalid)
Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
if(NativeFunctions.WindowStation.SetProcessWindowStation(hwinsta.DangerousGetHandle())) {
NativeFunctions.SafeDesktopHandle ptrDesktop = NativeFunctions.WindowStation.OpenInputDesktop(
0,
true,
NativeFunctions.AccessMask.DESKTOP_CREATEWINDOW);
if(ptrDesktop.IsClosed || ptrDesktop.IsInvalid)
return;
if(!NativeFunctions.WindowStation.SetThreadDesktop(ptrDesktop.DangerousGetHandle()))
return;
Log log = Logger.Instance.CreateLog("DXService", true, true, false);
log.LogMessage("Desktop set, creating D3D-Object.", LOGMESSAGELEVEL.CRITICAL, true);
Direct3D direct3D = new Direct3D();
log.LogMessage("Direct3D object created, creating device.", LOGMESSAGELEVEL.CRITICAL, true);
if(direct3D.AdapterCount == 0) {
log.LogMessage("FATAL: direct3D.AdapterCount == 0");
}
}
}
Esto es parte de un servicio de windows mínima. Puse el código importante en la función OnContinue porque es más fácil de depurar que el código de inicio. Le di a estos servicios el derecho de interactuar con el escritorio activo. cuando ejecuto el servicio como una cuenta de sistema local para que funcione el escritorio y la ventana, pero la cantidad de GraphicsAdapters sigue siendo 0, cuando ejecuto el servicio usando una cuenta de usuario dedicada, entonces ni siquiera puedo abrir la WindowStation. ¿Hay algo más que pueda intentar o que estoy haciendo mal? Estoy probando esto en una máquina con Windows 7, mientras estoy conectado ya que de lo contrario la depuración se vuelve muy difícil. ¿Podría ser esto un problema?
Gracias
Muchas gracias por la pista a las estaciones de ventana, ¿podría tratar de recordar algunas de las acciones necesarias para que esto funcione, ya que es casi exactamente lo que necesito. Según lo que he leído hasta ahora, necesito ejecutar mi aplicación como un servicio, con privilegios para acceder al escritorio interactivo (agujero de seguridad) y luego, de alguna manera, debería ser capaz de crear un dispositivo válido. ¿Pero cómo? ;) – Gooo
Lo siento, fue hace demasiado tiempo y no estaba realmente involucrado con ese código.Podría haber sido tan simple de obtener el escritorio hwnd para el escritorio utilizado para mostrar la pantalla de inicio de sesión (a través de EnumDesktopWindows?) O podría haber sido más complicado, realmente no lo recuerdo. – timday