OSInfo 範例
更新:2007 年 11 月
這個範例示範如何以傳值方式傳遞格式化的類別或以傳址方式傳遞結構做為 Unmanaged 函式的參數,這個 Unmanaged 函式預期具有內嵌字元緩衝區的結構。
OSInfo 範例使用下列 Unmanaged 函式,顯示其原始函式宣告:
從 Kernel32.dll 匯出 GetVersionEx。
// BOOL GetVersionEx(LPOSVERSIONINFO lpVersionInfo);
傳遞到函式的原始結構包含以下元素:
typedef struct _OSVERSIONINFO
{
DWORD dwOSVersionInfoSize;
DWORD dwMajorVersion;
DWORD dwMinorVersion;
DWORD dwBuildNumber;
DWORD dwPlatformId;
TCHAR szCSDVersion[ 128 ];
} OSVERSIONINFO;
在這個範例中,當傳遞至 Unmanaged 函式時,OSVersionInfo 類別和 OSVersionInfo2 結構會產生相同的結果。MarshalAsAttribute 屬性會將 UnmanagedType 列舉值設定為 ByValTStr,用來識別出現在 Unmanaged 結構之中的內嵌、固定長度的字元陣列。
LibWrap 類別包含兩個原型:GetVersionEx 傳遞類別當成參數,而 GetVersionEx2 傳遞結構當成參數。在這個範例中,藉由明確套用 InAttribute 和 OutAttribute 屬性,可以確保將 OSVersionInfo 封送處理為 In/Out 參數,而呼叫端可以查看封送處理回的變更(由於效能因素,類別的預設方向屬性是 In,避免呼叫端查看封送處理回的變更)。
一般以傳值 (By Value) 方式傳遞的 OSVersionInfo2 結構,會用 ref (Visual Basic 中為 ByRef) 關鍵字宣告,並且以傳址 (By Reference) 方式傳遞。Marshal.SizeOf 方法會決定 Unmanaged 結構的大小 (以位元組為單位)。
下列程式碼範例的原始程式碼是由 .NET Framework 平台叫用技術範例所提供。
宣告原型
< StructLayout( LayoutKind.Sequential )> _
Public Class OSVersionInfo
Public OSVersionInfoSize As Integer
…
< MarshalAs( UnmanagedType.ByValTStr, SizeConst := 128 )> _
Public versionString As String
End Class 'OSVersionInfo
< StructLayout( LayoutKind.Sequential )> _
Public Structure OSVersionInfo2
Public OSVersionInfoSize As Integer
…
< MarshalAs( UnmanagedType.ByValTStr, SizeConst := 128 )> _
Public versionString As String
End Structure 'OSVersionInfo2
Public Class LibWrap
Declare Ansi Function GetVersionEx Lib "kernel32" Alias _
"GetVersionExA" ( <[In], Out> ByVal osvi As OSVersionInfo ) As Boolean
Declare Ansi Function GetVersionEx2 Lib "kernel32" Alias _
"GetVersionExA" ( ByRef osvi As OSVersionInfo2 ) As Boolean
End Class 'LibWrap
[ StructLayout( LayoutKind.Sequential )]
public class OSVersionInfo
{
public int OSVersionInfoSize;
…
[ MarshalAs( UnmanagedType.ByValTStr, SizeConst=128 )]
public String versionString;
}
[ StructLayout( LayoutKind.Sequential )]
public struct OSVersionInfo2
{
public int OSVersionInfoSize;
…
[ MarshalAs( UnmanagedType.ByValTStr, SizeConst=128 )]
public String versionString;
}
public class LibWrap
{
[ DllImport( "kernel32" )]
public static extern bool GetVersionEx( [In, Out] OSVersionInfo osvi );
[ DllImport( "kernel32", EntryPoint="GetVersionEx" )]
public static extern bool GetVersionEx2( ref OSVersionInfo2 osvi );
}
呼叫函式
Public Class App
Public Shared Sub Main()
Console.WriteLine( ControlChars.CrLf + "Passing OSVersionInfo _
as class" )
Dim osvi As New OSVersionInfo()
osvi.OSVersionInfoSize = Marshal.SizeOf( osvi )
LibWrap.GetVersionEx( osvi )
Console.WriteLine( "Class size: {0}", osvi.OSVersionInfoSize )
…
Console.WriteLine( ControlChars.CrLf + "Passing OSVersionInfo _
as struct" )
Dim osvi2 As New OSVersionInfo2()
osvi2.OSVersionInfoSize = Marshal.SizeOf( osvi2 )
LibWrap.GetVersionEx2( osvi2 )
Console.WriteLine( "Struct size: {0}", osvi2.OSVersionInfoSize )
…
End Sub 'Main
End Class 'App
public class App
{
public static void Main()
{
Console.WriteLine( "\nPassing OSVersionInfo as class" );
OSVersionInfo osvi = new OSVersionInfo();
osvi.OSVersionInfoSize = Marshal.SizeOf( osvi );
LibWrap.GetVersionEx( osvi );
Console.WriteLine( "Class size: {0}", osvi.OSVersionInfoSize );
…
Console.WriteLine( "\nPassing OSVersionInfo as struct" );
OSVersionInfo2 osvi2 = new OSVersionInfo2();
osvi2.OSVersionInfoSize = Marshal.SizeOf( osvi2 );
LibWrap.GetVersionEx2( ref osvi2 );
Console.WriteLine( "Struct size: {0}", osvi2.OSVersionInfoSize );
…
}
}