0

Screenshot of the error: Screenshot of the error

Simple FTP client that automatically synchronizes with servers and retrieves the files.

Application seems to run well on my computer and 3 other computers i have tested it on. Dependencies are included in the exe and build as a single file.

I was sent this screenshot from my customer but i am not able to replicate the issue on my end to fix it. The crash happens when the start server button is pressed.

I figured this must be related to the "timer" since the start server button enables the timer. Interval is set by the button according to what the user inputs as the desired sync rate.

Has anyone encountered this problem before?

I have tried removing the timer entirely and use System.Threading.Thread.CurrentThread.Sleep(min*1000)

I find that to be really unstable because it is making my application freeze and unresponsive.

On a second computer that i tested this on I tried updating windows and that fixed this, but its not working on my clients computer.

my next thoughts are to try and install a fresh VM and try to replicate the error so i can follow up on it.

Code Bellow :


'This program includes most dependencies needed to run.
'In case you are still encountering errors while operating this program,
'if you are using windows 10 please run windows update and make sure you are up to the latest version
'if its still not working please download V_redistributables for visual studio

'Patch Notes 1.0.3
'The program now pulls the newer file version from the FTP directory and updates it.
'if you are using a single database and you want that updated it will now look for the last updated 
'version and pull that file.


Imports System.Configuration
Imports System.IO
Imports System.Net

Public Class Form1

    Dim apppath = Application.StartupPath() + "ftpc\" 'get app path
    Dim settings = apppath + "settings.nfo"
    Dim username
    Dim password
    Dim IPad
    Dim IPpo
    Dim savedir
    Dim file As System.IO.StreamWriter
    Dim fs As FileStream
    Dim thatoneline
    Dim thatsecondline
    Dim thathirdline, remotefl
    Dim min, pbi, pbimax As Integer

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        On Error GoTo ErrorHandler
        Me.Text = "Lekysoft FTPC 1.0.3 status: Disconnected"
        If Not System.IO.File.Exists(settings) Then
            ' file does not exist , create settings file
            If Not System.IO.Directory.Exists(apppath) Then
                System.IO.Directory.CreateDirectory(apppath)
            End If
            fs = System.IO.File.Create(settings)
            IPad = ""
            fs.Close()

        Else
            fs.Close()

            On Error GoTo ErrorHandler
            FileOpen(1, settings, OpenMode.Binary, OpenAccess.Read, OpenShare.LockRead)
            'load data
            Input(1, IPad) 'get IP
            Input(1, IPpo) 'get port
            Input(1, username) 'get username
            Input(1, password) 'get pass
            Input(1, savedir) 'get save path
            Input(1, min) 'get save sync time
            ' Close before reopening in another mode.
            FileClose(1)
