Condividi tramite


How to: Call Unmanaged Code from Trusted Applications

Microsoft Silverlight will reach end of support after October 2021. Learn more.

In Silverlight applications, sometimes you want to call unmanaged libraries or native code, including Microsoft Win32 functions. In Silverlight 5, you can call unmanaged or native code through the platform invoke feature. Platform invoke is also referred to as PInvoke or P/Invoke. Platform invoke in Silverlight is very similar to platform invoke in the .NET Framework. However, there are some important differences.

  • Platform invoke in Silverlight can only be used in trusted applications hosted either in-browser or out-of-browser.

  • Platform invoke in Silverlight can only be used on computers running the Windows operating system. There is no Mac support.

Calling Unmanaged Code

When you call unmanaged code from managed code, you have to declare the unmanaged function and specify the library that has the function. The library that contains the function must be located on the computer that is running the application. Platform invoke is supported on computers running the Windows operating system only. If the specified function is in a Win32 library, the Silverlight runtime will be able to locate it. If you are calling your own unmanaged library, you will need to specify the full path to the library, or add it to the PATH system variable so the Silverlight runtime can locate the library. For security reasons, you can only call unmanaged code from a trusted application. For more information about trusted applications, see Trusted Applications.

In order for the platform invoke call to complete successfully, you may need to perform some conversion between managed and unmanaged data types. This is called type marshaling. In many cases, marshaling is automatic. For a mapping between unmanaged and managed data types, see Platform Invoke Data Types in the .NET Framework documentation. If you need to marshal the types manually, you can use the type marshaling methods in the System.Runtime.InteropServices namespace. Silverlight provides a subset of the type marshaling methods offered in the .NET Framework. If your scenario requires it, you can call unmanaged marshaling functions by using platform invoke. For more information about type marshaling, see Marshaling Data with Platform Invoke in the .NET Framework documentation.

