c# - NUnit no puede encontrar el ensamblaje, pero la aplicación de consola puede
.net matlab (6)
¿Está el ensamblado en el Caché de ensamblados global (GAC) o en cualquier lugar en el que se esté anulando el ensamblado que cree que se está cargando? Esto suele ser el resultado de un ensamblaje incorrecto que se está cargando, para mí significa que generalmente tengo algo en el GAC que anula la versión que tengo en bin / Debug.
Tengo una clase C # que llama a un conjunto .Net creado a partir de una función de Matlab . Puedo llamar esta función desde una simple aplicación de consola C # sin problemas.
Sin embargo, si intento ejecutar una prueba unitaria desde NUnit obtengo la siguiente excepción:
ClassLibrary1.Tests.UnitTests.TestPerformOptimization: System.Reflection.TargetInvocationException: el objetivo de una invocación ha lanzado una excepción. ----> System.Exception: error que reúne el objeto .NET. ''Mensaje: no se puede encontrar el ensamblado'' ClassLibrary1, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null ''. Fuente: mscorlib HelpLink: ''
Obtengo el mismo error si trato de llamar a la clase desde la consola NUnit independiente, desde el corrector de prueba de ReSharper o si intento invocar la función desde, por ejemplo, Excel (utilizando Excel-DNA).
Cuando llamo a mi componente compilado de Matlab, realmente cierro un método C # (en un objeto MWObjectArray) y lo inserto. Creo que el problema está sucediendo cuando el componente compilado de Matlab intenta invocar este método inyectado.
La única solución que he encontrado es simplemente colocar una copia de mi clase (que contiene el método que se inyecta) en la misma ubicación que el corredor de prueba NUnit, el corredor de prueba ReSharper o Excel. Sin embargo, esto simplemente no es una solución práctica en el futuro ya que necesito instalar esta aplicación en las máquinas de los usuarios. La otra opción que no puedo usar es copiar los archivos a mi% DEVPATH% por el mismo motivo.
¿Hay alguna manera de decirle al componente de Matlab dónde encontrar el ensamblaje de mi método / clase inyectado?
PROYECTO DE MUESTRA DESCARGAR
Hay un proyecto de muestra disponible para descargar here . Simplemente siga las instrucciones en el archivo README.txt ubicado en el archivo zip.
Actualización 1
Logré que mi unidad de prueba reconociera mi ensamblaje modificando mi clase para incluir lo siguiente en su constructor:
AppDomain.CurrentDomain.AssemblyResolve +=
(sender, args) => typeof(OptimizationFunction).Assembly;
Sin embargo, ahora obtengo la siguiente excepción:
Excepción: System.Reflection.TargetInvocationException: la excepción ha sido lanzada por el objetivo de una invocación. ---> System.Exception: Error al ordenar el objeto .NET. ''Mensaje: no se pudo cargar el archivo o ensamblado'' dotnetcli, Version = 1.0.5488.33915, Culture = neutral, PublicKeyToken = da1231a838c93da4 ''o una de sus dependencias. Se requiere un ensamble con un nombre fuerte. (Excepción de HRESULT: 0x80131044) Fuente: mscorlib HelpLink: ''en dotnetcli.throwNetExceptionID (BaseMsgID * msgId) en dotnetcli.DeployedDataConversion.GetMxArrayFromObject (datos del objeto)
--- Fin del registro de la pila de la excepción interna --- en System.RuntimeMethodHandle.InvokeMethod (Object object, Object [] arguments, Signature sig, Boolean constructor)
Por lo tanto, ahora tiene un problema resolviendo dotnetclli.dll (consulte el registro / excepción de Fusion a continuación) que, por lo que sé, debería residir solo en C: / Archivos de programa (x86) / MATLAB / MATLAB Runtime / v85 / bin / win32.
Aquí hay un extracto del Registro de Fusion:
=== Información de estado previa al enlace ===
LOG: DisplayName = ClassLibrary1 (Parcial) WRN: Nombre del ensamblado: ClassLibrary1 | ID de dominio: 1 WRN: se produce un enlace parcial cuando solo se proporciona una parte del nombre para mostrar del ensamblaje. WRN: Esto podría ocasionar que el encuadernador cargue un ensamblaje incorrecto. WRN: Se recomienda proporcionar una identidad textual completamente especificada para el ensamblaje, WRN: que consiste en el nombre simple, versión, cultura y token de clave pública. > WRN: consulte el documento técnico http://go.microsoft.com/fwlink/?LinkId=109270 para obtener más información y soluciones comunes a este problema. LOG: Appbase = file: /// C: /XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/ LOG: Initial PrivatePath = NULL LOG: Base dinámica = NULL LOG: Cache Base = NULL LOG: AppName = nunit-agent-x86.exe Conjunto de llamada: (Desconocido).
=== LOG: Este enlace se inicia en el contexto de carga predeterminado. LOG: Usando el archivo de configuración de la aplicación: C: / Insight / TFS / Asg / ConsoleApplication4 / packages / NUnit.Runners.2.6.3 / tools / nunit-agent-x86.exe.Config LOG: Usando el archivo de configuración del host: LOG: Usando la máquina archivo de configuración de C: / Windows / Microsoft.NET / Framework / v4.0.30319 / config / machine.config. LOG: Política que no se aplica a la referencia en este momento (enlace de ensamblaje privado, personalizado, parcial o basado en la ubicación). LOG: Intentando descargar el nuevo archivo URL: /// C: /XXXXX/ConsoleApplication4/packages/NUnit.Runners.2.6.3/tools/ClassLibrary1.DLL. LOG: Intentando descargar el nuevo archivo URL: /// C: /XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/ClassLibrary1/ClassLibrary1.DLL. LOG: Intentando descargar el nuevo archivo URL: /// C: /XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/lib/ClassLibrary1.DLL. LOG: Intentando descargar el nuevo archivo URL: /// C: /XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/lib/ClassLibrary1/ClassLibrary1.DLL. LOG: Intentando descargar el nuevo archivo URL: /// C: /XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/addins/ClassLibrary1.DLL. LOG: Intentando descargar el nuevo archivo URL: /// C: /XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/addins/ClassLibrary1/ClassLibrary1.DLL. LOG: Intentando descargar el nuevo archivo URL: /// C: /XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/ClassLibrary1.EXE. LOG: Intentando descargar el nuevo archivo URL: /// C: /XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/ClassLibrary1/ClassLibrary1.EXE. LOG: Intentando descargar el nuevo archivo URL: /// C: /XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/lib/ClassLibrary1.EXE. LOG: Intentando descargar el nuevo archivo URL: /// C: /XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/lib/ClassLibrary1/ClassLibrary1.EXE. LOG: Intentando descargar el nuevo archivo URL: /// C: /XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/addins/ClassLibrary1.EXE. LOG: Intentando descargar el nuevo archivo URL: /// C: /XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/addins/ClassLibrary1/ClassLibrary1.EXE. LOG: todas las URL de sondeo intentaron y fallaron.
WRN: se proporcionó información de enlace parcial para un ensamblaje: ¿cómo es posible que mi aplicación de consola pueda resolver este ensamblaje con mi prueba NUnit no?
Actualización 2
Obtuve la siguiente respuesta de Matlab cuando los contacté:
Hasta donde yo sé, este es el comportamiento predeterminado de .NET cuando se trata de deserializaciones. La aplicación que deserializa la clase busca el ensamblaje en su propia carpeta actual y GAC donde no puede encontrarlo. Es similar a (cuando lee esto, reemplace MATLAB con Nunit)
Tu ejemplo no representa la situación cuando MATLAB está involucrado. MATLAB envía la clase a través de APPDomains. Tu ejemplo no hace eso.
Use Fuslogvw para echar un vistazo a la encuadernación. Verá que no es MATLAB el que no puede encontrar el ensamblaje, es la aplicación de llamada que no puede resolver la dependencia (en su caso, nunit-agent-x86.exe).
Asegúrese de que todos los archivos necesarios sean producidos por la compilación de ConsoleApplication4 y colocados además del ejecutable (por ejemplo, cualquier DLL de conjunto necesario, DLL de tiempo de ejecución, archivo .config, etc.)
Una vez que esté seguro de que esto sucede, inicie NUnit con el modificador de línea de comando --no-shadow-copy, o configúrelo como un parámetro de configuración desde su herramienta GUI. Como dijo Bush, NUnit normalmente copia los archivos bajo prueba a un directorio separado y puede dejar atrás archivos importantes.
Si la clase creada por Matlab necesita algún tipo de tiempo de ejecución específico, asegúrese de que esté correctamente instalada en las computadoras donde está ejecutando las pruebas / usando Excel / ReSharper.
No trataría de tocar el violín, en este nivel, con el proceso de resolución de la Asamblea: por favor, resuma el contenido del artículo que vinculó, porque está pagada, y pruebe con la configuración sin copia de NUnit.
Creo que este problema proviene de una incompatibilidad de versión .NET CLR. Algunos clientes (me refiero al cliente que llama a su ensamblaje) cargan diferentes versiones del CLE, luego el ensamblado resuelto puede ser incompatible con ese CLR cargado. Esto podría causar un error no encontrado, porque realmente no se encuentra un ensamblaje compatible.
Intente verificar / jugar con las versiones de ambos clientes (la aplicación de la consola) y la versión del servidor (su ensamblaje) y diagnostique qué está cambiando.
También verifique que su referencia de ensamblaje esté marcada "Copiar en el directorio de salida" en todos los proyectos
Creo que este problema proviene de una incompatibilidad de versión .NET CLR. Algunos clientes (me refiero al cliente que llama a su ensamblaje) cargan diferentes versiones del CLE, luego el ensamblado resuelto puede ser incompatible con ese CLR cargado. Esto podría causar un error no encontrado, porque realmente no se encuentra un ensamblaje compatible.
Intente verificar / jugar con las versiones de ambos clientes (la aplicación de la consola) y la versión del servidor (su ensamblaje) y diagnostique qué está cambiando.
También verifique que su referencia de ensamblaje esté marcada "Copiar en el directorio de salida" en todos los proyectos
Querrá estudiar cómo ocurre la operación de sondeo en .NET load time. Aquí están las reglas para eso: https://msdn.microsoft.com/en-us/library/yx7xezcf(v=vs.110).aspx
Aparte de incluir el contenedor en el ensamblaje que está publicando, es el cargador el que decide si el molde de soporte de los archivos DLL es cargable. Si no puede encontrarlo usando las reglas anteriores, simplemente no tiene suerte.
Hemos visto problemas similares a esto en el pasado, algunos desarrolladores le dicen al administrador del sistema, aquí están los Dlls que necesita para ejecutar la aplicación. El Administrador del sistema sigue las instrucciones y el auge, la aplicación falla en el momento de la carga.
Motivo: Algunos hijos de un niño en la asamblea hacen referencia a un dll que NO está en el sistema según las reglas de prueba.
Solución 1) Obtenga el dll (hijo del niño) para incluir todas las dependencias en su conjunto 2) Cambie el ensamblaje principal más nuevo para incluir todas las dependencias (si los ensamblajes secundarios no se pueden cambiar). 3) Cópialos manualmente. 4) Crea un instalador que lo haga todo.
Un primer problema propuesto:
- Ejecutar regedit
- ir a HKEY_LOCAL_MACHINE / SOFTWARE / Microsoft / Fusion
- Agregar DWORD ForceLog = 1
- Agregar DWORD LogFailures = 1
- Agregar DWORD LogResourceBinds = 1
- Agregar String LogPath = C: / log / (last / must be there)
- Crear un directorio para registros (c: / logs por ejemplo)
Se registrará donde su aplicación buscó ensamblajes y cómo falló. Probablemente significa que el directorio de trabajo de nunit era diferente del directorio de trabajo utilizado por la aplicación de consola.
Un segundo error de propuesta: se requiere un ensamblado con un nombre fuerte significa que la biblioteca que ha intentado usar no está firmada. Si se trata de su ensamblaje, simplemente debe usar el signo visual studio del ensamblaje de las propiedades del proyecto. Si no es su ensamblaje, puede descompilarlo y compilarlo con un nombre seguro ( con este método ), pero el proveedor de dll de terceros debería proporcionarle un ensamblado de nombre seguro.