GetVersionEX call fails from VB5 
Author Message
 GetVersionEX call fails from VB5

When attempting to run the sample code below, VB responds with:
        Compile Error:

        User-defined type may not be passed ByVal

I have scoured the MSDN CD's to no avail...  How do I call this (and
other) Win API's from Visual Basic?

Any help getting off the ground will be greatly appreciated!!!


Systems & Networks
Mississippi State University

Sample code:
-------------------------------------------------------------------------------------

Private Type OSVersionInfo
       dwOSVersionInfoSize As Long
       dwMajorVersion As Long
       dwMinorVersion As Long
       dwBuildNumber As Long
       dwPlatformId As Long
       szCSDVersion As String * 128      '  Maintenance string for PSS
usage
End Type

Private Declare Function GetVersionEx Lib "kernel32" Alias
"GetVersionExA" _
                (ByVal lpVersionInformation As OSVersionInfo) _
        As Long

Private Sub Form_Load()

Dim lresult As Long
Dim lpOSVer As OSVersionInfo

lpOSVer.dwOSVersionInfoSize = 0
lpOSVer.dwMajorVersion = 0
lpOSVer.dwMinorVersion = 0
lpOSVer.dwBuildNumber = 0
lpOSVer.dwPlatformId = 0
lpOSVer.szCSDVersion = String(128, 0)

lresult = GetVersionEx(lpOSVer)

End Sub



Fri, 06 Oct 2000 03:00:00 GMT  
 GetVersionEX call fails from VB5

Drop the ByVal in the declare .. the API viewer is wrong ...

Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (lpVersionInformation
As OSVERSIONINFO) As Long

--
Randy Birch, MVP Visual Basic
VBnet, The Visual Basic Developers Resource Centre
http://home.sprynet.com/sprynet/rasanen/vbnet/default.htm

Common Controls Replacement Project
http://www.mvps.org/ccrp

:When attempting to run the sample code below, VB responds with:
:        Compile Error:
:
:        User-defined type may not be passed ByVal
:
:I have scoured the MSDN CD's to no avail...  How do I call this (and
:other) Win API's from Visual Basic?
:
:Any help getting off the ground will be greatly appreciated!!!
:

:Systems & Networks
:Mississippi State University
:
:Sample code:
:-------------------------------------------------------------------------------------
:
:Private Type OSVersionInfo
:       dwOSVersionInfoSize As Long
:       dwMajorVersion As Long
:       dwMinorVersion As Long
:       dwBuildNumber As Long
:       dwPlatformId As Long
:       szCSDVersion As String * 128      '  Maintenance string for PSS
:usage
:End Type
:
:
:Private Declare Function GetVersionEx Lib "kernel32" Alias
:"GetVersionExA" _
:                (ByVal lpVersionInformation As OSVersionInfo) _
:        As Long
:
:
:
:Private Sub Form_Load()
:
:
:Dim lresult As Long
:Dim lpOSVer As OSVersionInfo
:
:
:
:lpOSVer.dwOSVersionInfoSize = 0
:lpOSVer.dwMajorVersion = 0
:lpOSVer.dwMinorVersion = 0
:lpOSVer.dwBuildNumber = 0
:lpOSVer.dwPlatformId = 0
:lpOSVer.szCSDVersion = String(128, 0)
:
:lresult = GetVersionEx(lpOSVer)
:
:
:End Sub
:
:
:



Fri, 06 Oct 2000 03:00:00 GMT  
 GetVersionEX call fails from VB5

Quote:

>When attempting to run the sample code below, VB responds with:
>        Compile Error:

>        User-defined type may not be passed ByVal
>. . .
>Private Type OSVersionInfo
>       dwOSVersionInfoSize As Long
>       dwMajorVersion As Long
>       dwMinorVersion As Long
>       dwBuildNumber As Long
>       dwPlatformId As Long
>       szCSDVersion As String * 128      '  Maintenance string for PSS
>usage
>End Type

