2011年11月8日 星期二

C# 直接調用Win32 API DLL

若要宣告直接調用DLL方法,請按下列方法操作: 
第一步: 引用System.Runtime.InteropServices
using System.Runtime.InteropServices;

第二步: 直接從 C# 調用 DLL,使用 C# 關鍵字 static 和 extern 聲明方法。
使用DllImportAttribute 類別來使用API
[DllImport("user32.dll")] //替換成所需的DLL檔
public static extern ReturnType FunctionName(type arg1,type arg2,...);//替換成所需的方法及參數 

API查詢:
1.Windows API Reference for C#, VB.NET and VB6 
http://www.webtropy.com/articles/Win32-API-DllImport-art9.asp
為了怕微軟又變更連結所以整個都給它Copy下來,以便不急之需
==============================================================================================================
DllImportAttribute Class 
http://msdn.microsoft.com/zh-tw/library/system.runtime.interopservices.dllimportattribute(en-us,VS.71).aspx

[Visual Basic]
<AttributeUsage(AttributeTargets.Method)>
NotInheritable Public Class DllImportAttribute
Inherits Attribute
[C#]
[AttributeUsage(AttributeTargets.Method)]
public sealed class DllImportAttribute : Attribute
[C++]
[AttributeUsage(AttributeTargets::Method)]
public __gc __sealed class DllImportAttribute : public Attribute
[JScript]
publicAttributeUsage(AttributeTargets.Method)
class DllImportAttribute extends Attribute

Public Constructors
Supported by the .NET Compact Framework.
Initializes a new instance of the DllImportAttribute class with the name of the DLL containing the method to import.
Public Fields
public fieldBestFitMapping
Enables or disables best-fit mapping behavior when converting Unicode characters to ANSI characters.
Supported by the .NET Compact Framework.
Indicates the calling convention of an entry point.
Supported by the .NET Compact Framework.
Indicates how to marshal string parameters to the method and controls name mangling.
Supported by the .NET Compact Framework.
Indicates the name or ordinal of the DLL entry point to be called.
public fieldExactSpelling
Controls whether the 
DllImportAttribute.CharSet field causes the common language runtime to search an unmanaged DLL for entry-point names other than the one specified.
public fieldPreserveSig
Indicates whether the signature is a direct translation of the unmanaged entry point.
Supported by the .NET Compact Framework.
Indicates whether the callee calls the SetLastError Win32 API function before returning from the attributed method.
public fieldThrowOnUnmappableChar
Enables or disables the throwing of an exception on an unmappable Unicode character that is converted to an ANSI '?' character.
Public Properties
public propertyTypeId (inherited from Attribute)
When implemented in a derived class, gets a unique identifier for this Attribute.
Supported by the .NET Compact Framework.
Gets the name of the DLL file that contains the entry point.
Public Methods
public methodEquals (inherited from Object)
Supported by the .NET Compact Framework.
Overloaded. Determines whether two Object instances are equal.
public methodGetHashCode (inherited from Attribute)
Supported by the .NET Compact Framework.
Overridden. Returns the hash code for this instance.
public methodGetType (inherited from Object)
Supported by the .NET Compact Framework.
Gets the Type of the current instance.
public methodIsDefaultAttribute (inherited from Attribute)
When overridden in a derived class, returns an indication whether the value of this instance is the default value for the derived class.
public methodMatch (inherited from Attribute)
Supported by the .NET Compact Framework.
When overridden in a derived class, returns a value indicating whether this instance equals a specified object.
public methodToString (inherited from Object)
Supported by the .NET Compact Framework.
Returns a String that represents the current Object.
Protected Methods
protected methodFinalize (inherited from Object)
Supported by the .NET Compact Framework.
Overridden. Allows an Object to attempt to free resources and perform other cleanup operations before the Object is reclaimed by garbage collection.
In C# and C++, finalizers are expressed using destructor syntax.
protected methodMemberwiseClone (inherited from Object)
Supported by the .NET Compact Framework.
Creates a shallow copy of the current Object.

另有其他方法操作DLL,但對我來講太難了,老樣子Copy下來,以便不急之需。
資料出處: 
http://www.cnblogs.com/james.wong/articles/94004.html
============================================================================================================== 
C#.DLL Import
C# 程序員參考
平台調用教程
平台調用服務 (PInvoke) 允許託管代碼調用在 DLL 中實現的非託管函數。
本教程說明使用什麼方法才能從 C# 調用非託管 DLL 函數。該教程所討論的屬性允許您調用這些函數並使數據類型得到正確封送。
示例文件
請參見「平台調用」示例以下載和生成該教程所討論的示例文件。
平台調用
其他閱讀材料
教程
C# 代碼有以下兩種可以直接調用非託管代碼的方法:
對於這兩種技術,都必須向 C# 編譯器提供非託管函數的聲明,並且還可能需要向 C# 編譯器提供如何封送與非託管代碼之間傳遞的參數和返回值的說明。
該教程由下列主題組成:
該教程包括下列示例:
直接從 C# 調用 DLL 導出
若要聲明一個方法使其具有來自 DLL 導出的實現,請執行下列操作:
  • 使用 C# 關鍵字 static 和 extern 聲明方法。
  • 將 DllImport 屬性附加到該方法。DllImport 屬性允許您指定包含該方法的 DLL 的名稱。通常的做法是用與導出的方法相同的名稱命名 C# 方法,但也可以對 C# 方法使用不同的名稱。
  • 還可以為方法的參數和返回值指定自定義封送處理信息,這將重寫 .NET Framework 的默認封送處理。
示例 1
本示例顯示如何使用 DllImport 屬性通過調用 msvcrt.dll 中的 puts 輸出消息。
// PInvokeTest.cs
using System;
using System.Runtime.InteropServices;

class PlatformInvokeTest
{
[DllImport("msvcrt.dll")]
public static extern int puts(string c);
[DllImport("msvcrt.dll")]
internal static extern int _flushall();

public static void Main()
{
puts("Test");
_flushall();
}
}
輸出
Test
代碼討論
前面的示例顯示了聲明在非託管 DLL 中實現的 C# 方法的最低要求。PlatformInvokeTest.puts 方法用 static 和 extern 修飾符聲明並且具有 DllImport 屬性,該屬性使用默認名稱 puts 通知編譯器此實現來自 msvcrt.dll。若要對 C# 方法使用不同的名稱(如 putstring),則必須在 DllImport 屬性中使用 EntryPoint 選項,如下所示:
[DllImport("msvcrt.dll", EntryPoint="puts")]
有關 DllImport 屬性的語法的更多信息,請參見 DllImportAttribute 類
默認封送處理和為非託管方法的參數指定自定義封送處理
當從 C# 代碼中調用非託管函數時,公共語言運行庫必須封送參數和返回值。
對於每個 .NET Framework 類型均有一個默認非託管類型,公共語言運行庫將使用此非託管類型在託管到非託管的函數調用中封送數據。例如,C# 字符串值的默認封送處理是封送為 LPTSTR(指向 TCHAR 字符緩衝區的指針)類型。可以在非託管函數的 C# 聲明中使用 MarshalAs 屬性重寫默認封送處理。
示例 2
本示例使用 DllImport 屬性輸出一個字符串。它還顯示如何通過使用 MarshalAs 屬性重寫函數參數的默認封送處理。
// Marshal.cs
using System;
using System.Runtime.InteropServices;

class PlatformInvokeTest
{
[DllImport("msvcrt.dll")]
public static extern int puts(
[MarshalAs(UnmanagedType.LPStr)]
string m);
[DllImport("msvcrt.dll")]
internal static extern int _flushall();


public static void Main()
{
puts("Hello World!");
_flushall();
}
}
輸出
運行此示例時,字符串
Hello World!
將顯示在控制台上。
代碼討論
在前面的示例中,puts 函數的參數的默認封送處理已從默認值 LPTSTR 重寫為 LPSTR。
MarshalAs 屬性可以放置在方法參數、方法返回值以及結構和類的字段上。若要設置方法返回值的封送處理,請將 MarshalAs 屬性與返回屬性位置重寫一起放置在方法上的屬性塊中。例如,若要顯式設置 puts 方法返回值的封送處理:
...
[DllImport("msvcrt.dll")]
[return : MarshalAs(UnmanagedType.I4)]
public static extern int puts(
...
有關 MarshalAs 屬性的語法的更多信息,請參見 MarshalAsAttribute 類
注意   In 和 Out 屬性可用於批註非託管方法的參數。它們與 MIDL 源文件中的 in 和 out 修飾符的工作方式類似。請注意,Out 屬性與 C# 參數修飾符 out 不同。有關 In 和 Out 屬性的更多信息,請參見 InAttribute 類和 OutAttribute 類
為用戶定義的結構指定自定義封送處理
可以為傳遞到非託管函數或從非託管函數返回的結構和類的字段指定自定義封送處理屬性。通過向結構或類的字段中添加 MarshalAs屬性可以做到這一點。還必須使用 StructLayout 屬性設置結構的佈局,還可以控制字符串成員的默認封送處理,並設置默認封裝大小。
示例 3
本示例說明如何為結構指定自定義封送處理屬性。
請考慮下面的 C 結構:
typedef struct tagLOGFONT
{
LONG lfHeight;
LONG lfWidth;
LONG lfEscapement;
LONG lfOrientation;
LONG lfWeight;
BYTE lfItalic;
BYTE lfUnderline;
BYTE lfStrikeOut;
BYTE lfCharSet;
BYTE lfOutPrecision;
BYTE lfClipPrecision;
BYTE lfQuality;
BYTE lfPitchAndFamily;
TCHAR lfFaceName[LF_FACESIZE];
} LOGFONT;
在 C# 中,可以使用 StructLayout 和 MarshalAs 屬性描述前面的結構,如下所示:
// logfont.cs
// compile with: /target:module
using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
public class LOGFONT
{
public const int LF_FACESIZE = 32;
public int lfHeight;
public int lfWidth;
public int lfEscapement;
public int lfOrientation;
public int lfWeight;
public byte lfItalic;
public byte lfUnderline;
public byte lfStrikeOut;
public byte lfCharSet;
public byte lfOutPrecision;
public byte lfClipPrecision;
public byte lfQuality;
public byte lfPitchAndFamily;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=LF_FACESIZE)]
public string lfFaceName;
}
有關 StructLayout 屬性的語法的更多信息,請參見 StructLayoutAttribute 類
然後即可將該結構用在 C# 代碼中,如下所示:
// pinvoke.cs
// compile with: /addmodule:logfont.netmodule
using System;
using System.Runtime.InteropServices;

