Freigeben über


OSInfo-Beispiel

Dieses Beispiel demonstriert, wie eine formatierte Klasse durch einen Wert bzw. eine Struktur durch einen Verweis als Parameter an eine nicht verwaltete Funktion übergeben wird, die eine Struktur mit einem eingebetteten Zeichenpuffer erwartet.

Das OSInfo-Beispiel verwendet die folgende nicht verwaltete Funktion, die zusammen mit ihrer ursprünglichen Funktionsdeklaration aufgeführt wird:

  • GetVersionEx aus Kernel32.dll exportiert.

    // BOOL GetVersionEx(LPOSVERSIONINFO lpVersionInfo);
    

Die ursprüngliche, an die Funktion übergebene Struktur enthält die folgenden Elemente:

typedef struct _OSVERSIONINFO
{ 
  DWORD dwOSVersionInfoSize; 
  DWORD dwMajorVersion; 
  DWORD dwMinorVersion; 
  DWORD dwBuildNumber; 
  DWORD dwPlatformId; 
  TCHAR szCSDVersion[ 128 ]; 
} OSVERSIONINFO; 

In diesem Beispiel erzeugen die OSVersionInfo-Klasse und die OSVersionInfo2-Struktur dieselben Ergebnisse, wenn sie an eine nicht verwaltete Funktion übergeben werden. Das MarshalAsAttribute-Attribut legt den Enumerationswert UnmanagedType auf ByValTStr fest. Dieser Wert wird zum Identifizieren des Inlinearrays fester Länge verwendet, das innerhalb der nicht verwalteten Strukturen erscheint.

Die LibWrap-Klasse enthält zwei Prototypen: GetVersionEx übergibt die Klasse als Parameter, und GetVersionEx2 übergibt eine Struktur als Parameter. Indem das InAttribute-Attribut und das OutAttribute-Attribut explizit angewendet werden, stellt das Beispiel sicher, dass OSVersionInfo als In/Out-Parameter gemarshallt wird und der Aufrufer die zurückgemarshallten Änderungen sehen kann. (Aus Leistungsgründen ist das direktionale Attribut für eine Klasse In, sodass der Aufrufer die zurückgemarshallten Änderungen nicht sehen kann.)

Die OSVersionInfo2-Struktur, die in der Regel durch einen Wert übergeben wird, wird mit dem ref-Schlüsselwort (ByRef in Visual Basic) deklariert und durch einen Verweis übergeben. Die Marshal.SizeOf-Methode bestimmt die Größe der nicht verwalteten Struktur in Bytes.

Deklarieren von Prototypen

<StructLayout(LayoutKind.Sequential)> _
Public Class OSVersionInfo
    Public OSVersionInfoSize As Integer
    Public MajorVersion As Integer
    Public MinorVersion As Integer
    Public BuildNumber As Integer
    Public PlatformId As Integer

    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=128)> _
    Public CSDVersion As String
End Class

<StructLayout(LayoutKind.Sequential)> _
Public Structure OSVersionInfo2
    Public OSVersionInfoSize As Integer
    Public MajorVersion As Integer
    Public MinorVersion As Integer
    Public BuildNumber As Integer
    Public PlatformId As Integer

    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=128)> _
    Public CSDVersion As String
End Structure

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
[StructLayout(LayoutKind.Sequential)]
public class OSVersionInfo
{
    public int OSVersionInfoSize;
    public int MajorVersion;
    public int MinorVersion;
    public int BuildNumber;
    public int PlatformId;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
    public String CSDVersion;
}

[StructLayout(LayoutKind.Sequential)]
public struct OSVersionInfo2
{
    public int OSVersionInfoSize;
    public int MajorVersion;
    public int MinorVersion;
    public int BuildNumber;
    public int PlatformId;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
    public String CSDVersion;
}

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);
}
[StructLayout(LayoutKind::Sequential)]
public ref class OSVersionInfo
{
public:
    int OSVersionInfoSize;
    int MajorVersion;
    int MinorVersion;
    int BuildNumber;
    int PlatformId;

    [MarshalAs(UnmanagedType::ByValTStr, SizeConst=128)]
    String^ CSDVersion;
};