>Private Declare Function GetVersionEx Lib "kernel32" Alias
>"GetVersionExA" _
>                (ByVal lpVersionInformation As OSVersionInfo) _
>        As Long

That *is* how this function is declared in win32api.txt, but it
clearly wrong. The OSVersionInfo parameter needs to be passed ByRef,
not ByVal. I think it should be OK with that change, but I haven't
tested it.

- Show quoted text -

Quote:
>Private Sub Form_Load()

>Dim lresult As Long
>Dim lpOSVer As OSVersionInfo

>lpOSVer.dwOSVersionInfoSize = 0
>lpOSVer.dwMajorVersion = 0
>lpOSVer.dwMinorVersion = 0
>lpOSVer.dwBuildNumber = 0
>lpOSVer.dwPlatformId = 0
>lpOSVer.szCSDVersion = String(128, 0)

>lresult = GetVersionEx(lpOSVer)

>End Sub

Before calling this function, you need to set dwOSVersionInfoSize to
the size of the structure, otherwise the function call will fail
somewhat mysteriously.

In general, if you see a Win32 function that takes a structure that
begins with a size field, they want you to put the structure size in
that field.

-Mike

To reach me by email, either use the link in my Web site at
www.geary.com, or delete "bitbucket." from my email address.
My apologies for the inconvenience provoked by our friends
the spammers.  <sigh>



Sat, 07 Oct 2000 03:00:00 GMT  
 GetVersionEX call fails from VB5

Quote:

>When attempting to run the sample code below, VB responds with:
>        Compile Error:

>        User-defined type may not be passed ByVal

>I have scoured the MSDN CD's to no avail...  How do I call this (and
>other) Win API's from Visual Basic?

Yes, I know about that too... I crashed into the very same error the first
time. Even removing ByVal doesn't work. You need to explicitly replace it
with ByRef. This is a hint: UDT's in Win32 API functions are *almost always*
passed ByRef. What you might want to do is to either get a copy of the Win32
API help file & port it manually (not recommended) or find someone's port of
it.

PS. Can anyone help me with this code, it is not giving the expected
results. I want the version string to say "Win98 4.10.1650" but instead I
get some *REALLY* long number (see code/picture for details).

PPS. Picture available at http://web.singnet.com.sg/~apesena/gveprob.gif

== Begin code ==
Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (ByRef
lpVersionInformation As OSVERSIONINFO) As Long

Dim rc as long
Dim lpVersionInfo as OSVERSIONINFO
lpVersionInfo.dwOSVersionSize=Len(lpVersionInfo)
rc=GetVersionEx(lpVersionInfo)
lblPlatform.Caption = lpVersionInfo.dwMajorVersion & "." &
lpVersionInfo.dwMinorVersion & "." & lpVersionInfo.dwBuildNumber

The version no. as you would see is 4.10.[some long number]. The 4.10 part
is understandable as I'm running Win98 but I only want to display the
version of Windows the person is running. How can I do this???

== end code ==

OK, I seem to have gotten a workaround by using  szCSDVersion instead of
dwBuildNumber. But it may change in the future...
--
My e-mail address may have 2 bugs in it; deBUG to reply.

Damit Senanayake
Damit's Home; http://web.singnet.com.sg/~apesena/
ICQ UIN: 6930718

"It's one small step for man, one giant leap for mankind." -- Neil Armstrong



Sun, 08 Oct 2000 03:00:00 GMT  
 GetVersionEX call fails from VB5

Quote:

>PS. Can anyone help me with this code, it is not giving the expected
>results. I want the version string to say "Win98 4.10.1650" but instead I
>get some *REALLY* long number (see code/picture for details).

>== Begin code ==
>Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (ByRef
>lpVersionInformation As OSVERSIONINFO) As Long

>Dim rc as long
>Dim lpVersionInfo as OSVERSIONINFO
>lpVersionInfo.dwOSVersionSize=Len(lpVersionInfo)
>rc=GetVersionEx(lpVersionInfo)
>lblPlatform.Caption = lpVersionInfo.dwMajorVersion & "." &
>lpVersionInfo.dwMinorVersion & "." & lpVersionInfo.dwBuildNumber

>The version no. as you would see is 4.10.[some long number]. The 4.10 part
>is understandable as I'm running Win98 but I only want to display the
>version of Windows the person is running. How can I do this???

>OK, I seem to have gotten a workaround by using  szCSDVersion instead of
>dwBuildNumber. But it may change in the future...

I think the documentation for OSVERSIONINFO would help explain what
happened here and how to fix it. Note the description of dwBuildNumber
for Win95, which undoubtedly applies to Win98 also.

Oh, not to be too nitpicky <g>, but from the point of view of a
Windows C/C++ programmer, the variable name "lpVersionInfo" is a bit
confusing. Traditionally, the "lp" prefix is used to indicate that the
variable is a pointer to the data, not the data itself. So a C/C++
Windows  programmer coding in VB would probably name the variable like
this:

Dim VersionInfo as OSVERSIONINFO

i.e. without the "lp" prefix. Or maybe just:

Dim vi as OSVERSIONINFO

to save some typing. Anything but that "lp" prefix... <g>

Anyway, it's your code, not mine, so feel free to disregard this
unrequested advice... <g>

And now for the OSVERSIONINFO documentation:

OSVERSIONINFO

The OSVERSIONINFO data structure contains operating system version
information. The information includes major and minor version numbers,
a build number, a platform identifier, and descriptive text about the
operating system. This structure is used with the GetVersionEx
function.

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

Quote:
} OSVERSIONINFO;

Members

dwOSVersionInfoSize
Specifies the size, in bytes, of this data structure. Set this member
to sizeof(OSVERSIONINFO) before calling the GetVersionEx function.

dwMajorVersion
Identifies the major version number of the operating system. For
example, for Windows NT version 3.51, the major version number is 3;
and for Windows NT version 4.0, the major version number is 4.

dwMinorVersion
Identifies the minor version number of the operating system. For
example, for Windows NT version 3.51, the minor version number is 51;
and for Windows NT version 4.0, the minor version number is 0.

dwBuildNumber
Windows NT: Identifies the build number of the operating system.
Windows 95: Identifies the build number of the operating system in the
low-order word. The high-order word contains the major and minor
version numbers.

dwPlatformId
Identifies the operating system platform. This member can be one of
the following values: Value Platform
VER_PLATFORM_WIN32s Win32s on Windows 3.1.  
VER_PLATFORM_WIN32_WINDOWS Win32 on Windows 95 or Windows 98.
For Windows 95, dwMinorVersion is 0.

For Windows 98, dwMinorVersion is 10.

VER_PLATFORM_WIN32_NT Win32 on Windows NT.

szCSDVersion
Windows NT: Contains a null-terminated string, such as "Service Pack
3", that indicates the latest Service Pack installed on the system. If
no Service Pack has been installed, the string is empty.
Windows 95: Contains a null-terminated string that provides arbitrary
additional information about the operating system.

QuickInfo
  Windows NT: Requires version 3.5 or later.
  Windows: Requires Windows 95 or later.
  Windows CE: Requires version 1.0 or later.
  Header: Declared in winbase.h.
  Unicode: Defined as Unicode and ANSI structures.

See Also
System Information Overview, System Information Structures,
GetVersionEx

-Mike

To reach me by email, either use the link in my Web site at
www.geary.com, or delete "bitbucket." from my email address.
My apologies for the inconvenience provoked by our friends
the spammers.  <sigh>



Sun, 08 Oct 2000 03:00:00 GMT  
 GetVersionEX call fails from VB5