To call an unmanaged function

  1. Create a Silverlight 5 application project.

  2. If you will run the application outside the browser, in the project properties, select the Require elevated trust when running outside the browser check box.

    -or-

    If you will run the application in-browser, in the project properties, select the Require elevated trust when running in-browser check box. Also, make sure to host the application in a web site for debugging.

  3. In the code file, add a using or Imports statement to System.Runtime.InteropServices.

    Imports System.Runtime.InteropServices
    
    using System.Runtime.InteropServices;
    
  4. Declare the unmanaged function that you want to call in your managed code. In C#, use the static and extern keywords. In Visual Basic, use the Shared keyword. You should map the unmanaged and managed types appropriately. The following example shows a declaration of the Win32 GetDriveType function.

    Private Shared Function GetDriveType(lpRootPathName As String) As Integer
    End Function
    
    static extern int GetDriveType(string lpRootPathName);
    
  5. Add a DllImportAttribute to the declaration created in the previous step and specify the library where the function is located. The library must be located on the computer that will run the application. The following code example shows the declaration with the import attribute.

    <DllImport("kernel32.dll")> _
    Private Shared Function GetDriveType(lpRootPathName As String) As Integer
    End Function
    
    [DllImport("kernel32.dll")]
    static extern int GetDriveType(string lpRootPathName);
    
  6. Call the function from managed code as needed. The following code shows an example of how to call the GetDriveType function.

        Private Sub detectDrive_Click(sender As Object, e As RoutedEventArgs)
            Dim drives As [String]() = New String() {"c:\", "d:\", "e:\", "f:\", "g:\", "h:\", _
             "i:\"}
            Dim driveInserted As Boolean = False
            Dim driveLetter As String = ""
            For Each drive As [String] In drives
                ' Calling the native method. 
                ' “2” means that the drive is a removable drive.
                If GetDriveType(drive) = 2 Then
                    driveInserted = True
                    driveLetter = drive
                End If
            Next
            If driveInserted Then
                textBlock1.Text = "Removable drive is " & driveLetter
            Else
                textBlock1.Text = "No removable drive"
            End If
        End Sub
    
    
    
       private void detectDrive_Click(object sender, RoutedEventArgs e)
       {
           String[] drives = new string[] 
               { @"c:\", @"d:\", @"e:\", @"f:\", @"g:\", @"h:\", @"i:\" };
           bool driveInserted = false;
           string driveLetter = "";
           foreach (String drive in drives)
           {
               // Calling the native method. 
               // “2” means that the drive is a removable drive.
    
               if (GetDriveType(drive) == 2)
               {
                   driveInserted = true;
                   driveLetter = drive;
               }
           }
           if (driveInserted)
               textBlock1.Text = "Removable drive is " + driveLetter;
           else
               textBlock1.Text = "No removable drive";
       }
    
    
    

    To run this example, add the following XAML to the layout root grid control.

    <TextBlock Height="28" HorizontalAlignment="Left" Margin="48,72,0,0" Name="textBlock1" Text="Removable Drives" VerticalAlignment="Top" Width="183" />
    <Button Content="Detect Removable Drives" Height="23" HorizontalAlignment="Left" Margin="48,26,0,0" Name="detectDrive" VerticalAlignment="Top" Width="163" Click="detectDrive_Click" />
    

Calling back to a Managed Method from Unmanaged Code

Similar to the .NET Framework, in Silverlight 5, you can call a managed method from unmanaged code. This is called a reverse platform invoke. This is typically an advanced scenario. For example, you may want to call an unmanaged function in a custom library that requires a callback or a function pointer as a parameter, and pass a Silverlight managed method as the parameter. To do this in Silverlight, you must explicitly specify the entry point for reverse platform invoke call in managed code by using the AllowReversePinvokeCallsAttribute . You apply this attribute to managed methods that will be called from unmanaged code.

To call managed code from unmanaged code

  1. Create a Silverlight 5 application project.

  2. If you will run the application outside the browser, in the project properties, select the Require elevated trust when running outside the browser check box.

    -or-

    If you will run the application in-browser, in the project properties, select the Require elevated trust when running in-browser check box. Also, make sure to host the application in a web site for debugging.

  3. In the code file, add a using or Imports statement to System.Runtime.InteropServices.

    Imports System.Runtime.InteropServices
    
    using System.Runtime.InteropServices;
    
  4. Declare the unmanaged function that you want to call in your managed code. In C#, use the static and extern keywords. In Visual Basic, use the Shared keyword. You should map the unmanaged and managed types appropriately.

  5. Add a DllImportAttribute to the declaration created in the previous step and specify the library where the function is located. The library must be located on the computer that will run the application.

    <DllImport("kernel32.dll")> _
    Private Shared Function GetDriveType(lpRootPathName As String) As Integer
    End Function
    
    [DllImport("kernel32.dll")]
    static extern int GetDriveType(string lpRootPathName);
    
  6. Create a function delegate to pass to the unmanaged function.

  7. Add the AllowReversePinvokeCallsAttribute to the managed method that you want to call from unmanaged code. This enables the call to occur without an exception.

    The following code shows how to call a function named ProcessNumber that is located in a custom library. In this example, you see the unmanaged function declaration and a call to the unmanaged function, passing the function delegate that references the managed method.

    Public Delegate Function NumberSource() As Integer
    
    <DllImport("myNumberLib.dll")> _
    Private Shared Function ProcessNumber(src As NumberSource) As Integer
    End Function
    
    
    <AllowReversePInvokeCalls()> _
    Public Function ManagedSource() As Integer
        Return 42
    End Function
    
    Private Sub CallUnmanagedMethod()
        Dim result As Integer = ProcessNumber(New NumberSource(AddressOf ManagedSource))
    End Sub
    
    public delegate int NumberSource();
    
    [DllImport("myNumberLib.dll")]
    static extern int ProcessNumber(NumberSource src);
    
    
    [AllowReversePInvokeCalls]
    public int ManagedSource()
    {
        return 42;
    } 
    
    private void CallUnmanagedMethod() 
    {
        int result = ProcessNumber(new NumberSource(ManagedSource));
    }