La presentazione è in caricamento. Aspetta per favore

La presentazione è in caricamento. Aspetta per favore

P Invoke e COM Interoperability Raffaele Rialdi Visual Developer Security MVP MVP Profile:

Presentazioni simili


Presentazione sul tema: "P Invoke e COM Interoperability Raffaele Rialdi Visual Developer Security MVP MVP Profile:"— Transcript della presentazione:

1 P Invoke e COM Interoperability Raffaele Rialdi Visual Developer Security MVP MVP Profile: latform

2 Agenda Platform Invocation ServicesPlatform Invocation Services COMCOM Usare oggetti COM in dotnetUsare oggetti COM in dotnet Usare Activex in dotnetUsare Activex in dotnet Esporre oggetti COM da dotnetEsporre oggetti COM da dotnet Esporre Activex da dotnetEsporre Activex da dotnet Reverse P/InvokeReverse P/Invoke

3 Platform Invoke Servizio del framework che permette di chiamare le API esportate in una DLL "C-style"Servizio del framework che permette di chiamare le API esportate in una DLL "C-style" Gli attrezzi del mestiere sono dentro System.Runtime.InteropServicesGli attrezzi del mestiere sono dentro System.Runtime.InteropServices Il protagonista è l'attributo DllImportAttribute che svolge (tra le altre cose) le classiche operazioni di:Il protagonista è l'attributo DllImportAttribute che svolge (tra le altre cose) le classiche operazioni di: LoadLibrary (carica la dll in memoria) – Free (scarica la dll)LoadLibrary (carica la dll in memoria) – Free (scarica la dll) GetProcAddress (ottiene un puntatore alla funzione richiesta)GetProcAddress (ottiene un puntatore alla funzione richiesta) Marshalling (mapping e passaggio parametri)Marshalling (mapping e passaggio parametri) Molto aiuto viene dal wiki con molte dichiarazioni già pronte per la API di WindowsMolto aiuto viene dal wiki con molte dichiarazioni già pronte per la API di Windowswww.pinvoke.net

4 DllImportAttribute step-by-step Ottenere la documentazione (MSDN,...)Ottenere la documentazione (MSDN,...) Cercare la funzione prototipoCercare la funzione prototipo Cercare il nome della dll dove è implementataCercare il nome della dll dove è implementata [DllImport("PowrProf.dll")] extern static bool IsPwrHibernateAllowed(); _ Function IsPwrHibernateAllowed() As Boolean End Function _ Function IsPwrHibernateAllowed() As Boolean End Function

5 DllImportAttribute step-by-step [DllImport("User32.dll")] extern static int MessageBox(IntPtr hWnd, string Text, string Caption, int uType); MSDN public enum MessageBoxUType { MB_OK = 0x , MB_OKCANCEL = 0x , MB_ABORTRETRYIGNORE = 0x , MB_YESNOCANCEL = 0x , MB_YESNO = 0x , MB_RETRYCANCEL = 0x , MB_CANCELTRYCONTINUE = 0x } A MANO ma a volte su: dichiarare con const oppure enum (meglio)