The build contains 2 long values that need to be extracted ...

  Dim r As Long
  OSV.OSVSize = Len(OSV)
  r = GetVersionEx(OSV)

  Text1(7) = OSV.dwVerMajor
  Text1(8) = OSV.VerMinor
  Text1(9) = LoWord(OSV.BuildNumber)
  Text1(10) = HiWord(OSV.BuildNumber)

 'Computers's System Info
  Text1(11) = OSV.dwVerMajor & "." & OSV.VerMinor & "." & LoWord(OSV.BuildNumber)

Function LoWord(dw As Long) As Integer

   If dw And &H8000& Then
     LoWord = &H8000 Or (dw And &H7FFF&)
     Else: LoWord = dw And &HFFFF&
   End If

End Function

--
Randy Birch, MVP Visual Basic
VBnet, The Visual Basic Developers Resource Centre
http://home.sprynet.com/sprynet/rasanen/vbnet/default.htm

Common Controls Replacement Project
http://www.mvps.org/ccrp

:>When attempting to run the sample code below, VB responds with:
:>        Compile Error:
:>
:>        User-defined type may not be passed ByVal
:>
:>I have scoured the MSDN CD's to no avail...  How do I call this (and
:>other) Win API's from Visual Basic?
:
:Yes, I know about that too... I crashed into the very same error the first
:time. Even removing ByVal doesn't work. You need to explicitly replace it
:with ByRef. This is a hint: UDT's in Win32 API functions are *almost always*
:passed ByRef. What you might want to do is to either get a copy of the Win32
:API help file & port it manually (not recommended) or find someone's port of
:it.
:
:
:PS. Can anyone help me with this code, it is not giving the expected
:results. I want the version string to say "Win98 4.10.1650" but instead I
:get some *REALLY* long number (see code/picture for details).
:
:
:PPS. Picture available at http://web.singnet.com.sg/~apesena/gveprob.gif
:
:== Begin code ==
:Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (ByRef
:lpVersionInformation As OSVERSIONINFO) As Long
:
:Dim rc as long
:Dim lpVersionInfo as OSVERSIONINFO
:lpVersionInfo.dwOSVersionSize=Len(lpVersionInfo)
:rc=GetVersionEx(lpVersionInfo)
:lblPlatform.Caption = lpVersionInfo.dwMajorVersion & "." &
:lpVersionInfo.dwMinorVersion & "." & lpVersionInfo.dwBuildNumber
:
:
:The version no. as you would see is 4.10.[some long number]. The 4.10 part
:is understandable as I'm running Win98 but I only want to display the
:version of Windows the person is running. How can I do this???
:
:== end code ==
:
:OK, I seem to have gotten a workaround by using  szCSDVersion instead of
:dwBuildNumber. But it may change in the future...
:--
:My e-mail address may have 2 bugs in it; deBUG to reply.
:
:Damit Senanayake
:Damit's Home; http://web.singnet.com.sg/~apesena/
:ICQ UIN: 6930718
:
:"It's one small step for man, one giant leap for mankind." -- Neil Armstrong
:
:
:
:
:
:
:



Sun, 08 Oct 2000 03:00:00 GMT  
 GetVersionEX call fails from VB5

[snip]

Quote:
>Oh, not to be too nitpicky <g>, but from the point of view of a
>Windows C/C++ programmer, the variable name "lpVersionInfo" is a bit
>confusing. Traditionally, the "lp" prefix is used to indicate that the
>variable is a pointer to the data, not the data itself. So a C/C++
>Windows  programmer coding in VB would probably name the variable like
>this:

OK, but I thought that VB passed a pointer to the structure, since I'm
passing it in as ByRef in the declaration.

[more info]

Quote:
>dwBuildNumber
>Windows NT: Identifies the build number of the operating system.
>Windows 95: Identifies the build number of the operating system in the
>low-order word. The high-order word contains the major and minor
>version numbers.

OK, that explains it but how do I port the (LOWORD) and (HIWORD) macros to
VB?

