0

I'm working on turning an application into a "listener" of sorts. This program handles filling in ZPL shipping label templates with data from the database. We have multiple programs that call this label program, and all but one have a Zebra printer hooked to the PC, which the label program detects and automatically prints the labels once finished filling them in.

In a different application, which is a picking program where the user has a wearable terminal and wireless Zebra label printers, it's causing an issue. The label program knows what to process by way of a queue/stack table where the entries are linked to the machine name filling the queue in. On the picking program, instead of the label program sending the ZPL to a printer, it's writing the ZPL to a file so that the picking program can read the ZPL and modify the commands for the wireless Zebras.

I'm having trouble in the picking program, after the label program has run and created the text file containing the ZPL. The label program can, for some customers, write up to 4 ZPLs into the same file, and I need in the picking program to know when it's finished writing to the file and the file is ready for reading. Right now I'm checking that the label queue is empty for the machine, but the file isn't always ready to open by that time.

My code is below. I basically need to find some way of know when the file is finished being written to and is ready to read, but I need to take into account that the label program may error and never write the file at all.

StartPrintLabelListener() simply starts the label program if it isn't running already, and CheckCartonLabelQueueEmpty() checks to see if there are no records for the user in the queue table, returning a Boolean value. As you can see below, my most recent attempt at overcoming the file not being ready yet consists of a loop with a 1/10 of a second delay, doing a couple of checks each iteration (so that if it takes too long to generate the file, an error will occur).

Private Sub PrintLabel(strCartonID As String)
    Try
        Dim drCH As OracleDataReader = selectCartonInformation(strCartonID)
        Dim dteDateModified As DateTime = Nothing, dteNewDateModified As DateTime = Nothing
        Dim strTmpFileName As String = "C:\tmp\tmplabel.zpl"

        If System.IO.File.Exists(strTmpFileName) Then
            dteDateModified = System.IO.File.GetLastWriteTime(strTmpFileName)
            System.IO.File.Delete(strTmpFileName)
        End If

        If drCH.Read Then
            'insert the carton into the queue to be printed
            insertCartonLabelQueue(Convert.ToInt32(drCH.Item("SKLC_CH")))
        End If

        'start the print label listener if it isn't running for this user already
        StartPrintLabelListener()

        'now that the print label program is running, keep checking the SKLC_CARTONLABELQ to see if the label finished processing or until tmrLabelTimer elapses
        Dim intLabelTimer As Integer = 0
        Dim blnPrintLabelComplete As Boolean = False, blnCartonLabelQueueEmpty As Boolean = False, blnFileExists As Boolean = False, intFileExistsCheck As Integer = 0
        While Not blnPrintLabelComplete And intLabelTimer < 20000
            If Not blnCartonLabelQueueEmpty Then
                blnCartonLabelQueueEmpty = CheckCartonLabelQueueEmpty(Convert.ToInt32(drCH.Item("SKLC_CH")))
            End If

            If System.IO.File.Exists(strTmpFileName) Then
                intFileExistsCheck += 1
            End If

            blnFileExists = (intFileExistsCheck > 3)

            If blnCartonLabelQueueEmpty And blnFileExists Then
                blnPrintLabelComplete = True
            End If

            intLabelTimer += 100
            System.Threading.Thread.Sleep(100)
        End While

        'if blnPrintLabelComplete is set to true, vbPrintLabel processed the label. check the tmp file attributes to be sure it's actually a new file
        If blnPrintLabelComplete Then
            If System.IO.File.Exists(strTmpFileName) Then
                dteNewDateModified = System.IO.File.GetLastWriteTime(strTmpFileName)
            End If

            If dteNewDateModified = Nothing Or (Not dteNewDateModified = Nothing AndAlso Not dteDateModified = Nothing AndAlso dteNewDateModified <= dteDateModified) Then
                Throw New PrintLabelException("An error has occurred while generating the label.")
            End If

            If Not ZebraPrinter.PrintTmpFile(CurPicker.UserName) Then
                Throw New PrintLabelException("An error has occurred while printing the label.")
            End If
        Else
            deleteCartonsFromQueue(intSessionID)
            Throw New PrintLabelException("An error has occurred while generating the label.")
        End If
    Catch ex As Exception
        If TypeOf (ex) Is PrintLabelException Then
            Throw
        Else
            Throw New PrintLabelException("An error has occurred while printing the label.", ex)
        End If
    End Try
End Sub
RianBattle
  • 898
  • 6
  • 20
  • Are you looking for something like [this](http://stackoverflow.com/questions/876473/is-there-a-way-to-check-if-a-file-is-in-use/937558#937558)? – Rick S Mar 02 '15 at 19:08
  • Does the original program lock the file for the entire duration of adding data to the file or does it add some data, close the file, add some data, close the file, etc? – UnhandledExcepSean Mar 02 '15 at 19:33
  • @Ghost It opens and closes the file as it writes the data in large chunks. Basically, it determines how many different labels the particular carton needs, and loops through creating each one. On each label, it opens the test file with a `Using` statement with a `StreamWriter`, writes the ZPL, and then exits the `Using` statement. Actually stating that out loud makes me think I should be modifying the original program to lock it until it's finished processing, then close it. Would make it simpler to check in the calling program, correct? – RianBattle Mar 02 '15 at 19:48
  • 1
    Based on that, my recommendation is to write the file with a .tmp extension and at the very end of the writing process, rename it to .zpl. Your program that reads it would pick it up and delete it at the end. Your writing program would not write a new file while there is an existing .zpl in the directory. This should prevent concurrency issues. – UnhandledExcepSean Mar 02 '15 at 20:40
  • @Ghost thanks! I think I've been staring at this issue for too long...such a simple solution compared to what I was attempting and should work perfectly. I'll work on implementing and post back with results. thanks again! – RianBattle Mar 02 '15 at 21:00

0 Answers0