class PlatformInvokeTest
{
[DllImport("gdi32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr CreateFontIndirect(
[In, MarshalAs(UnmanagedType.LPStruct)]
LOGFONT lplf // characteristics
);

[DllImport("gdi32.dll")]
public static extern bool DeleteObject(
IntPtr handle
);

public static void Main()
{
LOGFONT lf = new LOGFONT();
lf.lfHeight = 9;
lf.lfFaceName = "Arial";
IntPtr handle = CreateFontIndirect(lf);

if (IntPtr.Zero == handle)
{
Console.WriteLine("Can't creates a logical font.");
}
else
{

if (IntPtr.Size == 4)
Console.WriteLine("{0:X}", handle.ToInt32());
else
Console.WriteLine("{0:X}", handle.ToInt64());

// Delete the logical font created.
if (!DeleteObject(handle))
Console.WriteLine("Can't delete the logical font");
}
}
}
運行示例
C30A0AE5
代碼討論
在前面的示例中,CreateFontIndirect 方法使用了一個 LOGFONT 類型的參數。MarshalAs 和 In 屬性用於限定此參數。程序將由此方法返回的數值顯示為十六進制大寫字符串。
註冊回調方法
若要註冊調用非託管函數的託管回調,請用相同的參數列表聲明一個委託並通過 PInvoke 傳遞它的一個實例。在非託管端,它將顯示為一個函數指針。有關 PInvoke 和回調的更多信息,請參見平台調用詳解
例如,考慮以下非託管函數 MyFunction,此函數要求 callback 作為其參數之一:
typedef void (__stdcall *PFN_MYCALLBACK)();
int __stdcall MyFunction(PFN_ MYCALLBACK callback);
若要從託管代碼調用 MyFunction,請聲明該委託,將 DllImport 附加到函數聲明,並根據需要封送任何參數或返回值:
public delegate void MyCallback();
[DllImport("MYDLL.DLL")]
public static extern void MyFunction(MyCallback callback);
同時,請確保委託實例的生存期覆蓋非託管代碼的生存期;否則,委託在經過垃圾回收後將不再可用。

沒有留言:

張貼留言