ErrorHandler:
            Resume Next
            'display loaded info

            txtsa.Text = IPad
            txtpo.Text = IPpo
            txtus.Text = username
            txtpa.Text = password
            txtpth.Text = savedir
            txtmin.Text = min

        End If
        txtpth.Text = apppath
        thatoneline = txtthatonetext.Text
        thatsecondline = txtthatsecondtext.Text
        thathirdline = txtthatthirdtext.Text

    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        If txtpa.Text = "" Or txtus.Text = "" Or txtsa.Text = "" Or txtpo.Text = "" Or txtpth.Text = "" Or txtmin.Text = "" Then
            MsgBox("Please fill in all the textfields")
        Else
            'Generate configuration file\

            IPad = txtsa.Text
            IPpo = txtpo.Text
            username = txtus.Text
            password = txtpa.Text
            savedir = txtpth.Text
            min = Len(txtmin.Text)
            file = My.Computer.FileSystem.OpenTextFileWriter(settings, False, System.Text.Encoding.Default)
            MsgBox("Configuration saved")
            file.WriteLine(IPad)
            file.WriteLine(IPpo)
            file.WriteLine(username)
            file.WriteLine(password)
            file.WriteLine(savedir)
            file.WriteLine(min)
            file.Close()



        End If
    End Sub



    Private Sub Button4_Click_1(sender As Object, e As EventArgs) Handles Button4.Click

        If FolderBrowserDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
            MsgBox("Configuration saved")
            savedir = FolderBrowserDialog1.SelectedPath + "\"
            txtpth.Text = savedir
        End If
    End Sub

    Private Sub PictureBox1_Click(sender As Object, e As EventArgs) Handles PictureBox1.Click

    End Sub

    Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
        End
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click


        Timer3.Interval = 1000 * min / 2 + (min * 10 / 100)
        pbi = 1
        pbimax = min * 100 + 1

        text1.Text = "Lekysoft FTPC 1.0.3 status: Connecting to... " + IPad.ToString + ":" + IPpo.ToString + " (Please wait)"
        Me.Text = text1.Text

        Button3.Enabled = True
        Button2.Enabled = False
        txtha.Enabled = False
        txtmin.Enabled = False
        txtpa.Enabled = False
        txtpo.Enabled = False
        txtpth.Enabled = False
        txtsa.Enabled = False
        txttime.Enabled = False
        txtus.Enabled = False
        Timer3.Enabled = True



        Dim credentials As NetworkCredential = New NetworkCredential(username.ToString, password.ToString)
        Dim url As String = "ftp://" + IPad + ":" + IPpo + "/"
        DownloadFtpDirectoryIfNewer(url, credentials, savedir)
        text1.Text = "Lekysoft FTPC 1.0.3 status: Connected to " + IPad.ToString + ":" + IPpo.ToString + " sync: " + min.ToString + " minutes"
        Me.Text = text1.Text
        MsgBox("ftp connection successful")

    End Sub

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        Me.FormBorderStyle = FormBorderStyle.FixedSingle
        Me.MaximizeBox = False
        PictureBox1.Visible = False
    End Sub

    '////////////////////////////////////////////////////////////////////////////////////////////

    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        Me.Text = "Lekysoft FTPC 1.0.3 status: Disconnected"
        pbi = 1
        ProgressBar1.Value = 1
        Timer3.Enabled = False

        pbi = 1

        Me.Text = "Lekysoft FTPC 1.0.3 status: Disconnected"
        Timer3.Enabled = False
        Button2.Enabled = True
        Button3.Enabled = False
        txtha.Enabled = True
        txtmin.Enabled = True
        txtpa.Enabled = True
        txtpo.Enabled = True
        txtpth.Enabled = True
        txtsa.Enabled = True
        txttime.Enabled = True
        txtus.Enabled = True

        text1.Text = "Lekysoft FTPC 1.0.3 status: Connected to " + IPad.ToString + ":" + IPpo.ToString + " autosynching every " + min.ToString + " minutes"
    End Sub


    Private Sub Timer3_Tick(sender As Object, e As EventArgs) Handles Timer3.Tick
        pbi = pbi + 1
        ProgressBar1.Maximum = pbimax
        If (pbi < pbimax + 1) Then
            ProgressBar1.Value = pbi
        Else
            pbi = 1
            Dim credentials As NetworkCredential = New NetworkCredential(username.ToString, password.ToString)
        Dim url As String = "ftp://" + IPad + ":" + IPpo + "/"
            DownloadFtpDirectoryIfNewer(url, credentials, savedir)
        End If
    End Sub


    Sub DownloadFtpDirectoryIfNewer(url As String, credentials As NetworkCredential, localPath As String)
        Dim listRequest As FtpWebRequest = WebRequest.Create(url)
        listRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails
        listRequest.Credentials = credentials

        Dim lines As List(Of String) = New List(Of String)

        Using listResponse As FtpWebResponse = listRequest.GetResponse(),
              listStream As Stream = listResponse.GetResponseStream(),
              listReader As StreamReader = New StreamReader(listStream)
            While Not listReader.EndOfStream
                lines.Add(listReader.ReadLine())
            End While
        End Using

        For Each line As String In lines
            Dim tokens As String() =
                line.Split(New Char() {" "}, 9, StringSplitOptions.RemoveEmptyEntries)
            Dim name As String = tokens(8)
            Dim permissions As String = tokens(0)

            Dim localFilePath As String = Path.Combine(localPath, name)
            Dim fileUrl As String = url + name

            If permissions(0) = "d" Then
                If Not Directory.Exists(localFilePath) Then
                    Directory.CreateDirectory(localFilePath)
                End If
                DownloadFtpDirectoryIfNewer(fileUrl + "/", credentials, localFilePath)
            Else
                Dim downloadRequest As FtpWebRequest = WebRequest.Create(fileUrl)
                downloadRequest.Method = WebRequestMethods.Ftp.GetDateTimestamp
                downloadRequest.Credentials = credentials

                Using downloadResponse As FtpWebResponse = downloadRequest.GetResponse()
                    Dim lastModified As DateTime = downloadResponse.LastModified

                    If Not System.IO.File.Exists(localFilePath) OrElse lastModified > System.IO.File.GetLastWriteTime(localFilePath) Then
                        Dim downloadFileRequest As FtpWebRequest = WebRequest.Create(fileUrl)
                        downloadFileRequest.Method = WebRequestMethods.Ftp.DownloadFile
                        downloadFileRequest.Credentials = credentials

                        Using downloadFileResponse As FtpWebResponse = downloadFileRequest.GetResponse(),
                              sourceStream As Stream = downloadFileResponse.GetResponseStream(),
                              targetStream As Stream = System.IO.File.Create(localFilePath)
                            Dim buffer As Byte() = New Byte(10240 - 1) {}
                            Dim read As Integer
                            Do
                                read = sourceStream.Read(buffer, 0, buffer.Length)
                                If read > 0 Then
                                    targetStream.Write(buffer, 0, read)
                                End If
                            Loop While read > 0
                        End Using
                    End If
                End Using
            End If
        Next
    End Sub


