文章摘要:[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]
public
AttributeUsage(AttributeTargets.Method)
class DllImportAttribute extends Attribute
DllImportAttribute Members
http://msdn.microsoft.com/zh-tw/library/system.runtime.interopservices.dllimportattribute_members(en-us,VS.71).aspx
Public Constructors
DllImportAttribute Constructor
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
BestFitMapping
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.
ExactSpelling
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.
PreserveSig
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.
ThrowOnUnmappableChar
Enables or disables the throwing of an exception on an unmappable Unicode character that is converted to an ANSI '?' character.
Public Properties
TypeId (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
Equals (inherited from Object)
Supported by the .NET Compact Framework.
Overloaded. Determines whether two Object instances are equal.
GetHashCode (inherited from Attribute)
Supported by the .NET Compact Framework.
Overridden. Returns the hash code for this instance.
GetType (inherited from Object)
Supported by the .NET Compact Framework.
Gets the Type of the current instance.
IsDefaultAttribute (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.
Match (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.
ToString (inherited from Object)
Supported by the .NET Compact Framework.
Returns a String that represents the current Object.
Protected Methods
Finalize (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.
MemberwiseClone (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# 代碼有以下兩種可以直接調用非託管代碼的方法:
-
直接調用從 DLL 導出的函數。
-
調用 COM 對象上的接口方法(有關更多信息,請參見 COM Interop 第一部分:C# 客戶端教程)。
對於這兩種技術,都必須向 C# 編譯器提供非託管函數的聲明,並且還可能需要向 C# 編譯器提供如何封送與非託管代碼之間傳遞的參數和返回值的說明。
該教程由下列主題組成:
該教程包括下列示例:
若要聲明一個方法使其具有來自 DLL 導出的實現,請執行下列操作:
-
使用 C# 關鍵字 static 和 extern 聲明方法。
-
將 DllImport 屬性附加到該方法。DllImport 屬性允許您指定包含該方法的 DLL 的名稱。通常的做法是用與導出的方法相同的名稱命名 C# 方法,但也可以對 C# 方法使用不同的名稱。
-
還可以為方法的參數和返回值指定自定義封送處理信息,這將重寫 .NET Framework 的默認封送處理。
本示例顯示如何使用 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 屬性重寫默認封送處理。
本示例使用 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 屬性設置結構的佈局,還可以控制字符串成員的默認封送處理,並設置默認封裝大小。
本示例說明如何為結構指定自定義封送處理屬性。
請考慮下面的 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);
同時,請確保委託實例的生存期覆蓋非託管代碼的生存期;否則,委託在經過垃圾回收後將不再可用。
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET