Professional Documents
Culture Documents
Cdigo Inseguro
De lo comentado se deduce que, en ocasiones, puede ser interesante utilizar punteros. Un primer acercamiento a los punteros son los delegates, que pertenecen al llamado safe code o cdigo seguro pero nicamente se comportan como punteros a funciones. En C# se permite utilizar punteros y al cdigo en el que se utilizan punteros se le denomina cdigo inseguro o unsafe code. El cdigo inseguro debe ser marcado utilizando la palabra reservada unsafe. Es posible marcar como unsafe: Una clase Un miembro de una clase Un bloque de cdigo
En C# no se permite declarar punteros a tipos referencia. Tampoco es posible marcar como unsafe una variable local (ha de marcarse el mtodo o bloque de cdigo en el que est). Adems de lo comentado, al compilar cdigo inseguro es necesario indicrselo al compilador utilizando el flag unsafe (independientemente de si se compila desde el Visual Studio .NET o desde la lnea de comandos). 1/38
Cdigo Inseguro
Figura 13.1
2/38
Cdigo Inseguro
Figura 13.2 En caso de que no est seleccionado, se ha de seleccionar el proyecto en desarrollo desde la explorador de soluciones:
3/38
Cdigo Inseguro
Figura 13.3 Al hacerlo, en la ventana propiedades se mostrar la informacin sobre el proyecto y se activarn los botones e iconos del cuadro de la ventana. Pulse sobre el cuarto icono de la ventana de propiedades y aparecer el cuadro de dilogo con las pgina de propiedades del proyecto. En propiedades de configuracin se ha de elegir Generar y Permitir bloques de cdigo no seguros a True.
4/38
Cdigo Inseguro
Figura 13.4 De este modo ser posible compilar cdigo inseguro. En caso contrario el compilador no lo permitir (genera error en tiempo de compilacin). Por lo dems, el uso y declaracin de punteros en C# es igual que en C y C++, con una excepcin: en C y C++, cuando se declaran varias variables de tipo puntero en una misma lnea se separan por comas y van precedidas todas ellas por *. Por ejemplo:
int *p1, *p2;
Ejemplo:
int num = 5; //la variable num ocupa 4 bytes de memoria //(stack o pila), por ejemplo, a partir //de la posicin 0x004FFFA8 hasta la //0x004FFFAB. El contenido de esas posiciones //es el valor 5. //la variable num2 ocupa 4 bytes //de memoria (stack o pila), por //ejemplo, a partir de la posicin 0x004FFFA4 hasta //la 0x004FFFA7. El contenido de esas //posiciones es el valor 10. // pNum es una variable de tipo puntero a entero y //ocupa 4 bytes de memoria (stack o pila), por //ejemplo, a partir de la 0x004FFFA0 hasta la //0x004FFFA3. El contenido de esas posiciones no est //definido (basura).
int *pNum;
5/38
Cdigo Inseguro
*pNum = &num2;
//al asignar la direccin de la variable num2 al //contenido de la variable pNum, las posiciones //correspondientes a la variable de tipo puntero pNum //(0x004FFFA0 a 0x004FFFA3) pasan a //contener la direccin de la variable num2, es //decir, 0x004FFFA4.
Aritmtica de punteros.
Es posible aadir o restar enteros a un puntero utilizando los operadores +, -, ++, --, += y -=. Por ejemplo, supngase que se aade la instruccin pNum++ al ejemplo anterior:
int num = 5; int num2 = 10; int *pNum; *pNum = &num2; pNum++;
Al incrementar en una unidad pNum lo que sucede es que su contenido pasa a ser el actual aumentado en cuatro unidades, ya que el tamao de una variable de tipo entero es 4 bytes y el compilador entiende que se quiere que pNum apunte a la siguiente variable de tipo entero y no al siguiente byte. De este modo, el contenido de pNum ser 0x004FFFA4 + 4, es decir 0x004FFFA8, que es la direccin de la variable num. Es importante notar que si el cdigo hubiese sido:
int num = 5; int num2 = 10; int *pNum; *pNum = # pNum++;
Al incrementar pNum pasara a valer 0x004FFFA8 + 4, que es 0x004FFFAC. Aqu se presenta el problema inherente al manejo directo de punteros. Qu hay en 0x004FFFAC? Lo ms posible es que no haya un entero sino algo desconocido, lo cual implicar un malfuncionamiento del programa cuyos efectos no son fcilmente predecibles. El siguiente ejemplo muestra cmo desarrollar cdigo inseguro y utilizar punteros y variables, indicando informacin sobre stos.
using System; class CodigoInseguroPunteros { static unsafe void Main (string[] args) { int int_num = 15; int *p_int_num = &int_num; Console.WriteLine("El valor de int_num es:" + *p_int_num); Console.WriteLine("La direccin de int_num es: " + (uint) p_int_num); Console.WriteLine("El tamao de int_num es:"+sizeof (int)); Console.WriteLine("El valor de p_int_num es: " +
6/38
Cdigo Inseguro
(uint) p_int_num); Console.WriteLine("La direccin de p_int_num es: " + (uint) &p_int_num); Console.WriteLine("El tamao de p_int_num es: " + sizeof (int*)); } }
El resultado es:
Figura 13.5 Tanto int_num como p_int_num son almacenados en la pila o stack ya que son datos de tipo primitivo (valor). Un int (entero) tiene un tamao de 4 bytes. Un puntero tiene un tamao de 4 bytes (independientemente del tipo de datos al que apunte). El contenido de p_int_num es la direccin de int_num. Se puede observar que la direccin de p_int_num es 1243464, es decir, anterior en 4 bytes (que es lo que ocupa el puntero) a int_num. Puesto que la pila crece hacia abajo y las variables se le aaden en el orden en que han sido declaradas, lo lgico es que p_int_num ocupe las posiciones ms bajas.
7/38
Cdigo Inseguro
Figura 13.6 El siguiente ejemplo es similar al anterior pero abarca ms tipos de datos de tipo valor (todos primitivos).
using System; class ManejoPunteros { static unsafe void Main (string[] args) { bool bool_val = true; char char_val = 'a'; sbyte sbyte_num = 5; short short_num = 10; int int_num = 15; long long_num = 20; double double_num = 25; float float_num = 30; bool *p_bool_val = &bool_val; char *p_char_val = &char_val; sbyte *p_sbyte_num = &sbyte_num; short *p_short_num = &short_num; int *p_int_num = &int_num; long *p_long_num = &long_num; double *p_double_num = &double_num; float *p_float_num = &float_num;
Console.WriteLine("El valor de bool_val es: " + *p_bool_val); //podra ponerse bool_val Console.WriteLine("La direccin de bool_val es: " + (uint) p_bool_val); //podra ponerse &bool_val Console.WriteLine("El tamao de bool_val es: " + sizeof (bool)); Console.WriteLine("El valor de char_val es: " + *p_char_val);
8/38
Cdigo Inseguro
Console.WriteLine("La direccin de char_val es: " + (uint) p_char_val); Console.WriteLine("El tamao de char_val es: " + sizeof (char)); Console.WriteLine("El valor de sbyte_num es: " + *p_sbyte_num); Console.WriteLine("La direccin de sbyte_num es: (uint) p_sbyte_num); Console.WriteLine("El tamao de sbyte_num es: " + sizeof (sbyte)); Console.WriteLine("El valor de short_num es: " + *p_short_num); Console.WriteLine("La direccin de short_num es: (uint) p_short_num); Console.WriteLine("El tamao de short_num es: " + sizeof (short)); Console.WriteLine("El valor de int_num es: *p_int_num); Console.WriteLine("La direccin de int_num es: " + (uint) p_int_num); Console.WriteLine("El tamao de int_num es: " + sizeof (int)); Console.WriteLine("El valor de long_num es: " + *p_long_num); Console.WriteLine("La direccin de long_num es: " + (uint) p_long_num); Console.WriteLine("El tamao de long_num es: " + sizeof (long)); Console.WriteLine("El valor de double_num es: " *p_double_num); Console.WriteLine("La direccin de double_num es: (uint) p_double_num); Console.WriteLine("El tamao de double_num es: " + sizeof (double)); Console.WriteLine("El valor de float_num es: " + *p_float_num); Console.WriteLine("La direccin de float_num es: (uint) p_float_num); Console.WriteLine("El tamao de float_num es: " + sizeof (float)); } }
" +
" +
" +
+ " +
" +
El resultado ser:
9/38
Cdigo Inseguro
Figura 13.7 Aqu puede observarse tambin la colocacin de las variables en la pila (en este caso no se muestra la informacin sobre los punteros).
Casting de punteros.
Es posible convertir punteros a un tipo de datos a punteros a otro tipo diferente de datos. Por ejemplo:
int num = 5; int *pNum; byte *pOcteto; pOcteto = # pNum = # System.Console.WriteLine(Contenido apuntado por pNum {0}, *pNum); System.Console.WriteLine(Contenido apuntado por pOcteto {0}, *pOcteto);
Tanto pOcteto como pNum apuntan a num, que es una variable que ocupa 4 bytes en memoria (stack), ya que es una variable de tipo int. Cuando se acceda a num mediante pNum, se permitir manejar los 4 bytes de num como lo que es (un entero), en cambio, cuando se acceda a num a travs de pOcteto, slo podr manipularse el primer byte u octeto de los 4 que ocupa num, porque a travs de un puntero a byte slo puede manejarse un byte, independientemente del tipo de datos real al que se refiera la direccin contenida en el puntero a byte. Es importante deducir de esto que dependiendo del casting que se haga es posible que no tenga utilidad alguna. Un casting lgico puede ser convertir cualquier tipo de puntero en un puntero a sbyte, para poder recorrer byte a byte el contenido de una variable. Tambin es posible convertir un puntero a otro tipo de datos no puntero, como puede ser int, uint, long... De todos estos casting los ms lgicos son a int o uint, ya que un dato de tipo int o uint ocupa 4 bytes y uno de tipo long 8, etc...
10/38
Cdigo Inseguro
Adems, si se desea mostrar por consola el valor de un puntero, por ejemplo pNum, no puede hacerse:
//error en compilacin System.Console.WriteLine(Contenido de pNum {0}, pNum);
Ha de hacerse lo siguiente:
System.Console.WriteLine(Contenido de pNum {0}, (uint) pNum);
Nota: en C#, al igual que en C y C++ puede utilizarse el operador sizeof para obtener el tamao de un tipo de datos.
Punteros void.
No es una buena idea utilizar punteros a void en C# pero en ocasiones puede ser necesario. El caso ms comn es cuando se desea invocar una funcin del API que necesita recibir parmetros de tipo void*. Se puede declarar punteros a void y hacer casting entre punteros de otros tipos y void:
void * pVoid; int * pInt; int num = 5; *pInt = &num pVoid = (void*) pInt;
pero no es posible desreferenciar punteros a void utilizando el operador *, es decir *pVoid causar un error de compilacin en cualquier expresin en que aparezca (en las declaraciones no, por supuesto).
11/38
Cdigo Inseguro
Por supuesto, tambin se pueden crear punteros a los miembros de una estructura. Por ejemplo:
Punto * pPunto; int * pX, pY; Punto p1 = new Punto(); pX = &(p1.X); //tambin pY = &(p1.Y); //tambin *pX = 5; *pY = 10; System.Console.WriteLine System.Console.WriteLine
(X: + pX ); (Y: + pY );
int * pX, pY; Punto p1 = new Punto(); fixed (pX = &(p1.X)) { //manejar pX *pX = 5; System.Console.WriteLine (X: + pX ); } ... fixed (pY = &(p1.Y)) { //manejar pY *pY = 10; System.Console.WriteLine (Y: + pY ); }
12/38
Cdigo Inseguro
pX, pY; p1 = new Punto(); (pX = &(p1.X)) (pY = &(p1.Y)) //manejar pX *pX = 5; System.Console.WriteLine (X: + pX ); //manejar pY *pY = 10; System.Console.WriteLine (Y: + pY );
... ... int * pX, pY; Punto p1 = new Punto(); fixed (pX = &(p1.X)) { //manejar pX *pX = 5; System.Console.WriteLine (X: + pX ); fixed (pY = &(p1.Y)) { //manejar pY *pY = 10; System.Console.WriteLine (Y: + pY ); } } ... ...
13/38
Cdigo Inseguro
Interoperabilidad.
Se denomina managed code al cdigo que se puede ejecutar bajo el control del CLR y unmanaged code a aqul cuya ejecucin no puede ser controlada por el CLR y por tanto no pueden aplicrsele las reglas de control de seguridad del CLR ni la recoleccin de basura (garbage collector). El managed code necesita en muchas ocasiones operar con el unmanaged code (cdigo nativo) existente. Incluso habr casos en los que sea necesario desarrollar una parte de un proyecto en cdigo nativo e invocar tal cdigo nativo desde el cdigo IL que es ejecutado, de modo controlado (managed code), por el CLR. Para permitir esto, el CLR soporta dos formas de operacin con el cdigo nativo: Platform Invocation Services (P/Invoke). COM Interoperability.
Es importante no confundir unmanaged code con unsafe code. Este ltimo es managed code precedido por la palabra clave unsafe al que se le permite utilizar caractersticas no seguras (unsafe) del lenguaje C++, como son los punteros.
14/38
Cdigo Inseguro
Clase2.FunClase2 (); Clase3.FunClase3 (); System.Console.WriteLine(" "); System.Console.WriteLine("Para llamar a MessageBox pulse Enter: "); System.Console.ReadLine(); MessageBox(0, "Hola desde el API de Windows", "Mensaje invocado desde .NET", 0); } }
15/38
Cdigo Inseguro
Figura 13.9
COM interoperability.
El CLR ofrece soporte tanto para utilizar componentes COM desde C# como para utilizar objetos C# desde componentes COM y desde cdigo nativo en general como si los objetos C# fuesen componentes COM. La interoperabilidad entre componentes COM y C# puede realizarse mediante enlace temprano (en compilacin) o tardo (en ejecucin). Utilizacin de componentes COM desde .NET. El uso de componentes COM desde C# es diferente dependiendo de si se utiliza enlace temprano o tardo. Utilizacin de componentes COM desde .NET mediante enlace temprano. Para poder utilizar un componente COM desde .NET de modo que queden todas las referencias resueltas en tiempo de compilacin (enlace temprano o early binding) es necesario que exista un objeto que siga la tecnologa .NET (para poder incluirlo en el cdigo .NET) y que exponga las interfaces del componente COM. A este objeto se le llama Runtime Callable Wrapper (RCW) y acta como proxy que utiliza .NET para acceder al componente COM. El RCW se encarga de traducir las llamadas que desde .NET se hagan a sus mtodos en las llamadas correctas al componente COM. Tambin se encarga de traducir la respuesta del componente COM de modo que pueda ser utilizado desde .NET y de controlar el ciclo de vida del componente COM (Addref, Release...). Para crear el RCW correspondiente a un componente COM se ha de utilizar TlbImp.exe. Por ejemplo: supnga que se dispone de un componente COM contenido en la dll quartz.dll (C:\Winnt\Sustem32\quartz.dll) y que se desea utilizar desde .NET, en concreto desde una aplicacin C#. Los pasos a seguir son: 1) Crear el RCW correspondiente al componente contenido en quartz.dll y copiarlo en el directorio de la aplicacin .NET que lo va a utilizar (no tiene porque ser as):
tlbimp c:\winnt\system32\quartz.dll /out:QuartzTypeLib.dll
16/38
Cdigo Inseguro
17/38
Cdigo Inseguro
El resultado es:
Figura 13.10 Este mismo ejemplo, hecho desde el Visual Studio .NET es ms sencillo gracias al cuadro de dilogo del men principal Proyecto/Agregar Referencia:
18/38
Cdigo Inseguro
Figura 13.11 Tras aceptar la librera seleccionada quartz.dll Visual Studio muestra un mensaje indicando que no existe el RCW para el componente contenido en quartz.dll y preguntando si se desea que lo cree.
Figura 13.12 Suponiendo que se acepta, Visual Studio .NET crea una dll llamada
este momento, la aplicacin puede utilizar la clase o, mejor dicho, las clases del paquete
QuartzTypeLib (puede haber ms de una clase o componente en una dll). En el explorador de soluciones se ve que aparece una referencia a QuartzTypeLib.
19/38
Cdigo Inseguro
Figura 13.13 Una de las ventajas que da Visual Studio .NET es que muestra ayuda contextual al escribir el cdigo que utiliza la referencia aadida (en este caso QuartzTypeLib).
Figura 13.14 Nota: En caso de que el componente est en una dll no incluida por defecto en la pestaa COM del cuadro de dilogo Agregar referencia puede utilizarse el botn Examinar para buscar e incluir la dll que se desee. 20/38
Cdigo Inseguro
Utilizacin de componentes COM desde .NET mediante enlace tardo. Cuando se utiliza enlace tardo para invocar los mtodos de un componente COM desde una aplicacin, sta ha de obtener la direccin de tales mtodos durante la ejecucin. Es decir, al compilar la aplicacin nada se sabe sobre la direccin de los componentes que va a utilizar la aplicacin. En enlace tardo no es necesario crear el RCW para el componente COM. Se ha de utilizar el mtodo GetTypefromProgID de la clase Type. Los pasos a seguir para utilizar un componente COM mediante enlace tardo son: 1) Incluir el namespace System.Interop.InteropSevices. 2) Crear un objeto Type para el componente COM utilizando Type.GetTypeFromProgID() o Type.GetTypeFromCLSID(). 3) Crear un componente COM utilizando Activator.CreateInstance(). 4) Llamar a los mtodos del componente COM utilizando el mtodo InvokeMember del objeto Type. El enlace tardo ya es conocido de un tema anterior y se puede observar que se sigue una idea similar al llamar a componentes COM mediante enlace tardo. Es importante saber que cuando se invoca a los mtodos de un componente COM mediante enlace tardo, la invocacin se hace utilizando la interface IDispatch. En el siguiente ejemplo va a intentarse invocar utilizando enlace tardo a los mtodos RenderFile y Run del componente FilgraphManager, contenido en Quartz.dll. Por supuesto, no hay que aadir una referencia a Quartz.dll en el proyecto.
using System; using System.Reflection; using System.Runtime.InteropServices; namespace COMInterop_Enlace_Tardio_Consola { /// <summary> /// Summary description for Aplicacion_COMInterop_Consola. /// </summary> public class Aplicacion_COMInterop_Consola_Enlace_Tardio { public Aplicacion_COMInterop_Consola_Enlace_Tardio() { // // TODO: Add constructor logic here // } public static void Main() { Type objTypeQuartz; object objQuartz; object[] arObjs = {@"C:\Archivos de programa\ Microsoft.NET\FrameworkSDK\Samples\ technologies\remoting\advanced\ remotingcom\mediaplayer\client\clock.avi"};
21/38
Cdigo Inseguro
objTypeQuartz = Type.GetTypeFromProgID("Quartz.FilgraphManager"); objQuartz = Activator.CreateInstance(objTypeQuartz); objTypeQuartz.InvokeMember("RenderFile", BindingFlags.InvokeMethod, null, objQuartz, arObjs); objTypeQuartz.InvokeMember("Run", BindingFlags.InvokeMethod, null, objQuartz, null); Console.WriteLine("Pulse Enter para continuar."); Console.ReadLine(); } } }
22/38
Cdigo Inseguro
Figura 13.16 La excepcin se lanza al intentar crear un objeto del tipo FilgraphManager, es decir, al ejecutar la lnea:
objQuartz = Activator.CreateInstance(objTypeQuartz);
ya que objTypeQuartz es null y no una referencia a un objeto. El problema real esta en la lnea anterior:
objTypeQuartz= Type.GetTypeFromProgID("Quartz.FilgraphManager");
El problema es que no est registrado el ProgID de FilgraphManager. La verdad es que no est registrado ni siquiera FilgraphManager. Para comprobarlo no hay ms que mostrar el registro del sistema y buscarlo.
Figura 13.17
23/38
Cdigo Inseguro
24/38
Cdigo Inseguro
Figura 13.19 Si se busca FilgraphManager, tampoco se encontrar. Esto puede hacer sospechar que no est registrado, pero la verdad es que s lo est (puede ejecutarse regsvr32 C:\Winnt\System32\Quartz.dll para asegurarse). Si se busca Quartz:
25/38
Cdigo Inseguro
Figura 13.21 Es decir, Quartz.dll s est registrada y se conoce su CLSID. Podra pensarse que tal vez valga este CLSID, aunque el que se quiere es el de FilgraphManager, que no se encuentra y por tanto cambiar el cdigo de modo que se utilice el CLSID, en lugar del ProgID:
using System; using System.Reflection; using System.Runtime.InteropServices; namespace COMInterop_Enlace_Tardio_Consola { /// <summary> /// Summary description for Aplicacion_COMInterop_Consola. /// </summary> public class Aplicacion_COMInterop_Consola_Enlace_Tardio { public Aplicacion_COMInterop_Consola_Enlace_Tardio() { // // TODO: Add constructor logic here // } public static void Main() { Type objTypeQuartz; object objQuartz;
26/38
Cdigo Inseguro
object[] arObjs = {@"C:\Archivos de programa\Microsoft.NET\FrameworkSDK\Samples\technolog ies\remoting\advanced\remotingcom\mediaplayer\client\ clock.avi"}; System.Guid clasid = new System.Guid("70E102B0-555611CE-97C0-00AA0055595A"); objTypeQuartz = Type.GetTypeFromCLSID(clasid); objQuartz = Activator.CreateInstance(objTypeQuartz); objTypeQuartz.InvokeMember("RenderFile", BindingFlags.InvokeMethod, null, objQuartz, arObjs); objTypeQuartz.InvokeMember("Run", BindingFlags.InvokeMethod, null, objQuartz, null);
Pero en tiempo de ejecucin sigue lanzando una excepcin (en modo no debug):
Figura 13.22 Podra utilizarse el CLSID pero: Tendra que ser el CLSID del componente deseado. El componente deseado tendra que soportar la interface IDispatch.
Llegar aqu y no realizar un ejemplo que funcione deja la duda en el aire, de modo que habr que realizar un ejemplo vlido.Hay que buscar un componente registrado que tenga un progID (o un versionIndependentProgID) o un CLSID y que soporte la interface COM IDispatch. Powerpoint.Application puede ser el componente que cumpla tal ejemplo. 27/38
Cdigo Inseguro
28/38
Cdigo Inseguro
objTypeApplicationPowerPoint = Type.GetTypeFromProgID("PowerPoint.Application"); objApplicationPowerPoint = Activator.CreateInstance(objTypeApplicationPowerPoint ); objTypeApplicationPowerPoint.InvokeMember("Activate", BindingFlags.InvokeMethod, null, objApplicationPowerPoint, null); Console.WriteLine("Pulse Enter para continuar."); Console.ReadLine(); } } }
Y el resultado de ejecutarla:
29/38
Cdigo Inseguro
Figura 13.25 Utilizacin de componentes .NET desde componentes COM y dll nativas. Lo ms comn es que al desarrollar cdigo .NET se necesite, en ocasiones, utilizar componentes COM existentes o nuevos. No obstante, tambin puede darse el caso contrario, es decir, la necesidad de invocar componentes .NET desde cdigo nativo Windows (componentes COM o funciones de dll). Para poder utilizar componentes .NET como si fuesen componentes COM es necesario que los componentes .NET estn registrados (en el registro del sistema o registry) y exista un proxy al que se invoque a travs de los datos registrados, siendo el proxy el que realmente invocar los mtodos del objeto o componente .NET. La aplicacin RegAsm (Register Assembly) registra un assembly y todos sus clases (componentes), creando adems el proxy. Se puede decir que es la inversa de TlbImp. Una vez registrado un assembly hay que realizar varios pasos para que sea realmente accesible como un componente COM: 1. Crear un nombre fuerte (strong name) para asignarlo al assembly. El nombre fuerte identificar al assembly (consta de un nombre de tipo texto, un nmero de versin, informacin sobre la cultura si se ha indicado, una clave pblica y una firma digital).
sn k assemblyx.snk
30/38
Cdigo Inseguro
2. Crear un fichero AssemblyInfo.cs que contenga una referencia al fichero con el nombre fuerte:
using System.Reflection; [assembly: AssemblyKeyFile(assemblyx.snk)]
5. Copiar la librera assemblyx.dll a la cach global (si no se hace, no ser accesible desde el cdigo nativo (COM y funciones de dll no COM):
gacutil /i assemblyx.dll
En el siguiente ejemplo se crea una clase muy sencilla llamada Doble (en el fichero N_Doble.cs), que contiene un mtodo Doblar que multiplica por dos el valor que recibe como parmetro.
namespace N_Doble { using system; public class Doble { public int Doblar(int num) { return (num * 2); } } }
31/38
Cdigo Inseguro
Figura 13.26 Una vez generada la librera, se utiliza regasm para registrarla en el registro del sistema.
Figura 13.27 En el registro del sistema ha de encontrarse una tentrada para el componente Doble.
32/38
Cdigo Inseguro
Figura 13.28 Ahora es necesario copiar N_Doble.dll a la cach global para que pueda ser accedida desde el cdigo Windows nativo. El primer paso es generar un strong name o nombre fuerte (es una buena idea generarlo y depositarlo en el archivo N_Doble.snk).
Figura 13.29
33/38
Cdigo Inseguro
Una vez se tiene el fichero con el nombre fuerte, ha de ser referenciado desde un fichero que luego se aadir al assembly N_Doble.dll. En este caso se llama AssemblyInfo.cs y contiene:
using System.Reflection; [assembly: AssemblyKeyFile("N_Doble.snk")]
Antes de aadir esta informacin a N_Doble.dll habr que generar un mdulo a partir de AssemblyInfo.cs.
Figura 13.30 Para aadir la informacin de tal mdulo a N_Doble.dll lo que realmente se har es regenerar N_Doble.dll a partir de N_Doble.cs indicando que se aada el mdulo AssemblyInfo.dll.
Figura 13.31
34/38
Cdigo Inseguro
Una vez se ha obtenido N_Doble.dll con la informacin de AssemblyInfo.dll slo resta copiarlo a la cach global.
Figura 13.32 A partir de este momento es posible utilizar desde cdigo Windows nativo el componente Doble. Un posible ejemplo puede ser un script (VBScript) contenido, por ejemplo, en una pgina Web:
//Fichero PrueballamarNETdesdeCOM.html <html> <head> <title> Prueba de llamada a .NET desde Windows nativo </title> </head> <body> <script language=VBScript> Option Explicit Dim objeto_N_Doble Dim Numero Dim Resultado Set objeto_N_Doble = CreateObject("N_Doble.Doble") Numero = InputBox("Nmero a doblar") Resultado = objeto_N_Doble.Doblar(CLng(Numero)) Call MsgBox(Resultado) </script> </body> </html>
Al cargar la pgina:
35/38
Cdigo Inseguro
Figura 13.33
36/38
Cdigo Inseguro
Figura
13.34
37/38
Cdigo Inseguro
38/38