Averiguar la versión de Windows usando API: GetVersion y GetVersionEx

 
Publicado el 24/May/2007
Actualizado el 24/May/2007
Autor: Guillermo 'guille' Som

Pulsa aquí, si quieres la versión para Visual Basic 6.0.

Pulsa aquí para ver cómo averiguar la versión del sistema operativo sin usar API.


Cómo averiguar la versión actual de Windows con Visual Basic .NET o C#, usando las funciones del API: GetVersion y GetVersionEx. Y como de costumbre, con código para VB como para C#.

 

 

Introducción:

Aquí tienes la forma de averiguar la versión de Windows en la que se está ejecutando tu aplicación, pero usando las funciones del API.

Te muestro dos formas de averiguarlo, una es usando la función GetVersion y la otra es usando GetVersionEx que utiliza el tipo de datos OSVERSIONINFOEX.
Aunque en realidad son tres formas, pero dos de ellas usan la misma función GetVersionEx aunque con dos versiones diferentes del tipo OSVERSIONINFO.

Nota:
Para usar el atributo DllImport debes añadir una importación del espacio de nombres System.Runtime.InteropServices.

 

Nota:
El código mostrado en el artículo es para Visual Basic .NET, más abajo está también el código para C#.

 

Las definiciones de las funciones, tipos y constantes

La función GetVersion es muy simple, solo devuelve un valor de tipo Integer en el que están los tres valores típicos de la versión: Mayor, Menor y Build. Lo que pasa es que está todo como "aglomerado" y hace falta desglosarlo, para ese desglose se deben tomar los valores dividiendo (o troceando) el valor en distintas partes, para eso se necesitan de otras funciones, ahora lo verás en la sección de cómo usar la función.

La definición de la función para Visual Basic .NET:

<DllImport("kernel32.dll")> _
Public Function GetVersion() As Integer
End Function

 

La función GetVersionEx utiliza un tipo de datos en el que se indican los diferentes valores. Esa versión puede usar el mismo tipo pero con más o menos información, por tanto, aquí te muestro dos definiciones según se quiera usar la versión reducida o extendida.

La definición de los tipos y las funciones:

' La versión simple
<DllImport("kernel32.dll")> _
Public Function GetVersionEx( _
    <MarshalAs(UnmanagedType.Struct)> ByRef osinfo As OSVERSIONINFO _
    ) As Integer
End Function

<StructLayout(LayoutKind.Sequential)> _
Public Structure OSVERSIONINFO
    Public dwOSVersionInfoSize As Integer
    Public dwMajorVersion As Integer
    Public dwMinorVersion As Integer
    Public dwBuildNumber As Integer
    Public dwPlatformId As Integer
    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=128)> _
    Public szCSDVersion As String
End Structure

' La versión extendida
<DllImport("kernel32.dll")> _
Public Function GetVersionEx( _
    <MarshalAs(UnmanagedType.Struct)> ByRef osinfo As OSVERSIONINFOEX _
    ) As Integer
End Function

<StructLayout(LayoutKind.Sequential)> _
Public Structure OSVERSIONINFOEX
    Public dwOSVersionInfoSize As Integer
    Public dwMajorVersion As Integer
    Public dwMinorVersion As Integer
    Public dwBuildNumber As Integer
    Public dwPlatformId As Integer
    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=128)> _
    Public szCSDVersion As String
    Public wServicePackMajor As Short
    Public wServicePackMinor As Short
    Public wSuiteMask As Short
    Public wProductType As Byte
    Public wReserved As Byte
End Structure

 

Cómo usar las funciones y tratar los resultados

Para usar la función GetVersion no hay que hacer nada especial, salvo guardar el valor en una variable de tipo Integer, y como te comentaba antes, ese valor hay que "desgranarlo" para obtener los valores correspondientes.

Veamos cómo se usa y más abajo puedes ver las funciones "extras" que he usado:

Dim res As Integer
res = GetVersion()

Dim major, minor, build As Integer

major = LoByte(LoWord(res))
minor = HiByte(LoWord(res))

' A partir de NT 4 tiene el Build (no en Me/9x)
build = HiWord(res)

Console.WriteLine("Versión: v{0}.{1}.{2}", major, minor, build)

 

Para usar la versión GetVersionEx debemos declarar una variable del tipo OSVERSIONINFO que es donde nos indica los valores de la versión. Aquí te muestro el código de forma simple, pero en el ZIP con el proyecto completo tanto para Visual Basic .NET como para C#, tienes más información de cómo identificar el sistema operativo según los valores de la versión.

Dim osv As OSVERSIONINFO = Nothing
Dim res As Integer

osv.dwOSVersionInfoSize = Marshal.SizeOf(osv)
res = GetVersionEx(osv)
Console.Write("Versión: v{0}.{1}.{2}", osv.dwMajorVersion, osv.dwMinorVersion, osv.dwBuildNumber)

