I am having a problem with timeouts in my DownloadFileAsync function. I am using VB.NET. According to multiple sources the "DownloadFileCompleted" event should be raised when the connection to the server while downloading is lost and the error flag should be set. Nothing of this is happening. I am trying this through starting the download and then simply stopping my internet connection through disabling WLAN.
Private Sub DownloadMod_DownloadFileCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.AsyncCompletedEventArgs) Handles DownloadMod.DownloadFileCompleted
MsgBox("Test1")
If e.Error IsNot Nothing Then
MsgBox("Test2")
End If
End Sub
Neither the test1 nor the test2 message box is appearing after loosing connection. I read that the standard timeout is 100 s, so I always waited 2 minutes to make sure, but nothing is happening.
This is how I start the download:
DownloadMod.DownloadFileAsync(New System.Uri("http://linktothefile.com/downloadfile.txt"), System.AppDomain.CurrentDomain.BaseDirectory & "Downloads\downloadfile.txt", Stopwatch.StartNew)
The stopwatch is in there for calculation of the download speed.
Downloadmod is defined like this:
Private WithEvents DownloadMod As New Net.WebClient
I would appreciate if someone could help me with this problem.
Turin
Related
I have an application which has a license key function.
The user gets their license key, then type it into the TextBox where the license key is supposed to go, and if the license key is valid, they get taken to the main form, where all of the features are.
Now, to make my program more secure, I need to be able to check that the user has definitely typed in their license key, and they haven't done something like delete (by decompiling) the license key form so they can gain access to the main form where all of the features are.
Note: My license keys are stored on a server.
How would I check that the user has definitely typed in the license key?
Below is the code.
AddLicense.vb:
Imports SKM.V3
Imports SKM.V3.Models
Imports SKM.V3.Methods
Public Class AddLicense
Private p_oRandom As Random
Private Const INTERVAL_MIN_SEC As Integer = 4
Private Const INTERVAL_MAX_SEC As Integer = 25
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
If BunifuProgressBar1.Value = 50 Then
Label3.Show()
Label2.Hide()
End If
BunifuProgressBar1.Value += 1
If BunifuProgressBar1.Value = BunifuProgressBar1.MaximumValue Then
BunifuProgressBar1.Hide()
Label3.Hide()
Label2.Hide()
Timer1.Stop()
BunifuMaterialTextbox1.Show()
BunifuThinButton21.Show()
Label4.Show()
LinkLabel1.Show()
BunifuThinButton22.Show()
End If
Timer1.Interval = p_oRandom.Next(INTERVAL_MIN_SEC, INTERVAL_MAX_SEC) * 3
End Sub
Private Sub BunifuImageButton1_Click(sender As Object, e As EventArgs) Handles BunifuImageButton1.Click
Me.Close()
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
p_oRandom = New Random
End Sub
Private Sub LinkLabel1_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) Handles LinkLabel1.LinkClicked
Try
Process.Start("https://selly.gg")
Catch ex As Exception
End Try
End Sub
Sub Nolicense()
BunifuThinButton21.Enabled = False
End Sub
Private Sub BunifuThinButton21_Click_1(sender As Object, e As EventArgs) Handles BunifuThinButton21.Click
Dim token = "WyIxMDM2IiwiZ082d2dnS0FmTkRuTXNPcGhlSkllVEx6ckFWMFhhSzlMM3Rvc01xUSJd"
Dim key = BunifuMaterialTextbox1.Text.Replace(" ", "")
Dim license = New LicenseKey() With
{
.ProductId = 3888,
.Key = key
}
If license.Refresh(token, True) Then
' we are able to auto complete missing key info
Me.BunifuThinButton21.Enabled = license.HasFeature(1).IsValid() ' either we have feature1 or not.
MsgBox("License is valid! Thanks for purchasing.")
Me.Hide()
Sploitbase.Show()
If license.HasFeature(4).HasNotExpired().IsValid() Then
Me.Hide()
Sploitbase.Show()
ElseIf license.HasNotFeature(4).IsValid() Then
Else
MsgBox("Your license has expired and cannot be used.")
Nolicense()
End If
license.SaveToFile()
Else
' something went wrong.
MsgBox("Unable to access the license server or the key is wrong.")
End If
Me.Close()
End Sub
Private Sub BunifuThinButton22_Click(sender As Object, e As EventArgs) Handles BunifuThinButton22.Click
End Sub
End Class
Sploitbase.vb - the main form:
Imports SKM.V3
Public Class Sploitbase
Private Sub Sploitbase_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Public Sub NoLicense()
End Sub
Private Sub TabPage1_Click(sender As Object, e As EventArgs)
End Sub
Private Sub LinkLabel1_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs)
Try
Process.Start("https://selly.gg")
Catch ex As Exception
End Try
End Sub
End Class
I believe what you want is to stop users from decompiling your program and removing the license key form entirely...
Unfortunately, it's impossible to stop that, as long as a program can be run on an ordinary computer, it can be decompiled, otherwise, it would be impossible for the processor to process it.
This means, that it would be possible to remove the relevant instructions for that, and C# and VB is easy to decompile - tools like dotPeek get valid source code (it won't be exactly the same as the original, but still readable and runs like the original) just with a click.
Keep in mind that even proper commercial programs made by whole companies have this problem.
So, what could you possibly "do"? Well, I only really have two suggestions... but they won't work too well.
One only makes it harder and the other one requires access to the internet all the time.
Obfuscation
Obfuscation essentially makes the code harder to read after decompiling, however, it won't stop people from deleting the form, it will just make it slightly harder.
I posted it as an option because it will make the code very confusing when recompiling and it might be helpful to "protect" it a bit more. However, just remember this: "It's a weak layer of defence for a weak attacker."
An obfuscator you could use is Eazfuscator.NET, that webpage I sent also has a description of essentially what it does and how to use it - it may be worth taking a look at.
Online Servers
This one requires a connection to the internet... but, it's the only other option you have at all - it's either this or... able-to-get-rid-of-product-key.
Essentially, in this idea, you make a server do all the work that the application has to do and then return the result of it.
Imagine the user's computer is a server. Their "server" runs the code, and so the code is on their "server" (otherwise it has nothing to run) and everything is processed on their server. Now, if you run it on your server, all the code is on your server and your server only returns the result, meaning, they can't get at the process that provides that result.
In the end, this would mean that the application physically would not be able to do anything without a license key, since the only way it can get its data processed is via the server, and the server won't process the data without a product key.
The only downside to this is that you must have an internet connection and if the internet connection is slow - the program will be slow.
Since you want to know how to do this in vb.net taking a look at ASP.NET may help, but it's really designed to make a full-website - not to just process a few tasks.
I can leave it up to you how you would want to approach this task but here's one way of doing this:
The code below will make a "request" to a certain URL and then get the result back - with this, you could make it so when it goes to that URL the server processes the data given (including the product key) and returns back a result.
Dim request As System.Net.HttpWebRequest
Dim response As System.Net.HttpWebResponse
request = System.Net.HttpWebRequest.Create("https://URLHERE")
response = askforupdate.GetResponse
Dim result As System.IO.StreamReader = New System.IO.StreamReader(response.GetResponseStream)
result now contains a String - but, keep in mind that you can use this for practically anything - even images! (Images are just New Bitmap(response.GetResponseStream))
You can pass data to the server via a Query String, for example:
my.website/processSomething?license=AAAAAAAA&sizeInput=241&somethingElse=asagsag
But, really, it's up to you how you do that.
I'm sorry I couldn't give you an exact solution, but, there really isn't one. You're going to end up sacrificing something either way.
Hopefully, this was at least helpful and helped you understand that it's really not possible to prevent people hacking your software without losing something.
I'm new to VB.NET threading
As for simple testing I tried the following, which I need to smoothly fill a listbox with values.
But it does not work as I expect, it hangs the interface. Please let me know what I'm doing wrong here.
Thank you.
Imports System.Threading
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim Thr As Threading.Thread
Thr = New Threading.Thread(New Threading.ThreadStart(AddressOf tprocess))
'Thr.SetApartmentState(ApartmentState.STA)
Thr.IsBackground = True
Thr.Start()
End Sub
Private Delegate Sub DoStuffDelegate()
Private Sub tprocess()
Dim i As Integer
For i = 0 To 20000
If Me.InvokeRequired Then
Me.Invoke(New DoStuffDelegate(AddressOf tprocess))
Else
ListBox1.Items.Add(i)
End If
Next
End Sub
End Class
When you write code to create a thread then you always have to worry about the kind of bugs that threading can cause. They are very hard to diagnose, the only decent way to address them is to know they exist and to write the code carefully so you know how to avoid them.
The most common threading bugs are threading races, deadlock and firehose bugs. You have the 1st and the 3rd bug in your code. You are complaining about the 3rd. Very quickly: the threading race bug is using Me.InvokeRequired. You have no guarantee that it is still true when the Me.Invoke() statement executes. This goes wrong when the user closes the window while your thread is still running. When you try to fix this problem you'll get to see what the 2nd bug looks like. But you are not there yet.
The firehose bug is the Me.Invoke() call. Very fast, takes less than a microsecond of work for the worker thread, you do it 20000 times at a very high rate. It is however another thread that must actually do the work of adding the item, your UI thread. That is not fast, it not only has to add the item but it also needs to repaint the control. Many microseconds.
While this goes on, your UI thread is burning 100% core, trying to keep up with the relentless rate of invoke requests. Working as hard as it can to add items to the listbox. Something has to give, while it is doing this it is not taking care of the lower priority jobs it has to do. Painting and responding to user input. In effect, your UI looks completely frozen. You can't see it paint anymore and trying to, say, close the window doesn't work. It isn't actually dead, it is hard at work.
Takes a while, probably a few handful of seconds, give or take. Until the worker thread finishes its for() loop and stops slamming the UI thread with invoke requests. And everything turns back to normal.
A firehose bug like this is pretty fundamental. The only way to fix it is to call Invoke() less often or at a lower rate. Note how putting Thread.Sleep(50) after the Invoke() call instantly fixes it. But of course that slows down your worker thread a lot. You call Invoke() less often by using AddRange() instead of Add(), adding (say) 1000 items at a time. Which is the proper fix but now it becomes fairly pointless to still try to update the listbox from the worker thread. Might as well do it with a single AddRange() call. The quickest way.
Try changing:
Thr = New Threading.Thread(New Threading.ThreadStart(AddressOf tprocess))
to this:
Thr = New Threading.Thread(AddressOf tprocess)
ThreadStart will start that thread immediately
I tried the following way. It's almost easy for me to handle. Backgroudworker manages this situation perfectly well.
Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim i As Integer
For i = 1 To 20000
BackgroundWorker1.ReportProgress((i / 20000) * 100, i)
Threading.Thread.Sleep(1)
Next
End Sub
Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
ProgressBar1.Value = e.ProgressPercentage
ListBox1.Items.Add(e.UserState)
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
MsgBox("Complete")
End Sub
I have a vb.net application that interfaces with some external hardware - an array of motor controllers. To do this, I'm using a CANOpen library provided by the hardware supplier. However, the timeouts built into the library are frankly excessive, and cause the application to hang painfully under specific conditions. I'd prefer not to need to edit the library if possible.
What's the most sensible way to design in another, shorter timeout within vb.net? The function in question is a blocking function, so presumably in-thread timers won't help. Is there an elegant solution here?
Give this a try, it's is the best I could come up with so far. I've used background workers just because they are easy to use.
Basically it's a thread within a thread which will at least keep your UI responsive, judging by what you've said you should probably use threading for all the drive comms functions anyway in case a drive loses comms for any reason while the app is running.
This ain't pretty, but it will at least allow you to exit out early before the CAN function itself times out.
Private connected As Boolean
Private Sub bwTryConnect_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bwTryConnect.DoWork
Dim timeout As Boolean
Dim timeoutCount As Integer
Dim timeoutValue As Integer = 5 ' timeout value
bwConnect.RunWorkerAsync() ' start worker to try connection
While bwConnect.IsBusy And Not timeout
Thread.Sleep(1000) ' wait a second
timeoutCount += 1 ' increment timeout value
If timeoutCount = timeoutValue Then timeout = True ' connection timed out
End While
' connected will be true if the try connection worker completed (connection to drive ok) before the timeout flag was set, otherwise false
connected = Not timeout
End Sub
Private Sub bwConnect_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bwConnect.DoWork
' use your CAN library function here - either a simple connect command or just try reading an arbitary value from the drive
' if you want to test this, uncomment one of the following lines:
'Thread.Sleep(20000) ' simulate timeout
'Thread.Sleep(2000) ' simulate connect
End Sub
Obviously you then call with bwTryConnect.RunWorkerAsync().
I am confused. Yes i understand I can't use the same backgroundworker to do two tasks at the same time. What I do not understand is this. Here is my code (all this thing does is set the marqueeanimationspeed of a progress bar...
'THE FOLLOWING SUB TOGGLES THE PROGRESS BAR
Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
'CHECK THE STATE OF THE PROGRESS BAR AND TOGGLE IT
If ToolStripProgressBar1.MarqueeAnimationSpeed = 0 Then
ToolStripProgressBar1.MarqueeAnimationSpeed = 22
End If
ToolStripProgressBar1.MarqueeAnimationSpeed = 0
End Sub
OK, so how long can this possibly take? Doesn't the worker do the task and exit? So I put in a pause (system.threading.thread.sleep(2000)... same problem, made it 20 seconds... same problem.
So I am assuming this is a simple thing I'm missing, but I've spent more than an hour searching and I don't get it.
All I am trying to accomplish here is to start the marquee progress bar while the UI is running something else, and then stop it. I assume I can create another backgroundworker and just use it, but I want to understand why the first one is not done with the task.
Thanks, and again, yes I spent an hour searching and I find all kinds of "solutions" but no explanation as to why this thing is not finished.
OK SO HERE IS THE SUB CALLING THE BGW
'THE FOLLOWING SUB FIRES THE SETTING CONNECTION STRINGS SUB
Private Sub SetCSButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SetCSButton.Click
'START THE PROGRESS BAR & CHANGE THE LABEL
BackgroundWorker1.RunWorkerAsync()
Threading.Thread.Sleep(1000)
ToolStripStatusLabel1.Text = "Preparing the connection strings..."
Me.Refresh()
thread3 = New System.Threading.Thread(AddressOf SetConnectionStrings)
thread3.Start()
'STOP THE PROGRESS BAR & CHANGE THE LABEL
BackgroundWorker2.RunWorkerAsync()
Threading.Thread.Sleep(1000)
ToolStripStatusLabel1.Text = "Standing by..."
Me.Refresh()
End Sub**strong text**
I had a 20second delay but still the first BGW does not finish. I know this is something simple but I dont understand, that's all I am after here.
I DID change the code and do not use the same methodology as I was trying at the time I wrote this question... What I do not understand is why a simple operation is never, apparently, finishing... having said that, it DOES finish as I was able to show a msgbox using the runworkercompleted event. So, as I tried and failed to convey, thbis is not about the right or wrong way to code, I know it wa wrong and was just trying to be quick and dirty, regardless of that, I am not doing that now, but I do not understand why the BGW is "still working". There must be some simple thing I am ignorant about.
Thanks
The error is not in the posted code but where you start the Bgw.
But it is all irrelevant because you should not touch the GUI from DoWork:
Private Sub BackgroundWorker1_DoWork(...) Handles BackgroundWorker1.DoWork
'CHECK THE STATE OF THE PROGRESS BAR AND TOGGLE IT
If ToolStripProgressBar1.MarqueeAnimationSpeed = 0 Then ' Boom, cross-threading violation
ToolStripProgressBar1.MarqueeAnimationSpeed = 22
End If
I don't think you need a Bgw, thread or timer here. Just change the speed before/after the slow action.
Using VB.Net I've added a CTRL-C handler:
AddHandler Console.CancelKeyPress, AddressOf QuitHandler
Which does the following:
Private Sub QuitHandler(ByVal sender As Object, ByVal args As ConsoleCancelEventArgs)
Console.WriteLine("Quitting...")
args.Cancel = True
Quit = True
End Sub
I then have a main loop which just runs until Quit=True.
This all works until I start reading from the serial port:
Private Sub port_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles Port.DataReceived
at which point the CTRL-C handler gets ignored for about 30secs at which point the console app just terminates without going through the cleanup code.
Why?
I don't know VB, but my guess would be that you're attempting to read data from the serial port that isn't there (err, the port is there, the data isn't); as a result, your program is blocking ("hanging") until the read attempt times out after 30 seconds.
If I'm correct, you need some way to poll your serial input without blocking, or (better) to get an asynchronous sub called when data actually appears.
You should make sure to understand how Timeouts work, since you are reading serial port on pooling. Your serial thread will always be running and trying to read something.
A best approuch would be to read data just when its availiable, then your serial thread would have time to breath.
You can also try to use DoEvents.