Published on

La interoperabilidad en .NET

Published in: Technology
  • Be the first to comment

  • Be the first to like this

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide
  • INTEROPERATION = Process of interacting with unmanaged code from within managed code
  • Interoperation es un nombre genérico que se refiera al proceso de interacutar con código no administrado desde código administrado.Es importante esta característica por:La gran cantidad de código legado en la que ya se invirtió y ya está probado.No se cuenta con API para todas las funciones que requiere el .NET Framework.
  • Interoperation

    1. 1. Interoperation<br />CHAPTER 13<br />
    2. 2. Interoperation<br />Interoperation is a generic name used to refer to the process of interacting with unmanaged code from within managed code.<br />The large amount of legacy code that was expensive to develop and has already been tested.<br />Not every Microsoft Windows API has been wrapped for the .NET Framework 2.0, so some tasks are possible only if you use Interoperation.<br />
    3. 3. Usingcomobjects<br />LESSON 1<br />
    4. 4. Lessonsummary<br />COM components can easily be consumed in a .NET application, although the reasons for doing so need to be carefully considered.<br />You can use the COM tab of the Add Reference dialog box to add a reference to registered COM components.<br />The TlbImp.exe tool is a command-line mechanism to import a COM component.<br />The out switch of the TlbImp.exe tool can be used to change the name of the assembly that will be imported from its original name to a preferred one.<br />The default behavior when catching System.Exception objects now catches both CLS-compliant and non-CLS-compliantexceptions.<br />The RuntimeCompatibilty attribute can be used to change whether non-CLS compliant exceptions will be trapped by default.<br />
    5. 5. ImportingTypeLibraries<br />Runtime Callable Wrapper (RCW): mechanism that serves as a proxy so that the .NET runtime can communicate with a COM component.<br />RCW handles the majority of the work between .NET and COM, including marshaling data types, handling events, and handling interfaces.<br />
    6. 6. ImportingTypeLibraries<br />Once a DLL has been registered, You have two ways to import registered COM DLLs:<br />Visual Studio 2005<br />TlbImp.exe<br />You can also use some of the services available in the System.Runtime. InteropServices namespace, but doing so is cumbersome and error prone<br />
    7. 7. ImportingTypeLibraries<br />
    8. 8. ImportingTypeLibraries<br />UsingtheType Library Importer utility (TlbImp.exe) is a little more intricate but still quite straightforward<br />Open the Visual Studio 2005 command prompt<br />Navigate to the location of the DLL you want to import<br />Typetlbimp <dllname>.dll<br />Thiswillimportthe DLL and create a .NET assemblywithits original name. Forexample, Person.dll willbeimported as Person.dll.<br />If you want a name to be used other than the original DLL name, type <br />tlbimp <dllname>.dll /out:<DesiredName>.dll.<br />Add a reference to the assembly name you chose just as you would for any other .NET assembly. TlbImp.exe is creating a new assembly for you from the COM library. So now you have a brand new .NET assembly, and it will be visible only under the .NET tab of the Add Reference dialog box.<br />
    9. 9. ImportingTypeLibraries<br />C# doesn’tsupportoptionalparameterswhereas Visual Basic 2005 does. COM components don’t support parameter overloading, so for each value in a parameter list, you’ve got to pass in something, even if it does nothing. Moreover, COM parameters are always passed by reference, which means that you can’t pass in a null value.<br />In Visual Basic 2005, this isn’t really an issue because many of these parameters are optional and you can just leave them out (or include them) as you see fit. C# doesn’t support this, though, so you have to create object variables (remember, they can’t be null) and then pass them in. This approach is problematic for the following reasons:<br />It leads to unnecessary and confusing code.<br />In many instances, it leads to code that’s virtually unreadable. (Imagine a 15 item parameter list, for instance.)<br />
    10. 10. ImportingTypeLibraries<br />To address this problem, a new feature of the Type class has been provided: Type.Missing. Examine the following code samples:<br />' VB<br />ImportsMicrosoft.Office.Core<br />Imports Microsoft.Office.Interop.Excel ' Must have Office installed for this demo<br />DimNewExcelApp As New Microsoft.Office.Interop.Excel.Application<br />'Thisworks fine<br />NewExcelApp.Worksheets.Add()<br />// C#<br />usingMicrosoft.Office.Core;<br />using Microsoft.Office.Interop.Excel; // Must have Office installed for this demo<br />ApplicationNewExcelApp = new Application();<br />// Thiswillnot compile.<br />NewExcelApp.Worksheets.Add();<br />
    11. 11. ImportingTypeLibraries<br />Instead of creating “dummy” object variables, the Type.Missing field can be used. That field can be passed in with the C# code and the application will work as expected. <br />' VB<br />Module Module1<br />Private OptionalParamHandler As Object = Type.Missing<br />Sub Main()<br />DimNewExcelApp As New Microsoft.Office.Interop.Excel.Application<br />NewExcelApp.Worksheets.Add(OptionalParamHandler, _<br />OptionalParamHandler, OptionalParamHandler, _<br />OptionalParamHandler)<br />End Sub<br />End Module<br />// C#<br />classProgram<br />{<br />private static Object OptionalParamHandler = Type.Missing;<br />staticvoidMain(string[] args)<br />{<br />ApplicationNewExcelApp = new Application();<br />NewExcelApp.Worksheets.Add(OptionalParamHandler,<br />OptionalParamHandler, OptionalParamHandler,<br />OptionalParamHandler);<br />}<br />}<br />
    12. 12. Tools usedbycomminterop<br />
    13. 13. Using COM objects in code<br />After the steps in the “Importing Type Libraries” section have been performed, using an object contained in a given library is virtually identical to using one created purely in .NET.<br />' VB<br />AxAcroPDF1.LoadFile("SamplePDFDocument.pdf")<br />AxAcroPDF1.Print()<br />// C#<br />axAcroPDF1.LoadFile(@"SamplePDFDocument.pdf");<br />axAcroPDF1.Print();<br />
    14. 14. Handlingexceptions in COM interop<br />What System.Exception would handle is any Common Language Specification (CLS) compliant exception. <br />COM errors won’t be CLS compliant, they won’t be caught by System.Exceptions. <br />Because so many developers mistakenly understood the behavior of trapping System.Exception, quite a bit of unstable code and code with serious potential security implications was developed.<br />
    15. 15. Handlingexceptions in COM interop<br />In version 2.0 of the .NET Framework, the RuntimeWrappedException class was introduced intotheSystem.Runtime.CompilerServicesnamespace.<br />
    16. 16. Handlingexceptions in COM interop<br />With the exception of WrappedException, each of the properties is inherited from the System.Exception class. So the main distinction is the WrappedException property, which is of type Object.<br />When a non-CLS-compliant exception is thrown, the common language runtime (CLR) creates an instance of this class and then sets the WrappedException property to the object that was thrown. <br />This behavior is handled by default and is transparent to the developer, but it’s important to be aware of.<br />
    17. 17. Handlingexceptions in COM interop<br />To turn off this behavior, you can use the RuntimeCompatibility attribute, as illustrated here:<br />‘VB<br />ImportsSystem.Runtime.CompilerServices<br /><Assembly: RuntimeCompatibility(WrapNonExceptionThrows:=False)><br />// C#<br />usingSystem.Runtime.CompilerServices;<br />[assembly: RuntimeCompatibility(WrapNonExceptionThrows=false)]<br />
    18. 18. Limitations of COM interop<br />There have been some shortcomings with using COM Interop:<br />Static/shared members COM objects are fundamentally different from .NET types. One of the differences is lack of support for static/shared members.<br />Parameterized constructors COM types don’t allow parameters to be passed into a constructor. This limits the control you have over initialization and the use of overloadedconstructors.<br />Inheritance One of the biggest issues is the limitations COM objects place on the inheritance chain. Members that shadow members in a base class aren’t recognizable, and therefore, aren’t callable or usable in any real sense.<br />Portability Operating systems other than Windows don’t have a registry. Reliance on the Windows registry limits the number of environments a .NET application can beportedto.<br />
    19. 19. Questions<br />Which methods allow COM components to be used in .NET applications? (Chooseallthatapply.)<br />A. Add a reference to the component through Microsoft Visual Studio 2005.<br />B. Use the Type Library Import tool (TlbImport.exe).<br />C. Use the Regsvr32 tool.<br />D. Ensure that the application is registered, using the RegSvr tool if necessary.<br /> Then either add a reference to it from the COM tab of the Add Reference dialog box or use TblImp.exe.<br />
    20. 20. Questions<br />2. How should non-CLS-compliant exceptions be trapped when running under t.he.NET Framework 2.0? (Choose all that apply.)<br />A. Trap an instance of the ApplicationException.<br />B. Trap an instance of System.Exception, and set the RuntimeCompatibiltyattributeto false.<br />C. Simply trap an instance of a System.Exception object.<br />D. Trap an instance of System.Exception, and set the RuntimeCompatibiltyattributeto true.<br />
    21. 21. Questions<br />4. Which tools can be used to manipulate COM Interop? (Choose all that apply.)<br />IntermediateLanguageDisassembler (Ildasm.exe).<br />B. The .NET Framework 2.0 Configuration Tool.<br />C. Type Library Importer (TlbImp.exe).<br />D. The Windows Registry Editor.<br />
    22. 22. Exposing.netcomponentstocom<br />Lesson 2<br />
    23. 23. Lessonsummary<br />The Register For COM Interop option under the build configuration automates the process of exposing .NET assemblies to COM components.<br />The primary mechanism for exposing .NET assemblies to COM components is theComVisibleattribute.<br />The ComVisible attribute can be set to apply to an entire assembly, an entire class, or individual members.<br />The more granular the application of the ComVisible attribute, the more it takes precedence. A class, for example, can be marked with ComVisible set to false and with a given member set to true. The member that is set to true will be visible to COM components.<br />
    24. 24. Building .NET Components for Use by COM<br />Just as COM components can be consumed by .NET applications, the reverse is true. <br />A proxy known as a COM Callable Wrapper (CCW) handles marshaling items between .NET and COM.<br />The .NET runtime will create onlyone CCW.<br />
    25. 25. Building .NET Components for Use by COM<br />Steps:<br />Create a .NET class library just like you normally would.<br />Open the Project Properties dialog box by right-clicking the project and selecting Properties.<br />Click the Build tab, which is located on the right side of the dialog box.<br />Select the Register For COM Interop option in the Output section of the tab.<br />Buildtheapplication.<br />
    26. 26. Building .NET Components for Use by COM<br />After the project is built, the necessary type library information will be created by Visual Studio 2005, which will also register each of the objects as COM objects for you.<br />
    27. 27. Hiding Public .NET Classes from COM<br /><ul><li>Considering visibility if you want everything to be visible or invisible and the level of granularity of this visibility.
    28. 28. To set COM Visibility to either On or Off by default, simply set the ComVisible Assembly attribute to true or false, respectively.</li></ul>' VB<br /><Assembly: ComVisible(False)> <br />' Visibility disabled by default Next, for each class and each member that you ' want to have visible or invisible, simply use the ComVisible<br />' attribute individually for each of them:<br />
    29. 29. Hiding Public .NET Classes from COM<br />Next, for each class and each member that you want to have visible or invisible, simply use the ComVisible attribute individually for each of them:<br /><ComVisible(True)> _<br />Public Property LastName() As String<br />Get<br />ReturnMe._lastName<br />EndGet<br /> Set(ByValvalue As String)<br />Me._lastName = value<br />End Set<br />EndProperty<br /><ComVisible(False)> _<br />Public Property Salary() As Int32<br />Get<br />ReturnMe._salary<br />EndGet<br /> Set(ByValvalue As Int32)<br />Me._salary = value<br />End Set<br />EndProperty<br />EndClass<br />ImportsSystem.Runtime.CompilerServices<br />ImportsSystem.Runtime.InteropServices<br /><ComVisible(False)> _<br />PublicClassComVisiblePerson<br />Private _firstName As String<br />Private _lastName As String<br />Private _salary As Int32<br /><ComVisible(True)> _<br />Public Property FirstName() As String<br />Get<br />ReturnMe._firstName<br />EndGet<br /> Set(ByValvalue As String)<br />Me._firstName = value<br />End Set<br />EndProperty<br />
    30. 30. Deploying COM-EnabledAssemblies<br />To ensure that things work as planned:<br /><ul><li>All classes must use a default constructor with no parameters.
    31. 31. Any type that is to be exposed must be public.
    32. 32. Any member that is to be exposed must be public.
    33. 33. Abstract classes will not be able to be consumed.</li></ul>After these criteria are met, the assembly is essentially ready to be exported.<br />
    34. 34. Deploying COM-EnabledAssemblies<br />Mechanisms to export the assembly:<br /><ul><li>Compile the type through Visual Studio’s build mechanism or through the command-line compiler.</li></ul>' VB<br />vbc /t:library ComVisiblePerson.vb<br />// C#<br />csc /t:library ComVisiblePerson.cs<br /><ul><li> Next you need to use the Type Library Exporter Utility. This should be done from the Visual Studio 2005 commandprompt:</li></ul>tlbexp ComVisiblePerson.dll /out:ComVisiblePersonlib.tlb<br /><ul><li>Next you need to create a resource script (ComVisiblePerson.res) with the following statement:</li></ul> IDR_TYPELIB1 typelib "ComVisiblePersonlib.tlb"<br />
    35. 35. Deploying COM-EnabledAssemblies<br /><ul><li> To generate the resource file, you compile the script by using the Resource Compiler, as shownhere:</li></ul>rc ComVisiblePersonLib.res<br /><ul><li> Then you recompile the assembly with the type library embedded as a Win32 resource file, as shownhere:</li></ul>' VB<br />vbc /t:library ComVisiblePerson.vb /win32res:ComVisiblePersonLib.res<br />// C#<br />csc /t:library ComVisiblePerson.cs /win32res:ComVisiblePersonLib.res<br />
    36. 36. Usingunmanagedcode<br />Lesson 3<br />
    37. 37. Afterthislesson, youwillbeableto:<br />Use Platform Invoke (P/Invoke) to access unmanaged code.<br />Encapsulate DLL functions.<br />Convert data types between managed and unmanaged code.<br />
    38. 38. Afterthislesson, youwillbeableto:<br />Use Platform Invoke (P/Invoke) to access unmanaged code.<br />Encapsulate DLL functions.<br />Convert data types between managed and unmanaged code.<br />
    39. 39. Callingplatforminvoke (P/Invoke)<br />Typical use case scenarios:<br />Functionality specific to the Windows operating system, context switching, and file I/O.<br />Advanced manipulation of windows, menus, dialog boxes, and icons. For example, if you want to customize a MessageBox outside of what the .NET Framework provides, the only way to do it is through the Windows API.<br />Advanceddrawingfunctionality.<br />
    40. 40. Callingplatforminvoke (P/Invoke)<br />You manage P/Invoke through the System.Runtime.InteropServices namespace<br />Create a new static/shared external method with the name of the function you wanttocall.<br />Decorate it with the DllImport attribute specifying the library that it should call.<br />Call the method from your code.<br />
    41. 41. Callingplatforminvoke (P/Invoke)<br />Example<br />' VB<br />ImportsSystem.Text<br />ImportsSystem.Runtime.InteropServices<br />PublicClassWindowExample<br />Private Const BufferSize As Int32 = 256<br /><DllImport("user32.dll")> Private Shared Function GetForegroundWindow() As IntPtr<br />EndFunction<br /><DllImport("user32.dll")> Private Shared Function GetWindowText(ByValhWnd As IntPtr, _<br />ByValtextValue As StringBuilder, ByVal counter As Int32) As Int32<br />EndFunction<br />PublicShared Sub GetScreenDemo()<br />Dim DemoBuilder As New StringBuilder(BufferSize)<br />Dim DemoHandle As IntPtr = GetForegroundWindow()<br />If GetWindowText(DemoHandle, DemoBuilder, BufferSize) > 0 Then<br />Console.WriteLine(DemoBuilder.ToString())<br />EndIf<br />End Sub<br />EndClass<br />When using Platform Invoke, use a StringBuilder object instead of a String. A StringBuilder is a reference type with no atypical behavior and is needed because of the way P/Invoke internals work.<br />
    42. 42. Encampsulating DLL functions<br />It’s often beneficial to create a class that exposes P/Invoke. This approach has the following benefits:<br />Consumers of your class will not know this code from any other “normal” code they are used to dealing with.<br />It relieves developers of having to remember the API call names and their respective parameters. You can create it once and then use it like any other .NET method.<br />It will be less error prone. Even slight typing differences can cause P/Invoke calls to break. Even if you are a perfect typist and never forget anything, it’s doubtful that everyone you work with will have the same capability. And if they don’t, they will invariable type something incorrectly, miss a parameter, or forget the name of something.<br />Example:<br />WindowExample.GetScreenDemo()<br />
    43. 43. Coverting data types<br />Whenusingunmanagedcode, the first mechanism for converting data types is the MarshalAs attribute. <br />MarshalAs can be applied to a property or a parameter. Either way, it works essentially the same.<br />Create your property, decorate it with the MarshalAs attribute, and then specify the type it should be converted from, as shown here:<br />
    44. 44. Converting data types<br />Just as this attribute can be applied to a method or property, it can be applied to a parameter as well.<br />
    45. 45. Marshalingstructures<br />Structures are commonly used in many Windows APIs and methods that you will use through P/Invoke.<br />By default, when a type is created, the CLR will decide how best to arrange the class’s members. <br />To manually direct the CLR about how to handle (or not handle) the layout of a type The System.Runtime.InteropServices.StructLayoutAttributeattribute is provided. <br />
    46. 46. Marshalingstructures<br />
    47. 47. Marshalingstructures<br />
    48. 48. Marshlingstructures<br />The StructLayoutAttribute constructor, takes one of the following three values:<br />LayoutKind.Auto Causes the developer to relinquish all control over the layout tothe CLR<br />LayoutKind.SequentialCauses the CLR to preserve the layout specified by the developer<br />LayoutKind.ExplicitCauses the CLR to use the layout explicitly specified by the developer by using memory offsets<br />
    49. 49. Marshlingstructures<br />Layout.Sequential<br />This method indicates that structure values will appear exactly as they should in the called library:<br />
    50. 50. Marshlingstructures<br />Layout.Explicit<br />Twothingsmustbe done:<br />The LayoutKind enumeration needs to be set to Explicit.<br />The offset in bytes must be specified for each field.<br />Other than these differences, using either approach is virtually indistinguishable from usingSequentiallayouts.<br />
    51. 51. Using a callbackwithunmanagedcode<br />The .NET Framework providesDelegate objects, which can be used to manage callbacks in a “type-safe” fashion.<br />
    52. 52. STEPS<br />Create a Delegate object with the same signature as the callback.<br />Substitute the Delegate for the callback, and make the call.<br />
    53. 53. Exception Handling in Managed Code<br />Using COM, you could use the GetLastError function to get the last error thatwasraised. This approach won’t work in a managed application.<br />The only thing more problematic than no exception handling is bad exception handling. <br />
    54. 54. If this code is run correctly, you’ll get a return value indicating that there was a bad pointer instead of just a numeric value.<br />
    55. 55. Limitations of UnmanagedCode<br />Some shortcomings with using unmanaged:<br />PerformanceCode that isn’t managed by a runtime will typically have the ability to perform faster than equivalent code that is managed. However, this benefit might not necessarily be realized because of the overhead associated with marshaling information between the unmanaged code and the .NET 2.0 runtime. It’s important to remember that unmanaged code can easily introduce issues such as memory leaks.<br />Type safetyUnmanaged code is sometimes not type safe. This deficiency can have multiple implications, including decreased readability and security issues. One of the most widely touted benefits of Visual Basic 2005 over previous versions is enhanced type strength. Moreover, there’s no guarantee that type library definitions are accurate, so depending on the metadata, there could be some definitions that are inaccurate ormissing.<br />Code securityThe .NET Framework security model didn’t exist previously. There’s no way that code written prior to this model can take advantage of it. Features such as declarative security are not available in unmanaged code, which can mean your new .NET code will be forced to accommodate this inconsistency.<br />VersioningAs is the case with security, versioning didn’t exist in the form it does now. Therefore, side-by-side execution might not be available when using unmanagedcode.<br />
    56. 56. Lessonsummary<br />The .NET Framework provides a mechanism to call Windows API calls and unmanaged code through Platform Invoke.<br />To use P/Invoke, you use the DllImport attribute and the name of the DLL you are referencing.<br />You must use the private and static/shared attributes for P/Invoke calls.<br />To allow default positioning in a structure that’s to be marshaled, you can use theLayout.Sequentialattribute.<br />To specify a value for the positioning in a structure, you can use the Layout.Explicitattribute.<br />Error messages from unmanaged code behave differently from managed exceptions. To trap them correctly, the Windows API can be used.<br />