End Class

Peter Macej
  • 4,831
  • 22
  • 49
  • 1
    `Timer3.Interval = Math.Max(1, 1000 * min \ 2 + (min * 10 \ 100))`. Use the debugger to get the `min` value. You need to reconsider this code to rewrite it in `vb.net` way, not `vb#`s. Good time to visit [Visual Basic documentation](https://learn.microsoft.com/en-us/dotnet/visual-basic/). – dr.null Jun 01 '23 at 13:41
  • 1
    You should have `Option Strict On` and then that line that sets the `Interval` would be flagged as an error, because you're assigning a `Double` value to an `Integer` property. That expression is obviously evaluating to a value that, when rounded to an `Integer`, results in zero. Maybe you should be using integer division (`\` rather than `/`) but who knows, because you haven't actually explained what you're trying to achieve. – jmcilhinney Jun 01 '23 at 13:44
  • @jmcilhinney My program works well on my computer and 3 others. its retrieving ftp files from a server to this client. on the other hand it does not work on my customers computer. It is very hard to debug since its not giving me an error and its running normally on my end – Kyriacos Leandrou Jun 01 '23 at 13:47
  • 1
    @dr.null that was a very helpful lead, i thought it would be rounded down as an integer if the result was a float value. That might be the cause of the error. Even if it strangely works on my computer and not on the client. I will try the CInt function to round up the reusult and see if that works out. Thank you – Kyriacos Leandrou Jun 01 '23 at 14:08
  • It obviously depends what the value of `min` is as to what `1000 * min / 2 + (min * 10 / 100)` evaluates to. A value of `-1` would cause that expression to produce zero, so maybe it's that. Add some code to catch the exception and display the value, then have the user run it again. That's how you need to determine what's going on in a deployed application if you can't replicate the issue in your development environment. – jmcilhinney Jun 01 '23 at 14:11
  • 1
    I have to agree with the earlier comment that that code looks like it was written for VB6. It could stand a lot of improvement, from setting `Option Strict On` and not using late binding and implicit conversions to using .NET types rather than VB Runtime functions that are basically holdovers from VB6. – jmcilhinney Jun 01 '23 at 14:13
  • @jmcilhinney this is a VB.Net forms project. Indeed i have learned to code in VB6 and I have been using that for years. I now have switched to .Net that is why my style must look oldschool . A lot must have changed since. – Kyriacos Leandrou Jun 01 '23 at 14:20
  • On line "Timer3.Interval = 1000 * min / 2 + (min * 10 / 100)" The interval value was returning a decimal number that was resulting in the integer being 0. This was fixed by changing the code to: (this rounds up the decimal to the closest integer) Timer3.Interval = CInt(1000 * min / 2 + (min * 10 / 100)) Unfortunately this did not fix the error and the message is still popping up. – Kyriacos Leandrou Jun 02 '23 at 08:56
  • @jmcilhinney I have tried the Option Strict On, i was able to define most of the ordinary variables but when it comes to abnormal types like Dim downloadFileRequest As FtpWebRequest = WebRequest.Create(fileUrl) , Option strict does not accept this as a valid declaration and flags it as an error – Kyriacos Leandrou Jun 02 '23 at 09:14
  • The strangest thing about this is that it works on all the computers i have tested it on, except my clients. =( – Kyriacos Leandrou Jun 02 '23 at 09:39
  • Of course that code is flagged as an error. `WebRequest.Create` returns a `WebRequest` reference, which you cannot assign to an `FtpWebRequest` variable. You need a reference of that type, so you need to cast: `Dim downloadFileRequest As FtpWebRequest = DirectCast(WebRequest.Create(fileUrl), FtpWebRequest)`. That's the whole point of `Option Strict On`: you have to cast and/or convert explicitly and not rely on the system to do it for you. – jmcilhinney Jun 02 '23 at 12:51

1 Answers1

0

I followed your advice and ended up rewriting the application from scratch. Removed any excessive and unnecessary additions, simplified and removed the interface. Automated it to specific credentials and time. everything was predefined and its just stat and go.

Its probably not the best approach but sometimes its better to scrap the project and start over clean when things do not work. Thank you for your help!