I use the AsyncRead methode (UserControl.AsyncRead Path, FileType, Key, DownloadType) in VB6 to download a file from internet. Everything works fine except am AsyncReadProgress when the internet goes down while a file is downloading.
The AsyncReadProgress event works the whole time because I can get the AsyncProp.StatusCode. But when the network goes down the AsucnReadProgress event won't fire.
Public Sub Download(URL As String, sDestination As String, Optional sId As String = "Id")
colDest.Add sDestination, sId
UserControl.AsyncRead URL, vbAsyncTypeFile, sId, vbAsyncReadForceUpdate
End Sub
Private Sub UserControl_AsyncReadProgress(AsyncProp As AsyncProperty)
RaiseEvent Progress(AsyncProp.BytesRead, AsyncProp.BytesMax, AsyncProp.PropertyName)
End Sub
Private Sub UserControl_AsyncReadComplete(AsyncProp As AsyncProperty)
On Error Resume Next
If AsyncProp.BytesRead > 0 And AsyncProp.BytesRead = AsyncProp.BytesMax Then
Name AsyncProp.value As colDest.Item(AsyncProp.PropertyName)
End If
colDest.Remove AsyncProp.PropertyName
RaiseEvent Completed(AsyncProp.BytesRead, AsyncProp.BytesMax, AsyncProp.PropertyName)
End Sub
Related
Thanks for reading.
I have built a VB6 DLL (VB_InterFace just for a name) that talks to a C# DLL (C#_Driver just for a name) that talks to a Bluetooth Device.
The Demo VB6 test app (VB_Demo just for a name) I created as stage one works fine, does what it is supposed to. It calls the VB_Interface and Opens and Closes the BTDevice. Additional functions also work fine.
However on placing the operational code from VB_Interface into another DLL that is the live operations DLL, Open works fine, but Close is throwing an error. "Variable not defined" when returning from the C#_Driver.
I just can't see why, the code is the same, the process is only marginally different. By this I mean ;
In the VB_Demo I have two buttons "Open" "Close" and when I click on these I get the feedback that I expect from the BTDevice.
Private Sub btnOpenPort_Click()
'MsgBox steps(0)
ReDim steps(5)
Dim rc As HF4000_ResultCodes
'rc = driver.OpenSerial(cmbPorts.Text)
If driver.OpenSerial(cmbPorts.Text) = True Then
Private Sub btnClosePort_Click()
Dim rc As HF4000_ResultCodes
If driver.CloseSerial("COM4") = True Then
However in the live DLL it just executes the same functions internally without being initiated by a button click.
' See IScanDevice documentation.
' #see IScanDevice#OpenDevice
Private Function IScanDevice_OpenDevice() As Scanning.Scan_ResultCodes
(truncated slightly)
50 If driver.OpenSerial("COM4") = True Then
rc = READY
MsgBox "Connected to the device successfully."
' See IScanDevice documentation.
' #see IScanDevice#CloseDevice
Private Function IScanDevice_CloseDevice() As Scanning.Scan_ResultCodes
(truncated slightly)
50 If driver.CloseSerial("COM4") = True Then
60 rc = READY
70 IScanDevice_CloseDevice = Scan_Success
clsDriver.cls
Public Event OnStateChanged(newState As String)
Public Event OnDataUpdated()
Dim WithEvents CSharpInteropServiceEvents As CSharpInteropService.LibraryInvoke
Dim load As New LibraryInvoke
Private Sub Class_Initialize()
Set CSharpInteropServiceEvents = load
End Sub
Private Sub CSharpInteropServiceEvents_MessageEvent(ByVal newState As String)
If newState = "OpenForm1" Then
' FormDummy2.Show ' Not required
End If
If State <> newState Then
State = newState
RaiseEvent OnStateChanged(State)
GetDriverData
End If
End Sub
Private Function BluetoothTestInvoke(load, functionName, param)
BluetoothTestInvoke = load.GenericInvoke("BluetoothTest.dll", "BluetoothTest.Class1", functionName, param)
End Function
Function OpenSerial(portNumber) ' "COM4"
Dim param(0) As Variant
Dim retorno As Variant
param(0) = portNumber
retorno = BluetoothTestInvoke(load, "OpenSerial", param)
OpenSerial = retorno(0) <<<<<<< Works fine returns TRUE
End Function
Function CloseSerial(portNumber) ' "COM4"
Dim param(0) As Variant
Dim retorno As Variant
param(0) = portNumber
retorno = BluetoothTestInvoke(load, "CloseSerial", param)
CloseSerial = retorno(0) <<<<<<<<< "Error Subscript Out of Range"
End Function
What I have discovered is this - and I guess this is the reason why the Close is not working. The question is why is this situation occurring ...
When driver.OpenSerial executes, it hits > Function OpenSerial
Within Function OpenSerial it executes BluetoothTestInvoke where "load" is "CSharpInteropService.LibraryInvoke"
From there it moves to - Sub CSharpInteropServiceEvents_MessageEvent
.. and everything is fine.
However when I then execute driver.CloseSerial after that, it hits > Function CloseSerial
Within Function OpenSerial it executes BluetoothTestInvoke where "load" is "CSharpInteropService.LibraryInvoke"
Now here it "should" move to - Sub CSharpInteropServiceEvents_MessageEvent
However No, it just drops to the next line which is CloseSerial = retorno(0)
and this is where I get the "Subscript out of range" error for retorno(0)
For some reason in the CloseSerial it is not invoking "load"
BluetoothTestInvoke(load, "CloseSerial", param)
Thoughts and suggestions much appreciated.
UPDATE
Quite right, one should never assume anything.
On the tips I started digging deeper into the C# Library. It turns out the "param" value that is the Bluetooth port is passed into the CloseSerial call, and from there is is passed around within the external C# library dll. At one stage it is reset so the port number that should be handled is lost, thus it doesn't close but specifically the "expected" data was not returned to the calling app.
param(0) = portNumber
retorno = BluetoothTestInvoke(load, "CloseSerial", param) << param was being reset in the external library.
I'm trying to launch a page with Browsers.Item(btChrome).Run(datavalue) and check if the page contains a specific word string that I'm looking for. And I got an error of Object required: 'Browsers'. I'm confused because I was following the tutorial of https://support.smartbear.com/testcomplete/docs/app-testing/web/general/examples/checking-specific-text.html. Can someone please point out where my code goes wrong?
Sub Test(datavalue)
Dim browser, page, str, Obj
Browsers.Item(btChrome).Run(datavalue) 'datavalue is an url
Set browser = Sys.Browser("*")
Set page = browser.Page("*")
str = "*Dashboard*"
If browser.ObjectIdentifier = "chrome" Then
Call aqObject.CheckProperty(body, "innerText", cmpContains, str, False)
Else
Call aqObject.CheckProperty(body, "textContent", cmpContains, str, False)
End If
End Sub
I have attempted to use an autoit object WinGetPos to handle a popup within a thread in a vb project, I would like WinGetPos function to return the x and y coordiantes of the specified popup and have used the below code, having first imported the AutoItX3.PowerShell.dll reference to my project. I am unable to generate any array could anyone suggest where I might be going wrong?
Imports AutoIt
Imports AutoItX3Lib
Private Declare Auto Function WinGetPos Lib "AutoItX3.PowerShell.dll" (ByVal mywindowtitle As String) As Array
Public Sub Main()
Dim PopUpThread As Thread = New Thread(AddressOf PopUpHandler)
With PopUpThread 'thread is looking for PopUp and press OK
.IsBackground = True
.Start()
End With
End Sub
Private Sub PopUpHandler()
Dim Ret As Integer
Dim myarray As Array
Do
Ret = FindWindow(vbNullString, "Choose File to Upload")
If Ret <> 0 Then
myarray = WinGetPos("Choose File to Upload")
MsgBox(UBound(myarray))
End If
Loop
End Sub
AutoItX is a well known and documented Programm. So why don't just look into the help file. There you will find how to use and WinGetPosX, WinGetPosY, WinGetPosHeight and WinGetPosWidth, but no WinGetPos. That may be the reason for your problem.
Is it possible in VBScript to determine the name of the function currently executing?
In .NET, you could do:
MethodBase method = MethodBase.GetCurrentMethod();
Console.WriteLine(method.Name);
In the past, I build a callstack viewer to see the performance of each function that is called. This needs one extra line of VBS code per function/sub and some overhead during runtime of course because of the extra code.
bottom - up:
Function DoSomething(a, b, c)
dim registerFunctionObj : Set registerFunctionObj = [new RegisterFunction]("DoSomething")
' other code
End Function
Whenever the function is called, it creates a new instance of the RegisterFunction object. When the function exits, the registerFunctionObj variable goes out of scope automatically, calling the Class_Terminate sub of the instance.
[new RegisterFunction] is just a function that return a registerFunction instance:
Function [new RegisterFunction](funcName)
Set [new RegisterFunction] = new cls_RegisterFunction
[new RegisterFunction].FunctionName = funcName
Set [new RegisterFunction].CallStackViewer = CallStackViewer
End function
Class cls_RegisterFunction
Private functionName_, startTime_, callStackViewer_, endTime_
Private Sub Class_Initialize
startTime_ = now
callStackViewer_.LogInitialize me
End Sub
Public Property Let FunctionName(fName)
functionName_ = fName
End Property
Public Property Set CallStackViewer(byRef csv)
Set callStackViewer_ = csv
End Property
Private Sub Class_Terminate
endTime_ = now
callStackViewer_.LogTerminate me
End Sub
End Class
The CallStackViewer instance is a singleton instance of the a CallStackViewer class, but you can make it a part of your project, so you retrieve it through you global project class:
Private PRIV_callStackViewer
Public Function CallStackViewer()
If not IsObject(PRIV_callStackViewer) Then
Set PRIV_callStackViewer = new cls_CallStackViewer
End If
Set CallStackViewer = PRIV_callStackViewer
End Function
Class cls_CallStackViewer
Public Sub Class_Initialize
' Here you can retrieve all function libraries (as text file) extract the
' function name, the file they are in and the linenumber
' Put them in a dictionary or a custom object
End Sub
Public Sub LogInitialize(byref registerFunction)
' Here you can push the function on a stack (use a standard dotnet list>stack for it),
' log the starttime to a log object or handle custom breakpoints
End Sub
Public Sub LogTerminate(byref registerFunction)
' Here you can pop the function from a stack, log the endtime to a log
' object or handle custom breakpoints
End Sub
End Class
Disclaimer: The code in here is pure demo code created on the fly. It lacks functionality and is only here to explain the concept. It could contain errors and is not complete.
The only thing you need is one line of code per function and your own imagination to expand it.
No, but you can easily implement it
dim module_name
sub sub1
module_name = "sub1"
wscript.echo "i'm " & module_name
'do something
end sub
function function1
module_name = "function1"
wscript.echo "i'm " & module_name
function1 = "something"
end function
In case of recursion you could also remember the level you'r in so that you can get out if getting too deep.
I know you can do it with an WMI event or overriding WndProc and looking for the right messages, but i was wondering if there wasn't something hidden in the net framework that makes this task easyer.
This free DriveDetector class provides this functionality (as least for USB drives, which is what I used it for). It uses the WndProc approach you describe.
I'm not aware of anything similar that is part of the standard .NET libraries.
In the following code, moDiskDetector will raise an EventArrived event when a new drive is detected.
To detect removal of a drive use "__InstanceDeletionEvent".
Private WithEvents moDiskAddWatcher As ManagementEventWatcher
Private Sub StartWatcher()
If moDiskAddWatcher Is Nothing Then
moDiskAddWatcher = CreateWatcher("__InstanceCreationEvent", "(TargetInstance ISA 'Win32_DiskDrive')")
End If
moDiskAddWatcher.Start()
End Sub
Private Sub StopWatcher()
If moDiskAddWatcher IsNot Nothing Then
moDiskAddWatcher.Stop()
moDiskAddWatcher.Dispose()
End If
End Sub
Private Function CreateWatcher(ByVal sClassName As String, ByVal sCondition As String) As ManagementEventWatcher
Dim oQuery As New WqlEventQuery()
oQuery.EventClassName = sClassName
oQuery.WithinInterval = New TimeSpan(0, 0, 5)
oQuery.Condition = sCondition
Return New ManagementEventWatcher(oQuery)
End Function