Dim s As String = szTrim(osv.szCSDVersion)
If String.IsNullOrEmpty(s) = False Then
    Console.Write(" ({0})", s)
End If
Console.WriteLine()

 

Las versiones de Windows dependen del valor de Mayor y Menor, (y la combinación de los dos), y más o menos te puede servir la siguiente tabla, que es aplicable a los valores de las dos funciones comentadas:

 

Sistema operativo   Mayor
Windows NT 3.51   3
Windows 95, 98, Me y NT 4.0   4
Windows 2000, XP y 2003   5
Windows Vista/Longhorn   6

 

Sistema operativo   Menor
Windows NT 3.51   51
Windows 95   0
Windows 98   10
Windows Me   90
Windows NT 4.0   0
Windows 2000   0
Windows XP   1
Windows 2003   2
Windows Vista/Longhorn   0

Por ejemplo, si el valor de Mayor es 5 y el de Menor es 2 es un Windows 2003 Server.
Si el valor de Mayor es 5 y el de Menor es 1 es un Windows XP.

Para averiguar cosas de Windows 9x o de Windows 2000 Server, si es XP Home o Profesional, lo ves en el ejemplo completo, que están casi todas las explicaciones necesarias y que son aburridas y no es plan de rellenar con cosas que a lo mejor no es lo que te interesa.

 

Y esto es todo, como siempre, espero que te sea de utilidad.

Nos vemos.
Guillermo

 


Código para Visual Basic.NET (VB.NET) El código para Visual Basic .NET (cualquier versión)
Private Function szTrim(ByVal s As String) As String
    ' Quita los caracteres en blanco y los Chr$(0)                  (13/Dic/01)
    Dim i As Integer

    ' Al estilo de .NET
    i = s.IndexOf(Chr(0))
    If i > -1 Then
        s = s.Substring(0, i)
    End If

    Return s.Trim()
End Function

Private Function LoWord(ByVal numero As Integer) As Integer
    ' Devuelve el LoWord del número pasado como parámetro
    Return numero And &HFFFF
End Function

Private Function HiWord(ByVal numero As Integer) As Integer
    ' Devuelve el HiWord del número pasado como parámetro
    Return numero \ &H10000 And &HFFFF
End Function

' Para valores (0~65535)
Private Function LoByte(ByVal numero As Integer) As Integer
    Return numero And &HFF
End Function

Private Function HiByte(ByVal numero As Integer) As Integer
    Return numero \ &H100 And &HFF
End Function

 

Código para C Sharp (C#) El código para C# (cualquier versión)
[DllImport("kernel32.dll")]
static extern public int GetVersion();


static void Main(string[] args)
{
    Console.Title = "Prueba de GetVersion (C#)";

    Console.WriteLine("Usando GetVersion:");
    mostrarVersion();
    Console.WriteLine();

    Console.ReadKey();
}

static private void mostrarVersion()
{
    int res;
    res = GetVersion();

    int major, minor, build;

    major = LoByte(LoWord(res));
    minor = HiByte(LoWord(res));

    // A partir de NT 4 tiene el Build (no en Me/9x)
    build = HiWord(res);

    Console.WriteLine("Versión: v{0}.{1}.{2}", major, minor, build);
}

static private string szTrim(string s)
{
    // Quita los caracteres en blanco y los Chr$(0)                  (13/Dic/01)
    int i;

    // Al estilo de .NET
    i = s.IndexOf((char)0);
    if (i > -1)
    {
        s = s.Substring(0, i);
    }

    return s.Trim();
}

static private int LoWord(int numero)
{
    // Devuelve el LoWord del número pasado como parámetro
    return numero & 0xFFFF;
}

static private int HiWord(int numero)
{
    // Devuelve el HiWord del número pasado como parámetro
    return numero / 0x10000 & 0xFFFF;
}

// Para valores (0~65535)
static private int LoByte(int numero)
{
    return numero & 0xFF;
}

static private int HiByte(int numero)
{
    return numero / 0x100 & 0xFF;
}


Espacios de nombres usados en el código de este artículo:

System.Runtime.InteropServices
 


Código de ejemplo (comprimido):

El código de ejemplo es para Visual Studio 2005, (incluso para las versiones Express), pero el código en realidad lo puedes usar con cualquier versión anterior, tanto de Visual Basic como de Visual C#, aunque tendrás que hacer pequeños cambios y copiarlo manualmente desde los ficheros de código.

Código de ejemplo para Visual Basic: versionWindowsAPI_vb.zip - 10.00 KB

(MD5 checksum: 2003C7CD44527A8C85B405F6C72216A0)

 

Código de ejemplo para Visual C#: versionWindowsAPI_cs.zip - 2.78 KB

(MD5 checksum: 14C22E1C0E062DB6380B996BE03689EA)

Nota: La versión de C# aún no está completa.


Ir al índice principal de el Guille

Valid XHTML 1.0 Transitional ¡CSS Válido!