es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

CoRegisterClassObject CO_E_WRONG_SERVER_IDENTITY (0x80004015) CoRegisterClassObject CO_E_WRONG_SERVER_IDENTITY (0x80004015)

Estoy construyendo un servidor COM fuera de proceso en .NET 5 utilizando esta clase de registro COM.

El cliente es un servicio en ejecución como sistema que no controlo.

Con el servidor configurado con RunAs = Usuario interactivo (valor predeterminado en mi caso), todo funciona según lo esperado durante la depuración: el servidor se puede registrar y el cliente puede llamar al servidor como un servidor COM fuera de proceso.

Sin embargo, en mi caso, el servidor se ejecuta como sistema (no como servicio) cuando no hay ningún usuario iniciado. Lo cual, por supuesto, significa que el registro falla cuando RunAs = Usuario interactivo con el error CO_E_WRONG_SERVER_IDENTITY (0x80004015).

He intentado solucionarlo estableciendo RunAs en Usuario que lanza (eliminando el valor RunAs del registro) y aunque eso permite que mi proceso que se ejecuta como sistema se registre correctamente, el cliente no parece conectarse al servidor COM existente y, en cambio, funciona como un servidor COM en proceso donde el cliente COM crea un nuevo proceso con el servidor COM.

También he intentado establecer RunAs = NT AUTHORITY\SYSTEM y mirar los permisos, pero en ambos casos tuve el mismo problema que antes.

Entonces, ¿cómo puedo registrar un servidor COM fuera de proceso para que se ejecute como sistema, sin ser un servicio, y permitir que un cliente COM que es un servicio que se ejecuta como sistema se conecte a él?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Solución para registrar un servidor COM fuera del proceso para ejecutarse como SYSTEM

    Para registrar un servidor COM fuera del proceso para ejecutarse como SYSTEM, sin ser un servicio, y permitir que un cliente COM que también es un servicio que se ejecuta como SYSTEM se conecte a él, puede probar los siguientes pasos:

    1. Configure el valor “RunAs” en el registro para el servidor COM en “Launching User”. Puede eliminar el valor “RunAs” si existe, lo que establecerá el valor en “Interactive User” por defecto.
    2. Configure los permisos de DCOM para el AppID del servidor COM para permitir que la cuenta SYSTEM lance y active el servidor COM. Esto se puede hacer utilizando la herramienta “dcomcnfg” de la siguiente manera:

    • Abra la herramienta “dcomcnfg” ejecutándolo desde la línea de comandos o desde el cuadro de diálogo “Ejecutar”.

    • Navegue hasta el nodo “Component Services -> Computers -> My Computer -> DCOM Config”.

    • Busque el AppID para su servidor COM, haga clic derecho sobre él y seleccione “Propiedades”.

    • Vaya a la pestaña “Security” y haga clic en “Edit” debajo de “Launch and Activation Permissions”.

    • Añada la cuenta “SYSTEM” y déle permisos de “Local Launch” y “Local Activation”.

    • Haga clic en “OK” para guardar los cambios.

    1. Compruebe que el servidor COM esté registrado y en funcionamiento. Puede utilizar la herramienta “dcomcnfg” para comprobar si el servidor COM está registrado y ejecutándose bajo la cuenta SYSTEM.

    2. En el código del cliente, cree el objeto COM utilizando la API “CoCreateInstanceEx” con el indicador de contexto “CLSCTX_LOCAL_SERVER” y establezca los parámetros “MachineName” y “SecurityDescriptor” según corresponda. Por ejemplo:

      hr = CoCreateInstanceEx(clsid, NULL, CLSCTX_LOCAL_SERVER, &serverInfo, 1, &params);
      

      Aquí, “serverInfo” es una instancia de la estructura “COSERVERINFO” que especifica el nombre de la máquina donde se está ejecutando el servidor COM. Establezca el miembro “pwszName” de esta estructura en “L”localhost”” o en el nombre real de la máquina según corresponda.

      “params” es una instancia de la estructura “COAUTHINFO” que especifica la configuración de seguridad para la conexión. Establezca los miembros “dwAuthnSvc”, “dwAuthzSvc”, “dwImpersonationLevel” y “dwCapabilities” de esta estructura según corresponda para su escenario.

      Por ejemplo:

      COSERVERINFO serverInfo = { 0 };
      serverInfo.dwReserved1 = 0;
      serverInfo.dwReserved2 = 0;
      serverInfo.pwszName = L"localhost";
      
      COAUTHINFO authInfo = { 0 };
      authInfo.dwAuthnSvc = RPC_C_AUTHN_DEFAULT;
      authInfo.dwAuthzSvc = RPC_C_AUTHZ_NONE;
      authInfo.dwImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE;
      authInfo.dwCapabilities = EOAC_NONE;
      
      COAUTHIDENTITY authId = { 0 };
      authId.User = NULL;
      authId.UserLength = 0;
      authId.Domain = NULL;
      authId.DomainLength = 0;
      authId.Password = NULL;
      authId.PasswordLength = 0;
      authId.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
      authInfo.pAuthIdentityData = &authId;
      
      COAUTHINFO* pAuthInfo = &authInfo;
      if (...) // establezca pAuthInfo en null si no se requiere autenticación
         pAuthInfo = NULL;
      
      MULTI_QI qi = { 0 };
      qi.pIID = &iid;
      qi.pItf = NULL;
      qi.hr = S_OK;
      
      HRESULT hr = CoCreateInstanceEx(clsid, NULL, CLSCTX_LOCAL_SERVER, &serverInfo, 1, &params);
      

      Tenga en cuenta que puede que tenga que ajustar la configuración de seguridad en el código del cliente para que coincida con los permisos de DCOM configurados para el AppID del servidor COM.

      Además, tenga en cuenta que cuando el código del cliente se ejecuta como un servicio, puede que necesite ejecutarse con privilegios elevados para poder conectarse al servidor COM que se ejecuta como SYSTEM.

Comments are closed.