elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Curso de javascript por TickTack


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  .NET (C#, VB.NET, ASP) (Moderador: kub0x)
| | | |-+  Evitar tener una DLL al lado del EXE?
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Evitar tener una DLL al lado del EXE?  (Leído 3,106 veces)
z3nth10n


Desconectado Desconectado

Mensajes: 1.583


"Jack of all trades, master of none." - Zenthion


Ver Perfil WWW
Evitar tener una DLL al lado del EXE?
« en: 22 Febrero 2017, 17:26 pm »

Hola buenas,

el error es simple, tengo un exe que utiliza una dll, que al compilarse (por medio de un batch) lo dejo "aislado" de sus correspondientes DLLs, realmente no queda aislado como tal, la DLL pasa a estar en otra carpeta, entonces, mi pregunta es si se puede hacer un link a esa DLL movida de sitio...

Según he leido con App.config es posible a hacerlo a subdirectorios, pero no a otro sitio:

http://stackoverflow.com/a/3577344/3286975

Y que por temas de seguridad no se puede hacer de otra forma:

https://social.msdn.microsoft.com/Forums/vstudio/en-US/4eb0026c-135b-4f4c-9ec2-0ef39a1b001a/referencing-a-dll-in-a-location-different-from-exe?forum=csharpgeneral

Entonces que me queda, utilizar Reflection para cargar esas DLLs?



Como veis, ahí dentro de la misma solución tengo la DLL (Librería de clases -> Lerp2API), y una aplicación de consola (Lerp2Console) que tiene como referencia a dicha DLL...

Vale, al compilarse, utilizo un Batch como venimos sabiendo dese antaño :xD este batch mueve las DLLs de tal forma que de pasar a estar asi:



Como veis, a la derecha, tenemos la consola con su "Copy Local", la Copy Local será borrada y a cambio se tomará la DLL que está en D:\LERP2DEV\Lerp2Dev Assets\Lerp2API\Build\
formando la jerarquía que podéis observar a la izquierda...

El problema está en que la consola está un nivel por debajo de la DLL que necesita para ejecutarse en vez de ser de al revés que sería como funcionaría...

Provocando este error:



El error y su solución es clara, pero quiero saber si se puede hacer de la forma que yo quiero, el código está en Github:

https://github.com/Lerp2Dev/Lerp2API/blob/c4562481509f874a019d9ea8700abde8069241c3/Project/Lerp2Console/Program.cs

Un saludo.


« Última modificación: 28 Febrero 2017, 12:10 pm por Ikillnukes » En línea


Interesados hablad por Discord.
Serapis
Colaborador
***
Desconectado Desconectado

Mensajes: 3.348


Ver Perfil
Re: Evitar tener una DLL al lado del EXE?
« Respuesta #1 en: 22 Febrero 2017, 18:41 pm »

Bla,bla,bla...


« Última modificación: 14 Diciembre 2020, 20:05 pm por Serapis » En línea

Eleкtro
Ex-Staff
*
Desconectado Desconectado

Mensajes: 9.788



Ver Perfil
Re: Evitar tener una DLL al lado del EXE?
« Respuesta #2 en: 22 Febrero 2017, 22:21 pm »

Hola.

¿Tú lo que quieres es incluir (adjuntar, embedir) esa dll en tu compilación.exe?, ¿o por lo contrario lo que quieres es mantener el archivo.dll aislado de los demás ensamblados y en una carpeta distinta al directorio de trabajo de tu compilación.exe?.

Hay varias soluciones efectivas para ambos casos, pero aclárame ese punto por favor para no explicar cosas distintas en vano...

¡Saludos!
En línea

z3nth10n


Desconectado Desconectado

Mensajes: 1.583


"Jack of all trades, master of none." - Zenthion


Ver Perfil WWW
Re: Evitar tener una DLL al lado del EXE?
« Respuesta #3 en: 22 Febrero 2017, 22:22 pm »

Me refiero a la segunda opción, tengo el exe en una carpeta y la dll en otro como puedes ver :P
En línea


Interesados hablad por Discord.
Eleкtro
Ex-Staff
*
Desconectado Desconectado

Mensajes: 9.788



Ver Perfil
Re: Evitar tener una DLL al lado del EXE?
« Respuesta #4 en: 23 Febrero 2017, 10:12 am »

Me refiero a la segunda opción, tengo el exe en una carpeta y la dll en otro

Bueno. Como ya te mencioné por privado, puedes crear un enlace simbólico (SymLink o también llamado SoftLink) con la herramienta mklink.exe de Microsoft:

Sintaxis que debes usar:
Código:
MkLink.exe "C:\Enlace Destino.dll" "C:\Archivo Origen.dll"

Esto creará una especie de acceso directo de "cero" bytes con el que no tendrás problemas para cargar el archivo de origen en tu aplicación. Logicamente debes asignarle el mismo nombre al archivo simbólico que el nombre original de tu librería.dll.

Esta es la opción que más te recomiendo bajo mi criterio. Te permite mantener la misma estructura de archivos (reemplazando el archivo original por otro archivo "fantasma" y funcional), el resultado no ocupa nada de espacio, y no supone ningún impacto negativo en el rendimiento del S.O. Solamente el archivo simbólico y tú, tú y el archivo simbólico :xD.

Si quieres crear el enlace de forma programática desde .NET, puedes utilizar la función Win32 CreateSymbolicLink:

Aqui tienes un ejemplo de uso y definiciones para VB.NET (de mi framework ElektroKit que puedes encontrar a la venta en CodeCanyon):

Código
  1. NativeMethods.CreateSymbolicLink("C:\Destination Link.ext", "C:\Source File.ext", NativeEnums.SymbolicLinkFlags.File)

Código
  1. <SuppressUnmanagedCodeSecurity>
  2. Public NotInheritable Class NativeMethods
  3.  
  4.    ''' ----------------------------------------------------------------------------------------------------
  5.    ''' <summary>
  6.    ''' Creates a symbolic link.
  7.    ''' </summary>
  8.    ''' ----------------------------------------------------------------------------------------------------
  9.    ''' <remarks>
  10.    ''' <see href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa363866%28v=vs.85%29.aspx"/>
  11.    ''' </remarks>
  12.    ''' ----------------------------------------------------------------------------------------------------
  13.    ''' <param name="dstFilePath">
  14.    ''' The path of the symbolic link to be created.
  15.    ''' </param>
  16.    '''
  17.    ''' <param name="srcFilePath">
  18.    ''' The path of the target for the symbolic link to be created.
  19.    ''' <para></para>
  20.    ''' If <paramref name="srcFilePath"/> has a device name associated with it,
  21.    ''' the link is treated as an absolute link;
  22.    ''' otherwise, the link is treated as a relative link.
  23.    ''' </param>
  24.    '''
  25.    ''' <param name="flags">
  26.    ''' Indicates whether the link target is a file or is a directory.
  27.    ''' </param>
  28.    ''' ----------------------------------------------------------------------------------------------------
  29.    ''' <returns>
  30.    ''' If the function succeeds, the return value is <see langword="True"/>.
  31.    ''' <para></para>
  32.    ''' If the function fails, the return value is <see langword="False"/>.
  33.    ''' <para></para>
  34.    ''' To get extended error information, call <see cref="Marshal.GetLastWin32Error"/>.
  35.    ''' <para></para>
  36.    ''' </returns>
  37.    ''' ----------------------------------------------------------------------------------------------------
  38.    <SuppressMessage("Microsoft.Interoperability", "CA1401:PInvokesShouldNotBeVisible", Justification:="Visible for API")>
  39.    <DllImport("Kernel32.dll", SetLastError:=True)>
  40.    Public Shared Function CreateSymbolicLink(ByVal dstFilePath As String,
  41.                                              ByVal srcFilePath As String,
  42.                <MarshalAs(UnmanagedType.I4)> ByVal flags As NativeEnums.SymbolicLinkFlags
  43.    ) As <MarshalAs(UnmanagedType.I1)> Boolean
  44.    End Function
  45.  
  46.    ''' <summary>
  47.    ''' Prevents a default instance of the <see cref="NativeMethods"/> class from being created.
  48.    ''' </summary>
  49.    Private Sub New()
  50.    End Sub
  51.  
  52. End Class

Código
  1. Public NotInheritable Class NativeEnums
  2.  
  3.    ''' ----------------------------------------------------------------------------------------------------
  4.    ''' <summary>
  5.    ''' Indicates whether a symbolic link is a file or is a directory.
  6.    ''' </summary>
  7.    ''' ----------------------------------------------------------------------------------------------------
  8.    ''' <remarks>
  9.    ''' <see href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa363866%28v=vs.85%29.aspx"/>
  10.    ''' </remarks>
  11.    ''' ----------------------------------------------------------------------------------------------------
  12.    Public Enum SymbolicLinkFlags As Integer
  13.  
  14.        ''' <summary>
  15.        ''' The link target is a file.
  16.        ''' </summary>
  17.        File = &H0
  18.  
  19.        ''' <summary>
  20.        ''' The link target is a directory.
  21.        ''' </summary>
  22.        Directory = &H1
  23.  
  24.    End Enum
  25.  
  26.    ''' <summary>
  27.    ''' Prevents a default instance of the <see cref="NativeEnums"/> class from being created.
  28.    ''' </summary>
  29.    Private Sub New()
  30.    End Sub
  31.  
  32. End Class

Nota: Recuerda que esta función de la API de Windows, como muchas otras, tiene una versión ANSI y otra Unicode (CreateSymbolicLinkA, CreateSymbolicLinkW) en caso de que necesites usar alguna en específico por el motivo que sea.



Lo que te comentó por encima el compañero @NEBIRE, consistiría en colocar el archivo.dll en uno de los directorios en el que el sistema operativo intentará buscar de forma automática las dependencias de tu executable. Es otra buena opción, pero yo lo recomendaría en otro tipo de circunstancias. Al estar hablando de una aplicación administrada, el cargador de dependencias de .NET lo más probable es que te diese problemas al intentar resolver la ubicación de una dependencia administrada que esté ubicada fuera del directorio de inicio de tu app, aunque la coloques en el directorio del sistema. Si descartas la opción de crear un enlace simbólico, entonces en lugar de esto lo que deberías hacer es registrar la dependencia en el GAC de Windows, pero bueno, te explicaré esta metodología por si quieres probar a ver si en tus circunstancias te funciona bien... o simplemente para que sepas algo más.

El orden de búsqueda de dependencias para aplicaciones de escritorio es el siguiente (el orden variará en el caso de que tengas activado el valor de registro SafeDllSearch):

  • 1. El directorio de inicio de la aplicación {startup dir}. Donde está alojada la aplicación.
     
  • 2. El directorio de trabajo actual de la aplicación {working dir}.
     
  • 3. Los directorios de sistema de 32 y 64 Bits.
       C:\Windows\SysWOW64\
       C:\Windows\System32\
     
  • 4. El directorio de sistema de 16 Bits.
       C:\Windows\System\
     
  • 5. El directorio de Windows
       C:\Windows\
     
  • 6. Los directorios que estén listados en las variables de entorno PATH.
       HKCU\Environment PATH
       HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment PATH

En la MSDN tienes toda la info que necesites conocer al respecto (para variar):

¡Saludos!
« Última modificación: 23 Febrero 2017, 10:21 am por Eleкtro » En línea

z3nth10n


Desconectado Desconectado

Mensajes: 1.583


"Jack of all trades, master of none." - Zenthion


Ver Perfil WWW
Re: Evitar tener una DLL al lado del EXE?
« Respuesta #5 en: 28 Febrero 2017, 12:09 pm »

Hola buenas,

5 días después de responder y una vez más que resuelta la duda, te respondo. Lo primero gracias por decir lo de los Symbolic Links, y a ti tb Nebire por tu sugerencia.

Me quedé atascado un poco porque al leer por encima, me quedé solo con lo de:

Citar
Código
  1. MkLink.exe "C:\Enlace Destino.dll" "C:\Archivo Origen.dll"

Y no leí lo del acceso directo. Una vez que hicimos ya lo hablamos en privado y le echaste un ojo más de cerca, me explicaste la sintaxis para hacerlo, que era la siguiente:

Código
  1. mklink "D:\LERP2DEV\Lerp2Dev Assets\Lerp2API\Build\Console\Lerp2API.dll" "D:\LERP2DEV\Lerp2Dev Assets\Lerp2API\Build\Lerp2API.dll"

Un saludo.

PD: En el repositorio se han quedado unos cuantos scripts interesantes, que Elektro no recomendaria, pero que a mi me han servido:

https://github.com/Lerp2Dev/Lerp2API/tree/b72b5530c4f5f36fcb2a476df64e03b03f7d6009/Project/Lerp2Console

Más en concreto: Dynamicals.cs, Instancials.cs, NativeLinking.cs y Program - Copia.cs

Es el uso de dynamic para instancias y llamadas estáticas (Instancials sirve para crear de forma rápida y sencilla llamadas (mediante llamadas estáticas o bien mediante creación de nuevas instancias), Dyanicals simplemente alberga la parte de la creación de objetos a partir de llamadas estáticas, Activator (una clase nativa de Reflection) es la que se encarga de la parte de instancias).

Llamada estática:

Código
  1. Console.WriteLine("Hola mundo");

Formato: Clase - Metodo

Llamada a través de una instancia:

Código
  1. Clase clase = new Clase();
  2. clase.Metodo();

Básicamente. NativeLinking.cs lo que hace es lo que nos propuso Elektro, pero de forma nátiva, en C#. :P

Ahora me he quedado trabado con el tema de los Sockets. :-\
« Última modificación: 28 Febrero 2017, 12:55 pm por Ikillnukes » En línea


Interesados hablad por Discord.
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines