Interoperation

52
CHAPTER 13

description

La interoperabilidad en .NET

Transcript of Interoperation

Page 1: Interoperation

CHAPTER 13

Page 2: Interoperation

Interoperation

Interoperation is a generic name used to referto the process of interacting with unmanagedcode from within managed code.

The large amount of legacy code that was expensive to develop and has already been tested.

Not every Microsoft Windows API has been wrapped for the .NET Framework 2.0, so some tasks are possible only if you use Interoperation.

Page 3: Interoperation

LESSON 1

Page 4: Interoperation

Lesson summary

COM components can easily be consumed in a .NET application, although the reasons for doing so need to be carefully considered.

You can use the COM tab of the Add Reference dialog box to add a reference to registered COM components.

The TlbImp.exe tool is a command-line mechanism to import a COM component.

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.

The default behavior when catching System.Exception objects now catches both CLS-compliant and non-CLS-compliantexceptions.

The RuntimeCompatibilty attribute can be used to change whether non-CLS compliant exceptions will be trapped by default.

Page 5: Interoperation

Importing Type Libraries

Runtime Callable Wrapper (RCW):

mechanism that serves as a proxy so

that the .NET runtime can communicate

with a COM component.

RCW handles the majority of the work

between .NET and COM, including

marshaling data types, handling events,

and handling interfaces.

Page 6: Interoperation

Importing Type Libraries

Once a DLL has been registered, You have

two ways to import registered COM DLLs:

Visual Studio 2005

TlbImp.exe

You can also use some of the services available in

the System.Runtime. InteropServices namespace,

but doing so is cumbersome and error prone

Page 7: Interoperation

Importing Type Libraries

Page 8: Interoperation

Importing Type Libraries

Using the Type Library Importer utility (TlbImp.exe) is a little

more intricate but still quite straightforward

1. Open the Visual Studio 2005 command prompt

2. Navigate to the location of the DLL you want to import

3. Type tlbimp <dllname>.dll

This will import the DLL and create a .NET assembly with its

original name. For example, Person.dll will be imported as

Person.dll.

5. If you want a name to be used other than the original DLL

name, type

tlbimp <dllname>.dll /out:<DesiredName>.dll.

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.

Page 9: Interoperation

Importing Type Libraries

C# doesn‟t support optional parameters whereas 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.

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:

It leads to unnecessary and confusing code.

In many instances, it leads to code that‟s virtually unreadable. (Imagine a 15 item parameter list, for instance.)

Page 10: Interoperation

Importing Type Libraries

To address this problem, a new feature of the Type class has been provided: Type.Missing. Examine the following code samples:

' VB

Imports Microsoft.Office.Core

Imports Microsoft.Office.Interop.Excel ' Must have Office installed for this demo

Dim NewExcelApp As New Microsoft.Office.Interop.Excel.Application

'This works fine

NewExcelApp.Worksheets.Add()

// C#

using Microsoft.Office.Core;

using Microsoft.Office.Interop.Excel; // Must have Office installed for this demo

Application NewExcelApp = new Application();

// This will not compile.

NewExcelApp.Worksheets.Add();

Page 11: Interoperation

Importing Type Libraries

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.

' VB

Module Module1

Private OptionalParamHandler As Object = Type.Missing

Sub Main()

Dim NewExcelApp As New Microsoft.Office.Interop.Excel.Application

NewExcelApp.Worksheets.Add(OptionalParamHandler, _

OptionalParamHandler, OptionalParamHandler, _

OptionalParamHandler)

End Sub

End Module

// C#

class Program

{

private static Object OptionalParamHandler = Type.Missing;

static void Main(string[] args)

{

Application NewExcelApp = new Application();

NewExcelApp.Worksheets.Add(OptionalParamHandler,

OptionalParamHandler, OptionalParamHandler,

OptionalParamHandler);

}

}

Page 12: Interoperation

Tools used by comm

interop

Page 13: Interoperation

Using COM objects in

codeAfter 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.

' VB

AxAcroPDF1.LoadFile("SamplePDFDocument.pdf")

AxAcroPDF1.Print()

// C#

axAcroPDF1.LoadFile(@"SamplePDFDocument.pdf");

axAcroPDF1.Print();

Page 14: Interoperation

Handling exceptions in COM

interop What System.Exception would handle is any

Common Language Specification (CLS) compliant

exception.

COM errors won‟t be CLS compliant, they won‟t be

caught by System.Exceptions.

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.

Page 15: Interoperation

Handling exceptions in COM

interopIn version 2.0 of the .NET Framework, the RuntimeWrappedException

class was introduced into the System.Runtime.CompilerServices

namespace.

Page 16: Interoperation

Handling exceptions in COM

interop 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.

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.

This behavior is handled by default and is transparent

to the developer, but it‟s important to be aware of.

Page 17: Interoperation

Handling exceptions in COM

interop To turn off this behavior, you can use the

RuntimeCompatibility attribute, as illustrated here:

„VB

Imports System.Runtime.CompilerServices

<Assembly: RuntimeCompatibility(WrapNonExceptionThrows:=False)>

// C#

using System.Runtime.CompilerServices;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows=false)]

Page 18: Interoperation

Limitations of COM

interopThere have been some shortcomings with using COM Interop: Static/shared members COM objects are fundamentally different

from .NET types. One of the differences is lack of support for static/shared members.

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 overloaded constructors.

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.

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 be ported to.

Page 19: Interoperation

Questions

1. Which methods allow COM components to be used in .NET applications? (Choose all that apply.)

A. Add a reference to the component through Microsoft Visual Studio 2005.

B. Use the Type Library Import tool (TlbImport.exe).

C. Use the Regsvr32 tool.

D. Ensure that the application is registered, using the RegSvrtool if necessary.

Then either add a reference to it from the COM tab of the Add Reference dialog box or use TblImp.exe.

Page 20: Interoperation

Questions

2. How should non-CLS-compliant exceptions be trapped when running under t.he .NET Framework 2.0? (Choose all that apply.)

A. Trap an instance of the ApplicationException.

B. Trap an instance of System.Exception, and set the RuntimeCompatibilty attribute to false.

C. Simply trap an instance of a System.Exception object.

D. Trap an instance of System.Exception, and set the RuntimeCompatibilty attribute to true.

Page 21: Interoperation

Questions

4. Which tools can be used to manipulate COM Interop? (Choose all that apply.)

A. Intermediate Language Disassembler(Ildasm.exe).

B. The .NET Framework 2.0 Configuration Tool.

C. Type Library Importer (TlbImp.exe).

D. The Windows Registry Editor.

Page 22: Interoperation

Lesson 2

Page 23: Interoperation

Lesson summary

The Register For COM Interop option under the build configuration automates the process of exposing .NET assemblies to COM components.

The primary mechanism for exposing .NET assemblies to COM components is the ComVisibleattribute.

The ComVisible attribute can be set to apply to an entire assembly, an entire class, or individual members.

The more granular the application of the ComVisibleattribute, 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.

Page 24: Interoperation

Building .NET Components

for Use by COM

Just as COM components can be consumed by

.NET applications, the reverse is true.

A proxy known as a COM Callable Wrapper

(CCW) handles marshaling items between .NET

and COM.

The .NET runtime will create only one CCW.

Page 25: Interoperation

Building .NET Components

for Use by COM

Steps:

1. Create a .NET class library just like you normally

would.

2. Open the Project Properties dialog box by right-

clicking the project and selecting Properties.

3. Click the Build tab, which is located on the right

side of the dialog box.

4. Select the Register For COM Interop option in

the Output section of the tab.

5. Build the application.

Page 26: Interoperation

Building .NET Components

for Use by COM

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.

Page 27: Interoperation

Hiding Public .NET Classes

from COM•Considering visibility if you want everything to be visible

or invisible and the level of granularity of this visibility.

•To set COM Visibility to either On or Off by

default, simply set the ComVisible Assembly attribute to

true or false, respectively.

' VB

<Assembly: ComVisible(False)>

' Visibility disabled by default 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:

Page 28: Interoperation

Hiding Public .NET Classes

from COMNext, for each class and each member that you want to have visible or

invisible, simply use the ComVisible attribute individually for each of them:

Imports System.Runtime.CompilerServices

Imports System.Runtime.InteropServices

<ComVisible(False)> _

Public Class ComVisiblePerson

Private _firstName As String

Private _lastName As String

Private _salary As Int32

<ComVisible(True)> _

Public Property FirstName() As String

Get

Return Me._firstName

End Get

Set(ByVal value As String)

Me._firstName = value

End Set

End Property

<ComVisible(True)> _

Public Property LastName() As String

Get

Return Me._lastName

End Get

Set(ByVal value As String)

Me._lastName = value

End Set

End Property

<ComVisible(False)> _

Public Property Salary() As Int32

Get

Return Me._salary

End Get

Set(ByVal value As Int32)

Me._salary = value

End Set

End Property

End Class

Page 29: Interoperation

Deploying COM-Enabled

Assemblies

To ensure that things work as planned:

All classes must use a default constructor

with no parameters.

Any type that is to be exposed must be public.

Any member that is to be exposed must be

public.

Abstract classes will not be able to be

consumed.

After these criteria are met, the assembly is essentially

ready to be exported.

Page 30: Interoperation

Deploying COM-Enabled

Assemblies

Mechanisms to export the assembly:

• Compile the type through Visual Studio‟s build mechanism or

through the command-line compiler.

' VB

vbc /t:library ComVisiblePerson.vb

// C#

csc /t:library ComVisiblePerson.cs

• Next you need to use the Type Library Exporter Utility. This should

be done from the Visual Studio 2005 command prompt:

tlbexp ComVisiblePerson.dll /out:ComVisiblePersonlib.tlb

•Next you need to create a resource script (ComVisiblePerson.res)

with the following statement:

IDR_TYPELIB1 typelib "ComVisiblePersonlib.tlb"

Page 31: Interoperation

Deploying COM-Enabled

Assemblies• To generate the resource file, you compile the script by using the

Resource Compiler, as shown here:

rc ComVisiblePersonLib.res

• Then you recompile the assembly with the type library embedded

as a Win32 resource file, as shown here:

' VB

vbc /t:library ComVisiblePerson.vb

/win32res:ComVisiblePersonLib.res

// C#

csc /t:library ComVisiblePerson.cs

/win32res:ComVisiblePersonLib.res

Page 32: Interoperation

Lesson 3

Page 33: Interoperation

After this lesson, you will be

able to:

Use Platform Invoke (P/Invoke) to

access unmanaged code.

Encapsulate DLL functions.

Convert data types between managed

and unmanaged code.

Page 34: Interoperation

After this lesson, you will be

able to:

Use Platform Invoke (P/Invoke) to

access unmanaged code.

Encapsulate DLL functions.

Convert data types between managed

and unmanaged code.

Page 35: Interoperation

Calling platform invoke

(P/Invoke)

Typical use case scenarios:

Functionality specific to the Windows

operating system, context switching, and file

I/O.

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.

Advanced drawing functionality.

Page 36: Interoperation

Calling platform invoke

(P/Invoke)

You manage P/Invoke through the

System.Runtime.InteropServices namespace

1. Create a new static/shared external

method with the name of the function you

want to call.

2. Decorate it with the DllImport attribute

specifying the library that it should call.

3. Call the method from your code.

Page 37: Interoperation

Calling platform invoke

(P/Invoke)Example

' VB

Imports System.Text

Imports System.Runtime.InteropServices

Public Class WindowExample

Private Const BufferSize As Int32 = 256

<DllImport("user32.dll")> Private Shared Function GetForegroundWindow() As IntPtr

End Function

<DllImport("user32.dll")> Private Shared Function GetWindowText(ByVal hWnd As IntPtr, _

ByVal textValue As StringBuilder, ByVal counter As Int32) As Int32

End Function

Public Shared Sub GetScreenDemo()

Dim DemoBuilder As New StringBuilder(BufferSize)

Dim DemoHandle As IntPtr = GetForegroundWindow()

If GetWindowText(DemoHandle, DemoBuilder, BufferSize) > 0 Then

Console.WriteLine(DemoBuilder.ToString())

End If

End Sub

End ClassWhen 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.

Page 38: Interoperation

Encampsulating DLL functions

It‟s often beneficial to create a class that exposes P/Invoke. This approach has the following benefits:

Consumers of your class will not know this code from any other “normal” code they are used to dealing with.

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.

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.

Example:

WindowExample.GetScreenDemo()

Page 39: Interoperation

Coverting data types

When using unmanaged code, the first

mechanism for converting data types is the

MarshalAs attribute.

MarshalAs can be applied to a property or a

parameter. Either way, it works essentially the

same.

Create your property, decorate it

with the MarshalAs attribute, and

then specify the type it should be

converted from, as shown here:

Page 40: Interoperation

Converting data types

Just as this attribute can be applied to a

method or property, it can be applied to

a parameter as well.

Page 41: Interoperation

Marshaling structures

Structures are commonly used in many Windows

APIs and methods that you will use through

P/Invoke.

By default, when a type is created, the CLR will

decide how best to arrange the class‟s members.

To manually direct the CLR about how to handle

(or not handle) the layout of a type The System.Runtime.InteropServices.StructLayoutAttribute

attribute is provided.

Page 42: Interoperation

Marshaling structures

Page 43: Interoperation

Marshaling structures

Page 44: Interoperation

Marshling structures

The StructLayoutAttribute constructor, takes one of the following three values:

LayoutKind.Auto Causes the developer to relinquish all control over the layout to theCLR

LayoutKind.Sequential Causes the CLR to preserve the layout specified by the developer

LayoutKind.Explicit Causes the CLR to use the layout explicitly specified by the developer by using memory offsets

Page 45: Interoperation

Marshling structures

Layout.Sequential

This method indicates that structure values will

appear exactly as they should in the called

library:

Page 46: Interoperation

Marshling structures

Layout.Explicit

Two things must be done:

The LayoutKind enumeration needs to be set to Explicit.

The offset in bytes must be specified for each field.

Other than these differences, using either approach is

virtually indistinguishable from using Sequential layouts.

Page 47: Interoperation

Using a callback with

unmanaged code

The .NET Framework provides Delegate

objects, which can be used to manage

callbacks in a “type-safe” fashion.

Page 48: Interoperation

STEPS

1. Create a

Delegate object

with the same

signature as the

callback.

2. Substitute the

Delegate for the

callback, and

make the call.

Page 49: Interoperation

Exception Handling in

Managed Code Using COM, you could use the GetLastError function to

get the last error that was raised. This approach won‟t

work in a managed application.

The only thing more problematic than no exception

handling is bad exception handling.

Page 50: Interoperation

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.

Page 51: Interoperation

Limitations of Unmanaged

CodeSome shortcomings with using unmanaged:

Performance Code 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.

Type safety Unmanaged 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 or missing.

Code security The .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.

Versioning As 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 unmanaged code.

Page 52: Interoperation

Lesson summary

The .NET Framework provides a mechanism to call Windows API calls and unmanaged code through Platform Invoke.

To use P/Invoke, you use the DllImport attribute and the name of the DLL you are referencing.

You must use the private and static/shared attributes for P/Invoke calls.

To allow default positioning in a structure that‟s to be marshaled, you can use the Layout.Sequential attribute.

To specify a value for the positioning in a structure, you can use the Layout.Explicit attribute.

Error messages from unmanaged code behave differently from managed exceptions. To trap them correctly, the Windows API can be used.