Section 22.4. PInvoke


22.4. P/Invoke

It is possible to invoke unmanaged code from within C#. Typically you would do this if you needed to accomplish something you couldn't accomplish through the FCL. With the 2.0 version of .NET, the use of P/Invoke will become relatively rare.

The .NET platform invoke facility (P/Invoke) was originally intended only to provide access to the Windows API, but you can use it to call functions in any DLL.

To see how this works, let's revisit Example 21-3. You will recall that you used the FileInfo class to rename files by invoking the MoveTo() method:

file.MoveTo(fullName + ".bak");

You can accomplish the same thing by using Windows' kernel32.dll and invoking the MoveFile method.[1] To do so, you need to declare the method as a static extern and use the DllImport attribute:

[1] In fact, this is what Fileinfo.Move() is doing itself.

[DllImport("kernel32.dll", EntryPoint="MoveFile",     ExactSpelling=false, CharSet=CharSet.Unicode,      SetLastError=true)] static extern bool MoveFile(   string sourceFile, string destinationFile);

The DllImport attribute class is used to indicate that an unmanaged method will be invoked through P/Invoke. The parameters are as follows:


DLL name

The name of the DLL you are invoking.


EntryPoint

Indicates the name of the DLL entry point (the method) to call.


ExactSpelling

Allows the CLR to match methods with slightly different names based on the CLR's knowledge of naming conventions.


CharSet

Indicates how the string arguments to the method should be marshaled.


SetLastError

Setting this to true allows you to call Marshal.GetLastWin32 Error, and check whether an error occurred when invoking this method.

The rest of the code is virtually unchanged, except for the invocation of the MoveFile( ) method itself. Notice that MoveFile( ) is declared to be a static method of the class, so use static method semantics:

Tester.MoveFile(file.FullName,file.FullName + ".bak");

Pass in the original filename and the new name and the file is moved, just as it was when calling file.MoveTo( ). In this example, there is no advantageand actually considerable disadvantageto using P/Invoke. You have left managed code, and the result is that you've abandoned type safety and your code will no longer run in "partial-trusted" scenarios. Example 22-10 shows the complete source code for using P/Invoke to move the files.

Example 22-10. Using P/Invoke to call a Win32 API method
#region Using directives using System; using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; using System.Text; #endregion namespace UsingPInvoke {    class Tester    {       // declare the WinAPI method you wish to P/Invoke       [DllImport( "kernel32.dll", EntryPoint = "MoveFile",           ExactSpelling = false, CharSet = CharSet.Unicode,           SetLastError = true )]       static extern bool MoveFile(          string sourceFile, string destinationFile );       public static void Main( )       {          // make an instance and run it          Tester t = new Tester( );          string theDirectory = @"c:\test\media";          DirectoryInfo dir =             new DirectoryInfo( theDirectory );          t.ExploreDirectory( dir );       }       // Set it running with a directory name       private void ExploreDirectory( DirectoryInfo dir )       {          // make a new subdirectory          string newDirectory = "newTest";          DirectoryInfo newSubDir =             dir.CreateSubdirectory( newDirectory );          // get all the files in the directory and          // copy them to the new directory          FileInfo[] filesInDir = dir.GetFiles( );          foreach ( FileInfo file in filesInDir )          {             string fullName = newSubDir.FullName +                "\\" + file.Name;             file.CopyTo( fullName );             Console.WriteLine( "{0} copied to newTest",                file.FullName );          }          // get a collection of the files copied in          filesInDir = newSubDir.GetFiles( );          // delete some and rename others          int counter = 0;          foreach ( FileInfo file in filesInDir )          {             string fullName = file.FullName;             if ( counter++ % 2 == 0 )             {                // P/Invoke the Win API                Tester.MoveFile( fullName, fullName + ".bak" );                Console.WriteLine( "{0} renamed to {1}",                   fullName, file.FullName );             }             else             {                file.Delete( );                Console.WriteLine( "{0} deleted.",                   fullName );             }          }          // delete the subdirectory           newSubDir.Delete( true );       }    } } Output (excerpt): c:\test\media\newTest\recycle.wav renamed to     c:\test\media\newTest\recycle.wav c:\test\media\newTest\ringin.wav renamed to     c:\test\media\newTest\ringin.wav



Programming C#(c) Building. NET Applications with C#
Programming C#: Building .NET Applications with C#
ISBN: 0596006993
EAN: 2147483647
Year: 2003
Pages: 180
Authors: Jesse Liberty

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net