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

 

 


Tema destacado: Guía actualizada para evitar que un ransomware ataque tu empresa


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  .NET (C#, VB.NET, ASP) (Moderador: kub0x)
| | | |-+  [WPF] Agregar referencia desde un recurso del mismo proyecto, es posible?
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: [WPF] Agregar referencia desde un recurso del mismo proyecto, es posible?  (Leído 3,172 veces)
z3nth10n


Desconectado Desconectado

Mensajes: 1.583


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


Ver Perfil WWW
[WPF] Agregar referencia desde un recurso del mismo proyecto, es posible?
« en: 22 Abril 2014, 17:09 pm »

Hola buenas, pues llevo con el tema 2 días y aún no he conseguido averiguar nada de nada, todo lo que he leido y he visto se ha hecho desde WinForms, supongo que no será muy dificil adaptarlo a WPF... La cosa es esta, veréis, yo tengo un DLL (que se puede agregar como referencia a un proyecto) la cosa es que este DLL tiene siempre que estar al lado del ejecutable (.exe) para que la aplicación rule, si no lo está no se abre como sabréis.

Para mi esto de que un maldito DLL tenga que estar al lado del Exe para que se pueda ejecutar me toca mucho la moral, y bueno, pues estuve viendo por ahí metodos de como poder llamar a este dichoso DLL desde los recursos.

Y bien, tengo dos problemas, uno a rasgos generales, que me planteé nada más plantear la duda y es... que si cargo desde los recursos este dichoso DLL como se supone que Intellise va a detectar que en los recursos hay tal DLL para importarlo (Imports DLL.Dichoso), no se si me explico, esta duda, como aún no he podido ni romper la punta del iceberg, pues la dejo ahí.

Y la otra es, el problema en sí, que he buscado por internet y nada...

ILMerge por aquí, .Net Shrink por allá, pero ningún maldito tutorial en condiciones que te explique paso por paso lo que se supone que hay que hacer.

Luego está CodeProject, y StackOverFlow, que me han aportado ciertos códigos, que luego, bueno, han llegado a tener algún efecto, pero no el deseado, el que más este:

Código
  1.    Private Sub DynaStart(ByVal sender As Object, ByVal e As StartupEventArgs) 'En winforms debería estar el tipico "Handles Me.StartUp"
  2.        AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf DynamicOokii_Dialogs_Wpf
  3.        AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf DynamicIonic_Zip
  4.    End Sub
  5.  
  6.    Private Function DynamicOokii_Dialogs_Wpf(sender As Object, e As System.ResolveEventArgs) As Reflection.Assembly
  7.        Dim desiredAssembly = New Reflection.AssemblyName(e.Name)
  8.  
  9.        If desiredAssembly.Name = "DynaWars_Splash_Text" Then
  10.            Return Reflection.Assembly.Load(My.Resources.Ookii_Dialogs_Wpf) 'replace with your assembly's resource name
  11.        Else
  12.            Return Nothing
  13.        End If
  14.    End Function
  15.  
  16.    Private Function DynamicIonic_Zip(sender As Object, e As System.ResolveEventArgs) As Reflection.Assembly
  17.        Dim desiredAssembly = New Reflection.AssemblyName(e.Name)
  18.  
  19.        If desiredAssembly.Name = "DynaWars_Splash_Text" Then
  20.            Return Reflection.Assembly.Load(My.Resources.Ionic_Zip) 'replace with your assembly's resource name
  21.        Else
  22.            Return Nothing
  23.        End If
  24.    End Function

Que al menos conseguí que la aplicación se abriese sin necesidad de tener los DLLs presentes, pero, cuando llamaba alguna función de Ookii o de Ionic_Zip la app dejaba de funcionar. (Las referencias también estaban agregadas desde Proyecto -> Agregar referencia, para que Intellise si que me reconociese estos métodos, yo creo que algo estoy haciendo pero que muy mal...)

Y luego esto, que para colmo estaba en C#: http://www.codeproject.com/Articles/528178/Load-DLL-From-Embedded-Resource

Que fue el que me dio la idea de Agregar las referencias al proyecto, a parte de subirlas a los recursos como Embedded Resource (Recurso Incrustado)

Así que nada, maestros, decidme que debo hacer para poder llevar a cabo tal hazaña... xD

Un saludo.

También he leido esto, que bueno, recoge algo de la esencia de lo que yo estoy haciendo: http://foro.elhacker.net/buscador-t381033.0.html


« Última modificación: 22 Abril 2014, 17:12 pm por Ikillnukes » En línea


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

Mensajes: 9.788



Ver Perfil
Re: [WPF] Agregar referencia desde un recurso del mismo proyecto, es posible?
« Respuesta #1 en: 22 Abril 2014, 21:39 pm »

Cita de: Ikillnukes;1042929488
este DLL tiene siempre que estar al lado del ejecutable (.exe) para que la aplicación rule, si no lo está no se abre como sabréis.

Eso es incorrecto, una dll es un archivo localizable como cualquier otro archivo, puedes meter el ensamblado en una carpeta cualquiera, y luego cargarlo desde esa '...\carpeta\ensamblado.dll' en tu proyecto (ya sea WF o WPF).



Cita de: Ikillnukes;1042929488
Para mi esto de que un maldito DLL tenga que estar al lado del Exe para que se pueda ejecutar me toca mucho la moral, y bueno, pues estuve viendo por ahí metodos de como poder llamar a este dichoso DLL desde los recursos.

Es lo más normal del mundo, una dll no es más que un conjunto de Classes y otros miembros (como un proyecto, en este caso solo métodos con sus objetos y otros miembros y los diálogos ...UserControls) compiladas en un ensamblado .NET ...de extensión dll y con sus puntos de acceso (EntryPoints) legibles y accesibles por el lenguaje, es un archivo complétamente independiente al que accedes.



Cita de: Ikillnukes;1042929488
si cargo desde los recursos este dichoso DLL como se supone que Intellise va a detectar que en los recursos hay tal DLL para importarlo (Imports DLL.Dichoso)

hmmm, creo que entiendo lo que quieres decir... aunque también creo que estás confundiendo cosas, la característica IntelliSense nada tiene que ver con la importación de un ensamblado (la instrucción Imports), son dos cosas muy distintas, aparte, la declaración Imports referencia los miembros de un ensamblado para que puedas especificarlos de forma abreviada y también para evitar ambiguedades (conflictos) entre miembros que tengan el mismo nombre ...pero tú la librería la puedes usar sin importarla, solo tienes que escribir el namespace completo (una vez hayas referenciado el ensamblado).

IntelliSense es una característica que muestra la información relevante (los comentarios XML que se hayan documentado en el ensamblado), sobre los miembros (cualquier miembro documentable, como una propiedad, o un método, y sus parámetros y/o su valor de retorno),

si te fijas en alguno de mis Snippets verás muchos comentarios, pues no lo hago por gusto, lo hago para documentar el código y que IntelliSense lo muestre.

Para usar la instrucción Imports en un ensamblado (la dll), este debe existir como un archivo físico en el disco para importar (al menos que yo sepa), ten en cuenta que los recursos se cargan en la memoria y no en el disco, pero como todo espacio de memoria, este se puede manipular y extraer, así que si añades una dll como recurso a tu proyecto, una vez compilado (quiero decir, en tiempo de ejecución) podrías extraer primeramente del Stream de memoria todos los bytes que forman el archivo dll para guardarlo en el disco físico ...en un 'archivo.dll', y luego cargarlo usando Reflection, o mejor todavía, puedes cargar el Stream del ensamblado (el recurso en el namespace My.Resources) diréctamente usando Reflection,
pero el tema Reflection es MUY extenso y complejo como para explicarlo en 10 segundos, y además deberías usar reflection también para modificar todos los nombres referenciados de la libreria, por ejemplo:
Código:
Dim dialog As New Ookii.Dialogs.VistaFolderBrowserDialog
Esa sería la manera normal como instanciarias el objeto, pero al no tenerlo referenciado obviamente no vas a poder especificar los nombres completos porque el Debugger te va a mandar a la mierd..., primero tienes que cargar el ensamblado, luego debes localizar el miembro instanciable (la Class que contiene el Constructor), y luego instanciarla, ejemplo:

Código
  1. Imports System.Reflection
  2.  
  3. Public Class Form1
  4.  
  5.  
  6.    Private Shadows Sub Shown() Handles MyBase.Shown
  7.  
  8.        ' Cargo la dll como recurso, es decir, cargo el Stream de memoria que contiene los bytes de la dll.
  9.        Dim asm As Assembly = Assembly.Load(My.Resources.Ookii_Dialogs)
  10.  
  11.        ' Obtengo el miembro 'VistaFolderBrowserDialog' del ensamblado.
  12.        Dim t As Type = (From member As Type In asm.GetTypes
  13.                         Where member.Name = "VistaFolderBrowserDialog").First
  14.  
  15.        ' Instancio la Class.
  16.        ' Esto sería el equivalente a:
  17.        ' Dim Dialog As New Ookii.Dialogs.VistaFolderBrowserDialog
  18.        Dim Dialog = Activator.CreateInstance(t)
  19.  
  20.        ' Asigno una propiedad del Objeto.
  21.        Dialog.Tag = "Hello"
  22.        MsgBox(Dialog.tag)
  23.  
  24.    End Sub
  25.  
  26. End Class
...Y eso es en versión reducida y rápida, si un método es privado o si hay coincidencias ambiguas (un método overload, con el mismo nombre que otro) deberás iterar los miembros (métodos) para hallar el correcto e invocarlo, y especificar sus Types, el Binder, y etc, y lo mismo para asignar valores a las propiedades en caso de que se den las mismas circunstancias, usar Reflection no es moco de pavo, es algo avanzado, aunque cuando vas aprendiendo te das cuenta de que hay cosas que son muy sencillas al fin y al cabo.

Y en fín, por esa razón te sugerí otras alternativas (seguir leyendo abajo).



Cita de: Ikillnukes;1042929488
ILMerge por aquí, .Net Shrink por allá, pero ningún maldito tutorial en condiciones que te explique paso por paso lo que se supone que hay que hacer.

No se si es sarcasmo, porque lo de ILMerge y .NET Shrink te lo sugerí yo... y a mi parecer si no te entiendes con una aplicación tan sencilla diseñada para newbies como es .NET Shrink entonces diréctamente te sugiero dejar de programar.

Te explico, abres la aplicación, arrastras los ensamblados .NET (el exe + las librerías dll), y le das al botoncito que pone 'Compress File', y listo, ya tienes todos los ensamblados empaquetado en un único archivo executable, muy dificil no es ...¿VERDAD?, ¿sigue siendo necesario un tutorial?.

De hecho te recomendé el uso de esa aplicación porque es lo más sencillo y rápido para ti, tú lo que debes hacer es agregar tus librerías dll a tu proyecto, no te preocupes por si la dll está "al lado" del exe, tu hazlo e importas la librería en tu proyecto como harias normalmente, acabas tu proyecto y todo el código, y luego (el paso final) abres el .NET Shrink (o ILMerge u otros Mergers) y lo empaquetas como te expliqué, se generará un único archivo EXE que contendrá todas las dll que hayas metido, la structura de archivos seguirá siendo la misma intérnamente, es decir, la dll estará ubicada al lado del exe ...pero todo estará empaquetado y podrás usar esa dll teniendo solo un exe (con la dll adentro).


Saludos!



Aparte de eso, por si te interesa más Reflection, hice este ejemplo y lo posteé hace tiempo en el hilo de Snippets, un ejemplo para localizar e invocar métodos:

Código
  1. Imports System.Reflection
  2. Imports System.Globalization
  3.  
  4. Public Class Form1
  5.  
  6.    Private Shadows Sub Load() Handles MyBase.Load
  7.  
  8.        Dim MethodName As String = "Test"
  9.  
  10.        Dim Method As MethodInfo =
  11.            Me.GetType().GetMethod(MethodName, BindingFlags.IgnoreCase Or BindingFlags.Instance Or
  12.                                               BindingFlags.Public Or BindingFlags.NonPublic)
  13.  
  14.        If Method IsNot Nothing Then
  15.            Method.Invoke(Me, BindingFlags.IgnoreCase Or BindingFlags.Instance Or
  16.                              BindingFlags.Public Or BindingFlags.NonPublic,
  17.                          Nothing,
  18.                          New Object() {"Hello World!", Type.Missing}, CultureInfo.InvariantCulture)
  19.  
  20.        Else
  21.            MsgBox("Method not found.")
  22.  
  23.        End If
  24.  
  25.    End Sub
  26.  
  27.    Private Sub Test(ByVal StringValue As String, Optional ByVal IntValue As Integer = 1)
  28.        MessageBox.Show(StringValue & IntValue)
  29.    End Sub
  30.  
  31. End Class

Nota: Hay que tener muy presente la visibilidad del miembro.


« Última modificación: 22 Abril 2014, 21:42 pm por Eleкtro » En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

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