Condividi tramite


Esempio di OSInfo

Aggiornamento: novembre 2007

In questo esempio viene dimostrato come passare una classe formattata per valore o una struttura per riferimento come parametro a una funzione non gestita per la quale è prevista una struttura con un buffer di caratteri incorporato.

Nell'esempio di OSInfo viene utilizzata la seguente funzione non gestita, illustrata con la dichiarazione di funzione originale:

  • GetVersionEx esportata da Kernel32.dll.

    // BOOL GetVersionEx(LPOSVERSIONINFO lpVersionInfo);
    

La struttura originale passata alla funzione contiene i seguenti elementi:

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

In questo esempio, la classe OSVersionInfo e la struttura OSVersionInfo2 producono gli stessi risultati quando vengono passate alla funzione non gestita. Il valore dell'enumerazione UnmanagedType viene impostato dall'attributo MarshalAsAttribute su ByValTStr, che consente di identificare la matrice di caratteri inline a lunghezza fissa presente nella struttura non gestita.

La classe LibWrap contiene due prototipi: GetVersionEx passa la classe come parametro e GetVersionEx2 passa una struttura come parametro. Mediante l'applicazione esplicita degli attributi InAttribute e OutAttribute, nell'esempio vengono garantiti il marshalling di OSVersionInfo come parametro in/out e la visualizzazione delle modifiche restituite con il marshalling da parte del chiamante. Per questioni di prestazioni, l'attributo direzionale predefinito per una classe è In, condizione che impedisce al chiamante di vedere le modifiche restituite con il marshalling.

La struttura OSVersionInfo2, che viene in genere passata per valore, è dichiarata con la parola chiave ref (ByRef in Visual Basic) e viene passata per riferimento. Il metodo Marshal.SizeOf consente di determinare la dimensione in byte della struttura non gestita.

Il codice sorgente per gli esempi di codice riportati di seguito è fornito dall'Esempio di tecnologia di richiamo piattaforma di .NET Framework.

Dichiarazione dei prototipi

< 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 );  
}

Chiamata delle funzioni

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 );
      …     
   }
}

Vedere anche

Attività

Esempio di tecnologia di richiamo piattaforma

Concetti

Marshalling di stringhe

Tipi di dati del richiamo piattaforma

Marshalling predefinito per le stringhe

Creazione di prototipi nel codice gestito