Overflow error on VB6 program running on Win XP - vb6

I'm getting a error message in a VB6 .exe file running on Windows XP.
I compile and "make it" on Windows 7/8, but always get an Overflow error message when it executes this two lines on XP:
sUrl = "C:\Arquivos de Programas\Internet Explorer\IEXPLORE.EXE http://example.com/WebForms/send.aspx?id=" & intCodID & "&type=500&usr=" & intCodUser
openWeb = Shell(sUrl, vbMaximizedFocus)
sUrl is a String and OpenWeb is actually a Integer, but I already declared it as Double and as nothing (just Dim OpenWeb) and still get the overflow error.
UPDATE
Didn't managed to find out what was happening there, but another solution for calling IE:
Dim IE
sUrl = "http://www.google.com/"
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
IE.Navigate sUrl

While the VB6 documentation says Shell() returns a Variant Double... that appears to be obsolete information left over from manuals for earler versions of VB. Instead if you check the typelib info (i.e. look in the IDE's Object Browser) it actually returns a Double type result value.
As far as I can tell Shell() is a wrapper around a call to the WinExec() function.
The returned values are:
0 The system is out of memory or resources.
ERROR_BAD_FORMAT = 11 The .exe file is invalid.
ERROR_FILE_NOT_FOUND = 2 The specified file was not found.
ERROR_PATH_NOT_FOUND = 3 The specified path was not found.
or a Process ID
Also contrary to the documentation, Shell() turns those error values into exceptions ("File not found", "Invalid procedure call or argument," etc.). So if the call succeeds you always get back a PID value.
In all cases this is a DWORD. So it always fits in a Double without the possibility of an overflow. If you are seeing an overflow there is something else going wrong in your code.
Sadly a Double isn't particularly useful here, though it can at least hold the entire range of values. But you'd normally want to carefully convert it to a Long value:
Option Explicit
Function DDoubleToDLong(ByVal DDouble As Double) As Long
'Some functions like the intrinsic Shell() return a Double
'to get around the lack of a UI4 type (DWORD, i.e. unsigned
'Long) in VB. Of course this isn't clean to pass to API
'calls, making it sort of worthless so we need to do a type
'conversion such as this:
If DDouble > 2147483647# Then
DDoubleToDLong = CLng(DDouble - 2147483648#) Or &H80000000
Else
DDoubleToDLong = CLng(DDouble)
End If
End Function
Private Sub Form_Load()
Dim DD As Double
Dim DL As Long
AutoRedraw = True
Font.Name = "Courier New" 'Or other handy monospaced font.
Font.Size = 12#
DD = 0#: DL = DDoubleToDLong(DD): Print DD, DL, Hex$(DL)
DD = 1#: DL = DDoubleToDLong(DD): Print DD, DL, Hex$(DL)
DD = 2147483647#: DL = DDoubleToDLong(DD): Print DD, DL, Hex$(DL)
DD = 2147483648#: DL = DDoubleToDLong(DD): Print DD, DL, Hex$(DL)
DD = 4294967295#: DL = DDoubleToDLong(DD): Print DD, DL, Hex$(DL)
End Sub
Integer is worthless since overflows will be common. Long without the conversion could cause overflows now and then. String is just silly.
You also need to quote the values for the EXE and its arguments property, as in:
Option Explicit
Function DDoubleToDLong(ByVal DDouble As Double) As Long
If DDouble > 2147483647# Then
DDoubleToDLong = CLng(DDouble - 2147483648#) Or &H80000000
Else
DDoubleToDLong = CLng(DDouble)
End If
End Function
Private Sub Form_Load()
Dim sUrl As String
Dim PID As Long
sUrl = """C:\Arquivos de Programas\Internet Explorer\IEXPLORE.EXE"" " _
& """http://example.com/WebForms/send.aspx?id=" _
& intCodID _
& "&type=500&usr=" _
& intCodUser _
& """"
PID = DDoubleToDLong(Shell(sUrl, vbMaximizedFocus))
End Sub
Even this isn't quite "right" since exception handling should be added. And both intCodID and intCodUser may require "cleansing" (UrlEncoding) depending on what types they are and what values they really have. These might be Integers based on the names, with you relying on implicit String coercion? If so they might be Ok.
BTW, as we see above special folder names get localized. For that matter the system drive might not even be C:\ at all! So such paths should never be hard-coded but instead be built up based on values returned from calls to Shell32 to look up the special folder.

An integer can only be a whole number. No decimals.
You say it's declared as an integer therefore you cannot assign 1. anything, and you certainly can't assign anything like that to a number variable as it's not a valid number anyway as it has two decimal points.
You need to declare it as string.

Related

why when pass arguments on a sub vb6 i retrieve error?

i wrote this code:
Sub Insert_Pic_From_File2(PicPath As String, ByVal row As Integer, ByVal col As Integer)
Dim Pic As Picture, Sh As Shape, Rng As Range
Set Rng = Range.Cells(row, col)
Set Rng = Rng.MergeArea
With Rng
Set Sh = ActiveSheet.Shapes.AddPicture(Filename:=PicPath, linkToFile:=msoFalse, SaveWithDocument:=msoTrue, Left:=.Left, Top:=.Top, Width:=.Width, Height:=.Height)
Sh.LockAspectRatio = msoFalse
End With
Set Sh = Nothing
Set Rng = Nothing
End Sub
and I call it from this line:
Insert_Pic_From_File2 ("D:\Area Open\ok.png", y, col_result)
both y and col_result are integer.
When I press enter the program give this error (in italian)
errore di compilazione:
Previsto: =
i think in english:
compilation error:
needed: =
Why this?
if i delete the arguments y and col_result seems no problem, but without arguments.
Thanks so much.
Don't use brackets round the parameters! They're only used if you use the redundant 'Call' statement or for Functions where a value is returned.
Insert_Pic_From_File2 "D:\Area Open\ok.png", y, col_result
should be fine

Why is the result of VarPtr(ByVal str) the same as StrPtr(str) ? (VB6)

In VB6 VarPtr should return the address of the variable, in this case the address of the variable str which is allocated on stack, and holds a pointer to a string in memory. StrPtr (or StrPtr) should return the address of the allocated string in the memory. ByVal should just create a copy, but in this case, it works strangely:
Dim str As String
str = "asd"
Debug.Print VarPtr(str)
Debug.Print VarPtr(ByVal str)
Debug.Print StrPtr(str)
The result is:
1636452
110882980
110882980
Why is the result of VarPtr(ByVal str) the same as StrPtr(str) ?
Strings passed ByVal pass the address of the first character of the containing C string in the BStr. StrPtr does the same.
There are two reasons that spring to mind for doing this. Passing Unicode to API calls and string building.
Passing Unicode to API calls
You could use StrPtr on a string rather than a byte array when sending Unicode strings to API functions.
Dim ByteArr() as Byte
Var1="My Text"
ByteArr = Var1
APICall(ByteArr(0))
APICall(StrPtr(Var1))
Should both pass a Unicode string to an API functions. Unicode strings are converted to ANSI strings when using the declare statement as Win 95 didn't do unicode.
String Building
On the other hand if you are string building, then that is built in to VBA using the Left, Right, and Mid statements, not functions (they are overloaded).
Sub Main()
Dim Var As String
Var = "gggggggggggg"
MsgBox StrPtr(Var)
Mid(Var, 1, 2) = "xx"
MsgBox StrPtr(Var) & " - " & Var
End Sub
ByVal Versus ByRef
Some authors like to say that the ByVal keyword is overloaded for
strings, meaning that it takes on a different meaning when applied to
strings than when applied to other variables. Frankly, I don't see it.
Writing:
ByVal str As String
tells VB to pass the contents of the BSTR (actually the ABSTR), which is the pointer to the character array. Thus, ByVal is acting
normally--it just happens that the content of the BSTR is a pointer to
another object, so this simulates a pass by reference. Similarly:
ByRef str As String
passes the address of the BSTR, as expected.
Win32 API Programming with Visual Basic, Chapter 6 Strings, O'Reilly, from MSDN Library October 2001
StrPtr
Strings in Visual Basic are stored as BSTR's. If you use the VarPtr on
a variable of type String, you will get the address of the BSTR, which
is a pointer to a pointer of the string. To get the address of the
string buffer itself, you need to use the StrPtr function. This
function returns the address of the first character of the string.
Take into account that Strings are stored as UNICODE in Visual Basic.
To get the address of the first character of a String, pass the String
variable to the StrPtr function.
Example:
Dim lngCharAddress as Long
Dim strMyVariable as String
strMyVariable = "Some String"
lngCharAddress = StrPtr(strMyVariable)
You can use this function when you need to pass a pointer to a
UNIOCODE string to an API call.
HOWTO: Get the Address of Variables in Visual Basic Q199824 Microsoft Knowledge Base, MSDN October 2001.
VarPtr is not part of the VBA/VB6 language, therefore companies that implement VBA (like Corel) may not implement it in their VBA. The VBA spec is here https://msdn.microsoft.com/en-us/library/dd361851.aspx

Advise on this . My code has some blocker.i am getting the error 'object required'

I am using the functions below.In the first one i have parsed the node of xml and its value using MSXML. similar func fr other xml.i want to use two nodevalues and highlight it.i tried something.but i am getting error in the line highlighted(**) as 'Object Required'.your quick reply will help me more.
Public Sub DisplayNode1(ByRef Nodes1 As MSXML2.IXMLDOMNodeList, _
ByVal Indent1 As Integer)
some lines
RichTextBox2.Text = Space$(Indent) & xNode1.ParentNode.nodeName & _
":" & xNode1.NodeValue
difference
some lines
Public Sub difference()
Dim a As IXMLDOMText
Dim b As IXMLDOMText
a.NodeValue = xNode.innertext 'i get erroe in line
b.NodeValue = xNode1.innertext
If StrComp(a, b) > 0 Then
a = vbRed
b = vbRed
End If
please help me soon.
There is a lot that is potentially wrong with this.
xnode isn't declared anywhere in your code sample
Neither a, b, or xnode are explicitly set anywhere in your code sample
Unless xnode is a form/module/global level variable then it will be out of scope in the Difference procedure
It's not shown but I'm guessing that you don't have Option Explicit set in your code or by default
You'll need to address these points first before you can get anywhere with this code.

VB6 - converting string to double using specific culture?

I am a long time C# developer and have had to look at some VB6 code lately. After some digging, we found out that, somewhere, somehow, we are storing a number as a string. Now we are reading it back and our code is not handling culture differences very well. Here is an example:
Dim text as String
Dim myVal as Double
Set text = "1,123456"
'This sets the value of myVal to 1123456 on our system - incorrect
myVal = text
Set text = "1.123456"
'This sets the value of myVal to 1.123456 on our system - correct
myVal = text
Keeping in mind that this is VB6 and NOT VB.NET, are there any built-in methods, functions, whatever, that can convert a string to a double using a particular culture?
Or at the very least, hinting to the conversion that we may be dealing with a different format?
We are still digging how the value gets written and see if we can reverse engineer the process to give us a consistent result. However, our customer(s) already has(have) data in one format or the other (or both, we are checking...), so a proper conversion algorithm or implementation would be a better answer at this point.
I've used this quick and dirty function in the past to get a double from a text. Here in Argentina, people sometimes use the point and sometimes the comma to separate decimal values, so this function is ready to accept both formats. If only one punctuation is present, it's assumed that it's the decimal separator.
function ConvertDBL( texto )
dim retval, SepDecimal, SepMiles
If texto = "" then texto = "0"
retval = replace(trim(texto), " ", "")
If cdbl("3,24") = 324 then
SepDecimal = "."
SepMiles = ","
else
SepDecimal = ","
SepMiles = "."
end if
If InStr( Retval, SepDecimal ) > 0 then
If InStr( Retval, SepMiles ) > 0 then
If InStr( Retval, SepDecimal ) > InStr( Retval, SepMiles ) then
Retval = replace( Retval, SepMiles, "" )
else
Retval = replace( Retval, SepDecimal, "" )
Retval = replace( Retval, SepMiles, SepDecimal )
end if
end if
else
Retval = replace( Retval, SepMiles, SepDecimal )
end if
ConvertDbl = cdbl( retval )
end function
You cannot choose an arbitrary culture by passing a culture object like you can in .Net. You can choose:
Functions which always use the current regional settings. CStr, Format, CDbl etc. Implicit conversions (like the ones in your question) also use the current regional settings.
Functions which always use USA regional settings (similar to the .Net invariant culture). Str, Val
Usually the current regional settings are taken from Control Panel. There are rumours that you can call SetThreadLocale to change the regional settings from code at runtime - never tried it myself.
In Visual Basic tested works very fast and efficient.
Step 1: Conversion from a string to a value representation.
Step 2: Conversion from a value representation to a double integer value.
Dim Str as String
Dim mValue as double
str = "100,10"
mValue = CDbl(Val(str))

VB6 Can IsNumeric be wrong?

Is it possible to test a string with IsNumeric() and for it to return true, but when you cast that same string to an integer using CInt() and assign it to a variable of type integer that it will give a type mismatch error?
I ask because I was getting a type mismatch error, so I used IsNumeric() to check the string was numeric before trying to cast it, but I still get the error.
I am tearing my hair out with this.
Here is the code in question.
iGlobalMaxAlternatives = CInt(strMaxAlternatives) is where the error is occuring.
Dim strMaxAlternatives As String
Dim iGlobalMaxAlternatives As Integer
iGlobalMaxAlternatives = 0
bSurchargeIncInFare = True
strMaxAlternatives = ReadStringKeyFromRegistry("Software\TL\Connection Strings\" & sConn & "\HH", "MaxAlt")
If IsNumeric(strMaxAlternatives) And strMaxAlternatives <> "" Then
iGlobalMaxAlternatives = CInt(strMaxAlternatives)
End If
You may have an overflow due the maximum integer size; the currency type actually does very well for large numbers (but beware of any regional issues). See edits below for Int64 discussion.
According to MSDN documentation on IsNumeric:
IsNumeric returns True if the data
type of Expression is Boolean, Byte,
Decimal, Double, Integer, Long,
SByte, Short, Single, UInteger,
ULong, or UShort, or an Object that
contains one of those numeric types.
It also returns True if Expression is
a Char or String that can be
successfully converted to a number.
IsNumeric returns False if Expression
is of data type Date or of data type
Object and it does not contain a
numeric type. IsNumeric returns False
if Expression is a Char or String
that cannot be converted to a number.
Since you are getting a Type Mismatch, perhaps a Double is interfering with the conversion. The IsNumeric does not guarantee it is an Integer, just that it matches one of the numeric possibilities. If the number is a double, perhaps regional settings (comma versus period and so on) are causing the exception.
You might try converting it to a double and then to an integer.
' Using a couple of steps
Dim iValue As Integer
Dim dValue As Double
dValue = CDbl(SourceValue)
iValue = CInt(iValue)
' Or in one step (might make debugging harder)
iValue = CInt(CDbl(SourceValue))
EDIT: After your clarification, it appears you are getting an overflow conversion. First try using a Long and CLng() instead of CInt(). There is still a chance the entry is Int64 though, which is more difficult using VB6.
I have used the following code for the LARGE_INTEGER and Integer8 types (both Int64), but it may not work for your situation:
testValue = CCur((inputValue.HighPart * 2 ^ 32) + _
inputValue.LowPart) / CCur(-864000000000)
This example was from an LDAP password expiration example, but like I said it may or may not work in your scenario. If you don't have the LARGE_INTEGER type, it looks like:
Private Type LARGE_INTEGER
LowPart As Long
HighPart As Long
End Type
Search for LARGE_INTEGER and VB6 for more information.
EDIT: For debugging, it may be useful to temporarily avoid error handling and then turn it back on after passing the troubling lines:
If IsNumeric(strMaxAlternatives) And strMaxAlternatives <> "" Then
On Error Resume Next
iGlobalMaxAlternatives = CInt(strMaxAlternatives)
If Err.Number <> 0 Then
Debug.Print "Conversion Error: " & strMaxAlternatives & _
" - " & Err.Description
EndIf
On Error Goto YourPreviousErrorHandler
End If
Yes, "3.41" would be numeric but not an integer.
VB6 doesn't provide good methods to guarantee CInt won't fail. I've found the simplest way is to just use error-handling.
function TryParse(byval text as string, byref value as integer) as boolean
on error resume next
value = CInt(text)
TryParse = (err.number = 0)
endfunction
Of course your error-handling preferences may vary.
Yes. Try this:
If IsNumeric("65537") Then
Dim i As Integer
i = CInt("65537") 'throws an error on this line!
End If
This one's an overflow, but I think it illustrates the unreliability of IsNumeric() in general (especially for ints - for doubles it's much more reliable).
According to the VB6 documentation, "IsNumeric returns True if the data type of Expression is Boolean, Byte, Decimal, Double, Integer, Long, SByte, Short, Single, UInteger, ULong, or UShort, or an Object that contains one of those numeric types. It also returns True if Expression is a Char or String that can be successfully converted to a number."
Many of those cannot be converted to an Integer. For example "1.5" is numeric but it's not an integer. So, you can convert it to a number, but not necessarily an integer.
The following code works without a Type Mismatch error in Visual BASIC 6
Dim I As Integer
I = CInt("3.41")
The same for this variant
Dim I As Integer
Dim TempS As String
TempS = "3.41"
I = CInt(TempS)
Posting the code in question would help answer your question. Basically there are several function in VB6 that are used to convert strings into number.
CInt and Int convert into number but handle rounding different. Direct assignment works and equivalent to using CInt. Howver I recommend continuing to use CInt to make the operation clear to you and your fellow developers in the future.
CInt works on number with commas like "3,041.41" However VB6 has problem handling region settings so if you are using notation other than standard American English you will get strange results and errors.
Your best bet is to start logging the errors with the actual values it's working with so you can figure out whats going on.
IsNumeric will return true if it can convert the string to a number. Even if there are non-numeric characters in the string. I always loop though the string one character at a time and test each character. If one character fails then I can return an error.
Just found this nugget. If you run the following, script #1 returns TRUE but script #2 & #3 will fail:
SELECT ISNUMERIC('98,0') AS isNum -- Fails
SELECT CONVERT(INT, '98,0') -- Fails
SELECT CONVERT(NUMERIC(11,4), '98,0') -- Fails
Two options...
Change
If IsNumeric(strMaxAlternatives) And strMaxAlternatives <> "" Then
iGlobalMaxAlternatives = CInt(strMaxAlternatives)
End If
To
If IsNumeric(strMaxAlternatives) And strMaxAlternatives <> "" Then
iGlobalMaxAlternatives = CDbl(strMaxAlternatives) ' Cast to double instead'
End If
Or
If IsNumeric(strMaxAlternatives) And strMaxAlternatives <> "" Then
If CDbl(strMaxAlternatives) Mod 1 = 0 Then ' Make sure there\'s no decimal points'
iGlobalMaxAlternatives = CInt(strMaxAlternatives)
End If
End If

Resources