[StructLayout(LayoutKind::Sequential)]
public value struct OSVersionInfo2
{
public:
    int OSVersionInfoSize;
    int MajorVersion;
    int MinorVersion;
    int BuildNumber;
    int PlatformId;

    [MarshalAs(UnmanagedType::ByValTStr, SizeConst=128)]
    String^ CSDVersion;
};

public ref class LibWrap
{
public:
    [DllImport("kernel32")]
    static bool GetVersionEx([In, Out] OSVersionInfo^ osvi);

    [DllImport("kernel32", EntryPoint="GetVersionEx")]
    static bool GetVersionEx2(OSVersionInfo2% osvi);
};

Aufrufen von Funktionen

Public Class App
    Public Shared Sub Main()
        Console.WriteLine(vbNewLine + "Passing OSVersionInfo as a class")

        Dim osvi As New OSVersionInfo()
        osvi.OSVersionInfoSize = Marshal.SizeOf(osvi)

        LibWrap.GetVersionEx(osvi)

        Console.WriteLine("Class size:    {0}", osvi.OSVersionInfoSize)
        Console.WriteLine("OS Version:    {0}.{1}", osvi.MajorVersion, osvi.MinorVersion)

        Console.WriteLine(vbNewLine + "Passing OSVersionInfo2 as a struct")

        Dim osvi2 As new OSVersionInfo2()
        osvi2.OSVersionInfoSize = Marshal.SizeOf(osvi2)

        LibWrap.GetVersionEx2(osvi2)
        Console.WriteLine("Struct size:   {0}", osvi2.OSVersionInfoSize)
        Console.WriteLine("OS Version:    {0}.{1}", osvi2.MajorVersion, osvi2.MinorVersion)
    End Sub
End Class
public class App
{
    public static void Main()
    {
        Console.WriteLine("\nPassing OSVersionInfo as a class");

        OSVersionInfo osvi = new OSVersionInfo();
        osvi.OSVersionInfoSize = Marshal.SizeOf(osvi);

        LibWrap.GetVersionEx(osvi);

        Console.WriteLine("Class size:    {0}", osvi.OSVersionInfoSize);
        Console.WriteLine("OS Version:    {0}.{1}", osvi.MajorVersion, osvi.MinorVersion);

        Console.WriteLine("\nPassing OSVersionInfo as a struct" );

        OSVersionInfo2 osvi2 = new OSVersionInfo2();
        osvi2.OSVersionInfoSize = Marshal.SizeOf(osvi2);

        LibWrap.GetVersionEx2(ref osvi2);
        Console.WriteLine("Struct size:   {0}", osvi2.OSVersionInfoSize);
        Console.WriteLine("OS Version:    {0}.{1}", osvi2.MajorVersion, osvi2.MinorVersion);
    }
}
public ref class App
{
public:
    static void Main()
    {
        Console::WriteLine("\nPassing OSVersionInfo as a class");

        OSVersionInfo^ osvi = gcnew OSVersionInfo();
        osvi->OSVersionInfoSize = Marshal::SizeOf(osvi);

        LibWrap::GetVersionEx(osvi);

        Console::WriteLine("Class size:    {0}", osvi->OSVersionInfoSize);
        Console::WriteLine("OS Version:    {0}.{1}", osvi->MajorVersion, osvi->MinorVersion);

        Console::WriteLine("\nPassing OSVersionInfo as a struct" );

        OSVersionInfo2 osvi2;
        osvi2.OSVersionInfoSize = Marshal::SizeOf(osvi2);

        LibWrap::GetVersionEx2(osvi2);
        Console::WriteLine("Struct size:   {0}", osvi2.OSVersionInfoSize);
        Console::WriteLine("OS Version:    {0}.{1}", osvi2.MajorVersion, osvi2.MinorVersion);
    }
};

Siehe auch

Konzepte

Marshallen von Zeichenfolgen

Datentypen für den Plattformaufruf

Standardmäßiges Marshalling für Zeichenfolgen

Weitere Ressourcen

Creating Prototypes in Managed Code