6 DllImportAttribute Nomi delle API Le API di Windows che usano stringhe esistono in due versioni: MessageBoxA (Ansi), MessageBoxW (Wide = Unicode)Le API di Windows che usano stringhe esistono in due versioni: MessageBoxA (Ansi), MessageBoxW (Wide = Unicode) ExactSpelling = false aggiunge automaticamente questo suffisso (A o W)ExactSpelling = false aggiunge automaticamente questo suffisso (A o W) Il default che è DllImport("MessageBox") cerca in sequenza:Il default che è DllImport("MessageBox") cerca in sequenza: MessageBox, MessageBoxA, MessageBoxW, (N=numero che rappresenta la dimensione dei parametri del metodo)MessageBox, MessageBoxA, MessageBoxW, (N=numero che rappresenta la dimensione dei parametri del metodo) È possibile cambiare il nome esatto tramite "EntryPoint"È possibile cambiare il nome esatto tramite "EntryPoint" A volte aiuta il "dependancy walker" (http://www.dependencywalker.com/)A volte aiuta il "dependancy walker" (http://www.dependencywalker.com/) [DllImport("User32.dll", EntryPoint="MessageBoxW", ExactSpelling=true, CharSet=CharSet.Auto)] extern static int MBox(IntPtr hWnd, string Text, string Caption, int uType);

7 DllImportAttribute Calling Convention Le calling convention sono una sorta di contratto alla compilazione che prevede:Le calling convention sono una sorta di contratto alla compilazione che prevede: come passare gli argomenti delle funzioni ed il valore di ritornocome passare gli argomenti delle funzioni ed il valore di ritorno quali registri della CPU devono essere salvatiquali registri della CPU devono essere salvati Le quattro convenzioni più usate oggi sono:Le quattro convenzioni più usate oggi sono: __cdeclusato dalle librerie C e numerose API__cdeclusato dalle librerie C e numerose API __stdcallconosciuta anche come "pascal", usata dalle Win32 API__stdcallconosciuta anche come "pascal", usata dalle Win32 API __fastcallusa i registri per passare gli argomenti__fastcallusa i registri per passare gli argomenti __thiscalldefault per le chiamate a funzioni membro in C++__thiscalldefault per le chiamate a funzioni membro in C++ Perché chiamata a funzione abbia successo la calling convention deve essere corretta (StdCall è il default)Perché chiamata a funzione abbia successo la calling convention deve essere corretta (StdCall è il default) [DllImport("User32.dll", CallingConvention=CallingConvention.StdCall)] extern static int MessageBox(IntPtr hWnd, string Text, string Caption, int uType);

8 DllImportAttribute Gestione errori Le Win32 mantengono una variabile di stato per gli erroriLe Win32 mantengono una variabile di stato per gli errori Problema: se dopo l'API con errore ne vengono eseguite altre senza errore, questo va persoProblema: se dopo l'API con errore ne vengono eseguite altre senza errore, questo va perso Usare via PInvoke la funzione GetLastError() è sbagliatoUsare via PInvoke la funzione GetLastError() è sbagliato DLLImport provvede alla proprietà SetLastErrorDLLImport provvede alla proprietà SetLastError L'errore viene letto subito dal CLR e messo da parteL'errore viene letto subito dal CLR e messo da parte Può essere letto con il metodo Marshal.GetLastWin32Error()Può essere letto con il metodo Marshal.GetLastWin32Error() [DllImport("User32.dll", SetLastError=true)] extern static int MessageBox(IntPtr hWnd, string Text, string Caption, int uType);

9 Uno sguardo in memoria Gli oggetti del CLR devono stare nel managed heapGli oggetti del CLR devono stare nel managed heap I buffer, blob, strutture dati 'classiche' devono stare nell'unmanaged heapI buffer, blob, strutture dati 'classiche' devono stare nell'unmanaged heap Il problema è quindi il marshalling dei dati, cioè copiare e/o mappare i dati da un mondo all'altroIl problema è quindi il marshalling dei dati, cioè copiare e/o mappare i dati da un mondo all'altro La bella notizia è che le tecniche di marshalling valgono anche per l'interoperabilità COMLa bella notizia è che le tecniche di marshalling valgono anche per l'interoperabilità COM Managed heap Managed Stack Bitmap String DateTime Int32 ref String ref Bitmap Unmanaged heap char[...] byte[...] BSTR int FILETIME Il problema del marshalling "Come mappare i tipi?"

10 Marshalling: blittable types I blittable types sono i tipi che hanno una rappresentazione identica sia nel mondo managed che unmanaged:I blittable types sono i tipi che hanno una rappresentazione identica sia nel mondo managed che unmanaged: Byte, SByteByte, SByte Int16, UInt16Int16, UInt16 Int32, UInt32Int32, UInt32 Int64, UInt64Int64, UInt64 IntPtr, UIntPtrIntPtr, UIntPtr SingleSingle DoubleDouble Array monodimensionali (UInt32[], Byte[],...)Array monodimensionali (UInt32[], Byte[],...) Value types (strutture) contenenti i tipi appena citatiValue types (strutture) contenenti i tipi appena citati Array e classi contenenti blittable types vengono "pinned" in memoria invece di copiare il loro valore nel mondo unmanaged.Array e classi contenenti blittable types vengono "pinned" in memoria invece di copiare il loro valore nel mondo unmanaged. Anche se "pinned" richiedono comunque l'applicazione degli attributi direzionali [in] o [out] quando richiestiAnche se "pinned" richiedono comunque l'applicazione degli attributi direzionali [in] o [out] quando richiesti

11 Marshalling: le stringhe CharSet influenza la scelta Ansi / Unicode di tutti i parametriCharSet influenza la scelta Ansi / Unicode di tutti i parametri Si può applicare [MarshalAs(...)] al parametroSi può applicare [MarshalAs(...)] al parametro La direzione del parametro è fondamentaleLa direzione del parametro è fondamentale Se la stringa è [in] nella API, si usa StringSe la stringa è [in] nella API, si usa String Se la stringa è [out] o [in, out] si usa StringBuilder preallocando lo spazioSe la stringa è [out] o [in, out] si usa StringBuilder preallocando lo spazio Da MSDN:Da MSDN: MSDN [DllImport("Kernel32.dll")] extern static uint GetCurrentDirectory(uint Size, StringBuilder Buffer); [DllImport("User32.dll)] extern static int MessageBox(IntPtr hWnd, string Text, string Caption, int uType); Normalmente Win9x Normalmente WinNT +

12 Marshalling: strutture di dati Il CLR non garantisce l'ordine e dimensione dei dati nella strutturaIl CLR non garantisce l'ordine e dimensione dei dati nella struttura il CLR ottimizza l'allineamento dei dati guadagnando spazio e performanceil CLR ottimizza l'allineamento dei dati guadagnando spazio e performance la dimensione di un oggetto managed è sempre e solo presunta (Marshal.SizeOf indica la dimensione dell'oggetto dopo il marshalling)la dimensione di un oggetto managed è sempre e solo presunta (Marshal.SizeOf indica la dimensione dell'oggetto dopo il marshalling) a questo proposito: questo proposito: Per ovviare a questo "problema" esiste StructLayoutAttributePer ovviare a questo "problema" esiste StructLayoutAttribute Pack consente di imporre l'allineamento (il default è 8)Pack consente di imporre l'allineamento (il default è 8) Size consente di imporre la dimensione della struttura (lasciare spazio,...)Size consente di imporre la dimensione della struttura (lasciare spazio,...) Si possono anche realizzare le "Union" grazie a "Explicit"Si possono anche realizzare le "Union" grazie a "Explicit" Si usa ref o out (ByRef) quando si vuole passare il puntatore all'oggetto. Diversamente viene passato by valueSi usa ref o out (ByRef) quando si vuole passare il puntatore all'oggetto. Diversamente viene passato by value [StructLayout(LayoutKind.Sequential)] struct MyStruct { char c; int i; short s; } union MyUnion { int x; float f; } [StructLayout (LayoutKind.Explicit)] struct MyUnion { [FieldOffset( 0 )] int x; [FieldOffset( 0 )] float f; }

13 Marshalling di array Possono esistere più dichiarazioni PInvoke valide per una stessa chiamataPossono esistere più dichiarazioni PInvoke valide per una stessa chiamata Usare la falsa riga di dichiarazioni come quelle di la falsa riga di dichiarazioni come quelle di Array di stringheArray di stringhe Array di struttureArray di strutture L'attributo MarshalAs permette di informare il CLR quando la dimensione è prefissataL'attributo MarshalAs permette di informare il CLR quando la dimensione è prefissata A volte è necessario fare manualmenteA volte è necessario fare manualmente Il parametro viene dichiarato IntPtr (puntatore)Il parametro viene dichiarato IntPtr (puntatore) Si usano i metodi StructureToPtr e PtrToStructure della classe MarshalSi usano i metodi StructureToPtr e PtrToStructure della classe Marshal Alla fine li vedremo in un esempioAlla fine li vedremo in un esempio Tip: In caso di NullReferenceException, provare a imporre il parametro ref (ByRef)Tip: In caso di NullReferenceException, provare a imporre il parametro ref (ByRef) int f(char **ppArray, int size); [ DllImport("...")] public static extern int f([in, out]string[] strings, int size); int f(POINT *pPOINT, int size); [ DllImport( "..." )] public static extern int f([In, Out] MyPoint[] points, int size); [MarshalAs(UnmanagedType.ByValArray, SizeConst=128)]

14 Marshalling di callback Le Callback usate nelle Win32 API sono puntatori a funzioniLe Callback usate nelle Win32 API sono puntatori a funzioni.NET non ha puntatori a funzioni, ma i delegate che sono type-safe.NET non ha puntatori a funzioni, ma i delegate che sono type-safe Esempio EnumDesktopWindowsEsempio EnumDesktopWindows [DllImport("User32.dll")] public extern static bool EnumDesktopWindows(IntPtr hDesktop, EnumWindowsProcDelegate lpfn, uint lParam); public delegate bool EnumWindowsProcDelegate(IntPtr hwnd, uint lParam);

15 Pinning della memoria managed Quando si passa un reference type viene copiato il reference e fatto il pinning della memoria nel managed heapQuando si passa un reference type viene copiato il reference e fatto il pinning della memoria nel managed heap il pinning automatico funziona spesso...il pinning automatico funziona spesso ad esempio non può funzionare per le chiamate asincrone... ad esempio non può funzionare per le chiamate asincrone Quando si passa un value type il valore viene copiato nella memoria unmanagedQuando si passa un value type il valore viene copiato nella memoria unmanaged Se si può usare un value type, questo risolve il problema di cui sopraSe si può usare un value type, questo risolve il problema di cui sopra Per eseguire il pinning da C# e VB si usa GCHandlePer eseguire il pinning da C# e VB si usa GCHandle Free rilascia l'handle e permette al GC di muovere il blocco di memoriaFree rilascia l'handle e permette al GC di muovere il blocco di memoria string s = "blah blah"; GCHandle pin = GCHandle.Alloc(s, GCHandleType.Pinned); try {... } finally { pin.Free(); }

16 Agenda Platform Invocation ServicesPlatform Invocation Services COMCOM Usare oggetti COM in dotnetUsare oggetti COM in dotnet Usare Activex in dotnetUsare Activex in dotnet Esporre oggetti COM da dotnetEsporre oggetti COM da dotnet Esporre Activex da dotnetEsporre Activex da dotnet Reverse P/InvokeReverse P/Invoke

17 Il mondo COM Ci sono molte differenzeCi sono molte differenze Serve quindi un wrapperServe quindi un wrapper I wrapper sono diversi a seconda se si espone un oggetto COM a.NET o viceversaI wrapper sono diversi a seconda se si espone un oggetto COM a.NET o viceversa COM.NET CreateInstancenew Reference count Garbage Collector QueryInterfacecast Errori via HRESULT Eccezioni Guid Strong name Type library Metadati ApartmentsMTA-style

18 Usare oggetti COM da.NET Visual Studio.NETVisual Studio.NET TLBimpTLBimp Una volta disponibile l'assembly di interopUna volta disponibile l'assembly di interop Gli oggetti COM si usano come fossero managed (si usa il wrapper)Gli oggetti COM si usano come fossero managed (si usa il wrapper) Si istanziano con new e si chiamano proprietà e metodiSi istanziano con new e si chiamano proprietà e metodi addref/release sono gestiti dall'infrastruttura (RCW)addref/release sono gestiti dall'infrastruttura (RCW)

19 Dietro le quinte RCW = Runtime Callable WrapperRCW = Runtime Callable Wrapper creato al runtime per parlare con il mondo comcreato al runtime per parlare con il mondo com si occupa di eseguire il marshalling dei tipisi occupa di eseguire il marshalling dei tipi esiste un RCW per ogni oggetto (non interfaccia) COMesiste un RCW per ogni oggetto (non interfaccia) COM si occupa di chiamare Addref/Release/QueryInterfacesi occupa di chiamare Addref/Release/QueryInterface L'oggetto referenziato da RCW è scaricato dalla memoria se il suo reference counter è 0 e cioè se:L'oggetto referenziato da RCW è scaricato dalla memoria se il suo reference counter è 0 e cioè se: RCW viene scaricato dal Garbage Collector oppureRCW viene scaricato dal Garbage Collector oppure viene fatto un esplicito Marshal.ReleaseComObjectviene fatto un esplicito Marshal.ReleaseComObject RCW wrappa IEnumVariant, IDispatch, IUnknown, IErrorInfoRCW wrappa IEnumVariant, IDispatch, IUnknown, IErrorInfo.NETCOMRCW

20 Come customizzare RCW Si può customizzare RCW in due modiSi può customizzare RCW in due modi Modificando la type libraryModificando la type library si ricava l'IDL (se non è dispobile si può importare con il typelib viewer di Oleview.exe)si ricava l'IDL (se non è dispobile si può importare con il typelib viewer di Oleview.exe) si aggiungono gli attributi IDL grazie alla keyword custom che permette di modificare namespace e il nome dotnet del wrapper:si aggiungono gli attributi IDL grazie alla keyword custom che permette di modificare namespace e il nome dotnet del wrapper: si ricompila con midl /Oicfsi ricompila con midl /Oicf si importa con TLBImp oppure VS.netsi importa con TLBImp oppure VS.net Modificando l'RCWModificando l'RCW si decompila l'assembly generato da TLBImpsi decompila l'assembly generato da TLBImp si modifica l'ILsi modifica l'IL si ricompilasi ricompila

21 COM da.NET: TLBImp [ComImport, ClassInterface((short) 0), Guid("EF70C490-E7FE-11D2-AB0D-00A02457BBE9"), TypeLibType((short) 2), ComSourceInterfaces("mailctl.interop._IMailerEvents\0")] public class MailerClass : IMailer, Mailer, _IMailerEvents_Event { // Methods [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime), DispId(3)] public virtual extern void IsValidName([In, MarshalAs(UnmanagedType.BStr)] string Recipient); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime), DispId(2)] public virtual extern void Logoff(); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime), DispId(1)] public virtual extern void Logon([In, MarshalAs(UnmanagedType.BStr)] string Profile, [In] int bUI); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime), DispId(4)] public virtual extern void SendMail([In, MarshalAs(UnmanagedType.BStr)] string Subject, [In, MarshalAs(UnmanagedType.BStr)] string Message, [In, MarshalAs(UnmanagedType.BStr)] string OriginatorAddress, [In, MarshalAs(UnmanagedType.BStr)] string AddrTo, [In, MarshalAs(UnmanagedType.BStr)] string AddrCc, [In, MarshalAs(UnmanagedType.BStr)] string AddrCcn, [In, MarshalAs(UnmanagedType.BStr)] string PathNames, [In] int bReceipt, [In] int bUI); // Properties [DispId(5)] public virtual int MapiIsInstalled { [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime), DispId(5)] get; } } TLBImp usa la classe la classeTypeLibConverter

22 Usare ActiveX in dotnet Winform può solo usare controlli che derivano da ControlWinform può solo usare controlli che derivano da Control Ci vuole quindi un wrapperCi vuole quindi un wrapper Il controllo wrapper è AxHost che deriva da Control e ospita l'ActiveXIl controllo wrapper è AxHost che deriva da Control e ospita l'ActiveX Come si genera il wrapper?Come si genera il wrapper? Aggiungendo alla toolbar dei controlli l'ActiveXAggiungendo alla toolbar dei controlli l'ActiveX Usando da command prompt l'utility AxImp.exeUsando da command prompt l'utility AxImp.exe Si può customizzare il comportamento?Si può customizzare il comportamento? si, anche se serve raramentesi, anche se serve raramente il punto di partenza è generare il wrapper e guardarlo con reflectoril punto di partenza è generare il wrapper e guardarlo con reflector Si può usare un ActiveX facendo Add-Reference?Si può usare un ActiveX facendo Add-Reference? dipende dal controllo ma nella maggior parte dei casi no perchè l'ActiveX esegue il dispatch dei messaggi tramite message pump della finestra che viene creata solo se è 'visuale'dipende dal controllo ma nella maggior parte dei casi no perchè l'ActiveX esegue il dispatch dei messaggi tramite message pump della finestra che viene creata solo se è 'visuale'

23 Primary Interop Assembly PIA Devono essere fornite dall'autore del componente COMDevono essere fornite dall'autore del componente COM Deve esistere una sola PIA per ogni oggetto COMDeve esistere una sola PIA per ogni oggetto COM Una sola PIA può gestire più versioni dello stesso oggetto COMUna sola PIA può gestire più versioni dello stesso oggetto COM Devono essere strong-namedDevono essere strong-named Devono esporre tutti gli oggetti COM originali con gli stessi guidDevono esporre tutti gli oggetti COM originali con gli stessi guid In caso di componenti esterni referenziatiIn caso di componenti esterni referenziati Non li devono ridefinireNon li devono ridefinire Devono referenziare le loro PIADevono referenziare le loro PIA Devono essere marcati con l'attributo PrimaryInteropAssemblyAttributeDevono essere marcati con l'attributo PrimaryInteropAssemblyAttribute 1.Usare TLBImp 2.Creare il wrapper manualmente assegnandogli: strong namestrong name GuidAttribute (LIBID guid)GuidAttribute (LIBID guid) attributo PrimaryInteropAssemblyAttributeattributo PrimaryInteropAssemblyAttribute

24 Agenda Platform Invocation ServicesPlatform Invocation Services COMCOM Usare oggetti COM in dotnetUsare oggetti COM in dotnet Usare Activex in dotnetUsare Activex in dotnet Esporre oggetti COM da dotnetEsporre oggetti COM da dotnet Esporre Activex da dotnetEsporre Activex da dotnet Reverse P/InvokeReverse P/Invoke

25 Esporre oggetti COM da.NET CCW = COM Callable WrapperCCW = COM Callable Wrapper creato al runtimecreato al runtime si occupa di eseguire il marshalling dei tipisi occupa di eseguire il marshalling dei tipi esiste un CCW per ogni oggetto dotnetesiste un CCW per ogni oggetto dotnet l'oggetto dotnet come sempre sarà dato al GC solo se tutti i reference (del CCW ed altri) vengono rilasciatil'oggetto dotnet come sempre sarà dato al GC solo se tutti i reference (del CCW ed altri) vengono rilasciati CCW espone sempre una "dual interface" (IUnknown + IDispatch)CCW espone sempre una "dual interface" (IUnknown + IDispatch) CCW espone IEnumVariant (for each di vb6) per i tipi dotnet che implementano IEnumerable, IErrorInfo/HRESULT per le eccezioni e ovviamente IDispatch/IUnknownCCW espone IEnumVariant (for each di vb6) per i tipi dotnet che implementano IEnumerable, IErrorInfo/HRESULT per le eccezioni e ovviamente IDispatch/IUnknown.NETCOMCCW

26 COM object step-by-step Creare una class library con strong nameCreare una class library con strong name Dare una versione custom all'oggettoDare una versione custom all'oggetto La differenza di versioning è un problema rilevante con COMLa differenza di versioning è un problema rilevante con COM Scrivere la classe dotnetScrivere la classe dotnet Decorarla con gli attributi di interop che customizzano il comportamento del CCWDecorarla con gli attributi di interop che customizzano il comportamento del CCW Registrarla con RegasmRegistrarla con Regasm Registrarla nella GACRegistrarla nella GAC Esportare la Type LibraryEsportare la Type Library [ClassInterface(ClassInterfaceType.AutoDual)][ComVisible(true)][Guid("D0C1F90F-59B2-4e06-B36F-CC835B14C2EC")] public class Adder { public Adder() {} public int Add(int x, int y) { return x + y; } public int Mul(int x, int y) { return x * y; }} regasm addercomserver.dll gacutil -i addercomserver.dll tlbexp addercomserver.dll /out:addercomserver.tlb

27 Registration-free Disponibile solo in Windows XP - SP2, e Windows 2003Disponibile solo in Windows XP - SP2, e Windows 2003 Evita la registrazione nel registry dei componenti COMEvita la registrazione nel registry dei componenti COM È necessario scrivere un manifest Win32È necessario scrivere un manifest Win32 Vantaggi:Vantaggi: più versioni dello stesso componente nello stesso PCpiù versioni dello stesso componente nello stesso PC xcopy deploymentxcopy deployment us/cpguide/html/cpconConfiguringNET-BasedComponentsForRegistration- FreeActivation.asphttp://msdn.microsoft.com/library/default.asp?url=/library/en- us/cpguide/html/cpconConfiguringNET-BasedComponentsForRegistration- FreeActivation.asphttp://msdn.microsoft.com/library/default.asp?url=/library/en- us/cpguide/html/cpconConfiguringNET-BasedComponentsForRegistration- FreeActivation.asphttp://msdn.microsoft.com/library/default.asp?url=/library/en- us/cpguide/html/cpconConfiguringNET-BasedComponentsForRegistration- FreeActivation.asp

28 Realizzare ActiveX in dotnet Activex specifiche OC96 + libro "Inside OLE"Activex specifiche OC96 + libro "Inside OLE" Per ActiveX si intende quindi oggetti 'visuali' e non i comuni oggetti COMPer ActiveX si intende quindi oggetti 'visuali' e non i comuni oggetti COM Task NON supportato ufficialmente da MicrosoftTask NON supportato ufficialmente da Microsoft Fattibile ma con non poche difficoltà. Strada sconsigliata.Fattibile ma con non poche difficoltà. Strada sconsigliata. Per IE esiste la possibilità di mostrare controlli Winform in una pagina htmlPer IE esiste la possibilità di mostrare controlli Winform in una pagina html migliore sicurezzamigliore sicurezza nessuna dialog di richiesta certificatonessuna dialog di richiesta certificato tecnica poco diffusa in attesa della diffusione del frameworktecnica poco diffusa in attesa della diffusione del framework Per le migrazioni di UI conviene il contrarioPer le migrazioni di UI conviene il contrario Fare l'hosting di Winform dentro MFC, etc.Fare l'hosting di Winform dentro MFC, etc.

29 Performance PInvoke 10 istruzioni x86PInvoke 10 istruzioni x86 COM 50 istruzioni x86COM 50 istruzioni x86 Ma poi c'è il marshalling (che è il più) dei parametriMa poi c'è il marshalling (che è il più) dei parametri Riduzione del numero di parametriRiduzione del numero di parametri Riduzione del numero di funzioni da chiamareRiduzione del numero di funzioni da chiamare Usare [in] e [out] per ridurre il numero di marshallingUsare [in] e [out] per ridurre il numero di marshalling In DllImport usare SetLastError=true solo se poi si chiama Marshal.GetLastWin32Error()In DllImport usare SetLastError=true solo se poi si chiama Marshal.GetLastWin32Error()

30 Agenda Platform Invocation ServicesPlatform Invocation Services COMCOM Usare oggetti COM in dotnetUsare oggetti COM in dotnet Usare Activex in dotnetUsare Activex in dotnet Esporre oggetti COM in dotnetEsporre oggetti COM in dotnet Esporre Activex in dotnetEsporre Activex in dotnet Reverse P/InvokeReverse P/Invoke

31 Reverse P/Invoke MSDN KB dice:MSDN KB dice:.... This requires a DLL export, which.NET Framework does not support. Managed code has no concept of a consistent value for a function pointer because these function pointers are proxies that are built dynamically. A che servono "DLL Export"?A che servono "DLL Export"? Global hookGlobal hook Control Panel AppletsControl Panel Applets Applicazione unmanaged chiama una API esposta da un assemblyApplicazione unmanaged chiama una API esposta da un assembly Si, si può fare! MA.... (c'è sempre un "ma")Si, si può fare! MA.... (c'è sempre un "ma") Certamente con C++, ma è troppo scontatoCertamente con C++, ma è troppo scontato Non con VB.NET, neppure con C#... ok, neanche con J#Non con VB.NET, neppure con C#... ok, neanche con J#

32 Reverse P/Invoke 1.Creare un progetto Class Library (C# o VB.NET) 2.Scrivere la funzione da esportare come API 3.Compilarla e disassemblarla con ILDasm ( ildasm /out=revsimple.il revsimple.dll ) 4.Modificare l'IL come segue:.corflags 0x invece di.corflags 0x corflags 0x invece di.corflags 0x Aggiungere in cima:.vtfixup [1] int32 fromunmanaged at VT_01.data VT_01 = int32(0)Aggiungere in cima:.vtfixup [1] int32 fromunmanaged at VT_01.data VT_01 = int32(0) Dentro la funzione da esportare aggiungere:.method public hidebysig static int32 modopt([mscorlib]System.Runtime.InteropServices.CallConvStdCall)Dentro la funzione da esportare aggiungere:.method public hidebysig static int32 modopt([mscorlib]System.Runtime.InteropServices.CallConvStdCall) CPlApplet(native int hwndCPl, unsigned int32 uMsg, [in][out] native int lParam1, [in][out] native int lParam2) cil managed {.vtentry 1 : 1.export [1] as CPlApplet CPlApplet(native int hwndCPl, unsigned int32 uMsg, [in][out] native int lParam1, [in][out] native int lParam2) cil managed {.vtentry 1 : 1.export [1] as CPlApplet Riassemblare: ilasm /out=hello.dll revsimple.il /dll Rinomina la funzione esportata Calling Convention

33 Reverse P/Invoke Control panel managed applet 1.Class library con una funzione chiamata: public static int CPlApplet( IntPtr hwndCPl, uint uMsg, [In,Out] IntPtr lParam1, [In,Out] IntPtr lParam2) 2.Dichiarazione di CPLINFO, NEWCPLINFO, CPL_... 3.Marshalling manuale dei parametri perché la lParam1 e lParam2 possono puntare a strutture diverse (CPLINFO o NEWCPLINFO) case CPLMessages.CPL_INQUIRE: AppletNumber = lParam1.ToInt32(); Info = (CPLINFO)Marshal.PtrToStructure(lParam2, typeof(CPLINFO)); Info.idIcon = 101; Info.idName = 201; Info.idInfo = 202; Info.lData = (IntPtr)1; Marshal.StructureToPtr(Info, lParam2, true); return 0; numeri delle risorse (prox slide)

34 Control panel managed applet Il problema delle risorse 4.Preparazione del file di risorse "resources.rc": 5.Compilazione delle risorse in res (command prompt di Visual Studio): rc resources.rc 6.Eventualmente aggiungere al file resources.rc le informazioni di versione perché quelle di vs.net vanno perse 101ICONDISCARDABLE"Italy.ico" STRINGTABLE DISCARDABLE BEGIN 201"Managed Applet" 202"Mostra le opzioni del managed applet" END icona applet nome sotto l'icona descrizione a fianco all'icona

35 Reverse P/Invoke Control panel managed applet 7.Embedding di risorse Win32 nell'assembly: c:\dev.net\Demo\Interop\RevPInvoke>csc /resource:obj\Debug\RevPInvoke.InteropWorkshop.resources /win32res:resources.res /target:library /out:bin\debug\RevPInvoke.dll *.cs 8.In alternativa usare "Resource Hacker" importando il file.res: 9.Registrarlo: HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Control Panel\Cpls ManagedApplet = path del.cpl risorse unmanaged (win32) dll nome dll compilare tutti i sorgenti risorse managed

36 Domande?


Scaricare ppt "P Invoke e COM Interoperability Raffaele Rialdi Visual Developer Security MVP MVP Profile:"

Presentazioni simili


Annunci Google