Quote:
>For Windows 95, dwMinorVersion is 0.

>For Windows 98, dwMinorVersion is 10.

OK, another one for my detection routine...

Quote:
>szCSDVersion
>Windows NT: Contains a null-terminated string, such as "Service Pack
>3", that indicates the latest Service Pack installed on the system. If
>no Service Pack has been installed, the string is empty.
>Windows 95: Contains a null-terminated string that provides arbitrary
>additional information about the operating system.

In Win98 1650 this string just says "Beta 3"
[more info]

--
My e-mail address may have 2 bugs in it; deBUG to reply.

Damit Senanayake
Damit's Home; http://web.singnet.com.sg/~apesena/
ICQ UIN: 6930718

"It's one small step for man, one giant leap for mankind." -- Neil Armstrong



Mon, 09 Oct 2000 03:00:00 GMT  
 GetVersionEX call fails from VB5

Quote:

>The build contains 2 long values that need to be extracted ...

>  Text1(7) = OSV.dwVerMajor
>  Text1(8) = OSV.VerMinor
>  Text1(9) = LoWord(OSV.BuildNumber)
>  Text1(10) = HiWord(OSV.BuildNumber)

>Function LoWord(dw As Long) As Integer

>   If dw And &H8000& Then
>     LoWord = &H8000 Or (dw And &H7FFF&)
>     Else: LoWord = dw And &HFFFF&
>   End If

>End Function

[snip]
OK, but where's the Hiword function (or rather: how do you code it)?
--
My e-mail address may have 2 bugs in it; deBUG to reply.

Damit Senanayake

SBN Members' Free Home Pages: http://freesbn.dyn.ml.org/
Damit's Home; http://web.singnet.com.sg/~apesena/
ICQ UIN: 6930718
SiteBuilder Network Level 2 Member
MSDN Online Member

"It's one small step for man, one giant leap for mankind." -- Neil Armstrong



Mon, 09 Oct 2000 03:00:00 GMT  
 GetVersionEX call fails from VB5

You can try these. Keep the shift functions around for other times you need
them in VB code.

'-------------------------------------------------------
'   LoWord
'
'   Returns the low word of a DWORD
'-------------------------------------------------------
Private Function LoWord(lngValue As Long) As Long
    LoWord = (lngValue And 65535)
End Function

'-------------------------------------------------------
'   HiWord
'
'   Returns the high word of a DWORD
'-------------------------------------------------------
Private Function HiWord(ByVal lngValue As Long) As Long
    HiWord = RightShift(lngValue, 16)
End Function

'----------------------------------------------------------------------
'   LeftShift
'
'   Since VB does not have a left shift operator.
'   LeftShift(8,2)  is equivalent to 8 << 2
'----------------------------------------------------------------------
Private Function LeftShift(ByVal lNum As Long, ByVal lShift As Long) As Long
    LeftShift = lNum * (2 ^ lShift)
End Function

'----------------------------------------------------------------------
'   RightShift
'
'   Since VB does not have a right shift operator.
'   RightShift(8,2)  is equivalent to 8 >> 2
'----------------------------------------------------------------------
Private Function RightShift(ByVal lNum As Long, ByVal lShift As Long) As
Long
    RightShift = lNum / (2 ^ lShift)
End Function


Quote:

>[snip]
>>Oh, not to be too nitpicky <g>, but from the point of view of a
>>Windows C/C++ programmer, the variable name "lpVersionInfo" is a bit
>>confusing. Traditionally, the "lp" prefix is used to indicate that the
>>variable is a pointer to the data, not the data itself. So a C/C++
>>Windows  programmer coding in VB would probably name the variable like
>>this:
>OK, but I thought that VB passed a pointer to the structure, since I'm
>passing it in as ByRef in the declaration.

>[more info]

