vb.net/windows服务器中的神秘多重执行问题

时间:2013-10-21 19:49:59

标签: vb.net smtp windows-server-2008 batch-processing

过去两周我一直在解决这个问题,而且我的智慧结束了。我已经尽可能地缩小了范围,我真的发布了这个,希望有人可以确认我的分析,并可能建议采取行动。

我将逐步了解应用程序中的这一点,以便我们都在同一页面上。编写应用程序以查询数据库并检索包含用户信息和用户电子邮件地址的三个随机记录,然后对于返回的每个记录,我们检查以查看类型,并根据类型发送电子邮件。我已经在本地测试了这个过程并且每次都没有问题地执行,但是一旦将其编译成可执行文件并放置在服务器上以每15分钟的间隔执行,用户就开始抱怨收到多个同样的电子邮件记录....我将发布一些代码,然后解释我到目前为止所发现的内容:

Module Module1

Sub Main()

    CreateExecutionLogFile(DateTime.Now.ToString, "BEGIN")

    Dim dtEmails As DataTable = RetreiveEmailsToSend()

    For Each dr As DataRow In dtEmails.Rows
        With dr
            Select Case .Item("EmailType").ToString.Trim
                Case "NEW"
                    SendNewEmail(.Item("EmpUserID").ToString.Trim, .Item("EmpEmailAddress").ToString.Trim, .Item("EmpFullName").ToString.Trim, _
                                       CInt(.Item("RecordIDPK").ToString.Trim), .Item("SupervisorEmailAddress").ToString.Trim)
                Case "24H"
                    Send24hEmail(.Item("EmpUserID").ToString.Trim, .Item("EmpEmailAddress").ToString.Trim, .Item("EmpFullName").ToString.Trim, _
                                       CInt(.Item("RecordIDPK").ToString.Trim), .Item("SupervisorEmailAddress").ToString.Trim)
                Case "48H"
                    Send48hEmail(.Item("EmpUserID").ToString.Trim, .Item("EmpEmailAddress").ToString.Trim, .Item("EmpFullName").ToString.Trim, _
                                       CInt(.Item("RecordIDPK").ToString.Trim), .Item("SupervisorEmailAddress").ToString.Trim)
            End Select
            UpdateRecordAfterEmail(CInt(.Item("RecordIDPK").ToString.Trim), .Item("EmailType").ToString.Trim)
        End With
    Next

    CreateExecutionLogFile(DateTime.Now.ToString, "END")

End Sub

''Send24hEmail() and Send48hEmail() are mirrors of this function with only the wording in the email body being changed
''therefore I only include the following function to make things easier to read in this post
Private Sub SendNewEmail(ByVal EmpUserID As String, ByVal EmpEmailAddress As String, ByVal EmpFullName As String, ByVal RecordID As Integer, ByVal SupEmailAddress As String)
    Dim strFrom As String = "DoNotReply@test.place"
    Dim strTo As String = EmpEmailAddress
    Dim strSubject As String = "TEST SUBJECT"
    Dim strCC As String = SupEmailAddress.Trim
    Dim strMessage As New StringBuilder

    With strMessage
        .Append("Hello!//EMAIL BODY IS BUILT HERE")
        .Append(DateTime.Now.ToString())
    End With

    SendEmail(strFrom, strTo, strSubject, strMessage.ToString, strCC, RecordID.ToString, "NEW", EmpUserID)
End Sub

Private Sub UpdateRecordAfterEmail(ByVal RecordID As Integer, ByVal EmailType As String)
    'Connects to database and runs query to update the record as sent
End Sub

Public Sub SendEmail(ByVal strFrom As String, ByVal strTo As String, ByVal strSubject As String, ByVal strMessage As String, ByVal strCC As String, ByVal recordID As String, ByVal type As String, ByVal userID As String)
    If CheckIfEmailSent(recordID, type) = False Then
        If strTo > "" Then
            Try
                Dim MailMsg As New MailMessage()
                strTo = strTo.Trim(CChar(","))

                MailMsg.To.Add(strTo)

                If strCC.Trim <> "" Then
                    MailMsg.CC.Add(strCC)
                End If

                MailMsg.From = New MailAddress(strFrom, "FROM MESSAGE")
                MailMsg.BodyEncoding = Encoding.Default
                MailMsg.Subject = strSubject.Trim()
                MailMsg.Body = strMessage.Trim() & vbCrLf
                MailMsg.Priority = MailPriority.High
                MailMsg.IsBodyHtml = False

                Dim mailClient As New SmtpClient("mail.name.place")
                mailClient.UseDefaultCredentials = True
                mailClient.Send(MailMsg)
                MailMsg.Dispose()

                CreateLogFile(recordID, type, userID, strTo)

            Catch innerException As Exception

                Dim MailMsg As New MailMessage()

                MailMsg.To.Add("nullReference@name.place")

                MailMsg.From = New MailAddress(strFrom, "FROM MESSAGE - ERROR")
                MailMsg.BodyEncoding = Encoding.Default
                MailMsg.Subject = strSubject.Trim()
                MailMsg.Body = strMessage.Trim() & vbCrLf & vbCrLf & vbCrLf & innerException.Message
                MailMsg.Priority = MailPriority.High
                MailMsg.IsBodyHtml = False

                Dim mailClient As New SmtpClient("mail.name.place")
                mailClient.UseDefaultCredentials = True
                mailClient.Send(MailMsg)
                MailMsg.Dispose()

            End Try
        End If
    Else
        CreateLogFile("*ERROR* ATTEMPTED RESEND" + " " + recordID, type, userID, strTo)
    End If

End Sub

Private Function CheckIfEmailSent(recordID As Integer, type As String) As Boolean
    ''Connect to database determine if recordID has already been sent
    ''If it has return true, else return false
End Function

Private Sub CreateLogFile(ByVal recordID, ByVal type, ByVal userID, ByVal email)
    ''Create log file on server containing information passed to function and
    ''current datetime
End Sub

Private Sub CreateExecutionLogFile(time As String, beginEnd As String)
    ''Create log file on server containing the time passed and either "BEGIN"
    ''or "END" depending on the value in "beginEnd"
End Sub

End Module

我最初在SendEmail()例程(CheckIfEmailSent())中放置了一个补丁,该例程连接到数据库,并在发送另一封电子邮件之前检查该记录是否已被标记为已发送。我认为这会很快解决问题,但我很快就被证明是错误的。

现在,由于问题在上述修补程序之后仍然存在,我开始认为它与smtp邮件客户端挂起并发送多封电子邮件有关,但后来我意识到情况并非如此,因为电子邮件中包含的内容是不同的,这意味着SendNewEmail()函数必须运行两次以生成新的时间值,以便在将电子邮件发送到SendEmail()函数之前放置在电子邮件的正文字符串中...... .0_0 ... 。是啊...

每次发送电子邮件时写入的日志文件都会显示第一封电子邮件已发送,而且从未记录第二封电子邮件......更奇怪。 在这一点上,我能想到的唯一事情是,不知何故,该过程最初从服务器执行两次,然后在初始进程仍在运行时再次执行两次并且它们是冲突的???我很茫然...如果有人能够对可能发生的事情有所了解,那么我或多或少就会成功! :/

1 个答案:

答案 0 :(得分:0)

在追踪哪些服务器正在发送电子邮件之后,我们终于找到了这个问题。发生的事情是,有一个旧版本的.exe设置运行,每个人都忘记了,这两个是相互冲突的。因为它们被设置为在发送之后将行标记为已发送,所以旧的.exe将不时地拉出记录并在新的运行之后立即发送它但是它有机会将其标记为已经发送,从而产生重复随机记录。