>>dwBuildNumber
>>Windows NT: Identifies the build number of the operating system.
>>Windows 95: Identifies the build number of the operating system in the
>>low-order word. The high-order word contains the major and minor
>>version numbers.
>OK, that explains it but how do I port the (LOWORD) and (HIWORD) macros to
>VB?

>>For Windows 95, dwMinorVersion is 0.

>>For Windows 98, dwMinorVersion is 10.
>OK, another one for my detection routine...

>>szCSDVersion
>>Windows NT: Contains a null-terminated string, such as "Service Pack
>>3", that indicates the latest Service Pack installed on the system. If
>>no Service Pack has been installed, the string is empty.
>>Windows 95: Contains a null-terminated string that provides arbitrary
>>additional information about the operating system.
>In Win98 1650 this string just says "Beta 3"
>[more info]

>--
>My e-mail address may have 2 bugs in it; deBUG to reply.

>Damit Senanayake
>Damit's Home; http://web.singnet.com.sg/~apesena/
>ICQ UIN: 6930718

>"It's one small step for man, one giant leap for mankind." -- Neil
Armstrong



Mon, 09 Oct 2000 03:00:00 GMT  
 GetVersionEX call fails from VB5

Quote:

>[snip]
>>Oh, not to be too nitpicky <g>, but from the point of view of a
>>Windows C/C++ programmer, the variable name "lpVersionInfo" is a bit
>>confusing. Traditionally, the "lp" prefix is used to indicate that the
>>variable is a pointer to the data, not the data itself. So a C/C++
>>Windows  programmer coding in VB would probably name the variable like
>>this:

>>Dim VersionInfo as OSVERSIONINFO

>>i.e. without the "lp" prefix. Or maybe just:

>>Dim vi as OSVERSIONINFO

>>to save some typing. Anything but that "lp" prefix... <g>

>OK, but I thought that VB passed a pointer to the structure, since I'm
>passing it in as ByRef in the declaration.

That's right. But the variable name is talking about the variable
itself, not how it may happen to be passed to some function. For
example, in C this function call would look something like this:

   OSVERSIONINFO vi;
   vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
   GetVersionEx( &vi );

Here, the "&" character says to pass a pointer to vi into the
function. But I didn't name "vi" itself with the "lp" prefix, because
"vi" itself is not a pointer. If this is clear as mud, here's another
example of the same function call coded a bit differently:

   OSVERSIONINFO vi;
   OSVERSIONINFO* lpvi;
   lpvi = &vi;
   lpvi->dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
   GetVersionEx( lpvi );

In this example, "vi" is still an OSVERSIONINFO variable, and "lpvi"
is *a pointer to* an OSVERSIONINFO. So I use the "lp" prefix on it,
but not on "vi" itself.

Now after all that, as I mentioned before, how you name your variables
is your own business, so pile as many grains of salt on all my advice
as you wish... <g> But this will give you an idea of how traditional
Windows programmers use those variable naming conventions...

-Mike

To reach me by email, either use the link in my Web site at
www.geary.com, or delete "bitbucket." from my email address.
My apologies for the inconvenience provoked by our friends
the spammers.  <sigh>



Tue, 10 Oct 2000 03:00:00 GMT  
 
 [ 10 post ] 

 Relevant Pages 

1. I am using the GetVersionEx API call

2. PRB: ODBC -- Call failed (VB5 -- ODBC -- Access97)

3. CreateProcess fails if in VC5 DLL and called from VB5 app

4. Calling a COM call back object's method fails if it is in Windows 98

5. 2 PRBS: Calling 16 bit DLL from VB5 and Bad DLL Calling Convention

6. Calling VB5 DLL with another VB5 DLL results in crashes

7. ODBC Call Failed

8. Trapping an ODBC failed call

9. ASP calling Access procedure failed

10. API call failing under NT

11. eval call fails after VC++ 6.0 installation

12. A97-SLQ6.5 ODBC calls failing or terribly slow - newer drivers are worse

 

 
Powered by phpBB® Forum Software