为什么这个正则表达式测试对于应该是相同的正文文本给出不同的结果? [英] Why does this regular expression test give different results for what should be the same body text?

查看:71
本文介绍了为什么这个正则表达式测试对于应该是相同的正文文本给出不同的结果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是相关的代码,它根据我是使用 TestLaunchURL 启动它还是在传入消息到达时由 Outlook 传递给它的消息正文的正则表达式测试给出不同的结果:

Here's the pertinent code, which is giving different results on the regular expression test for the message body depending on whether I launch it using TestLaunchURL or the message is passed to it by Outlook when an incoming message arrives:

Public Sub OpenLinksMessage(olMail As Outlook.MailItem)

 Dim Reg1 As RegExp
 Dim AllMatches As MatchCollection
 Dim M As Match
 Dim strURL As String
 Dim RetCode As Long

Set Reg1 = New RegExp

With Reg1
 .Pattern = "(https?[:]//([0-9a-z=\?:/\.&-^!#$;_])*)"
 .Global = True
 .IgnoreCase = True
End With

PlayTheSound "Speech On.wav"

RetCode = Reg1.Test(olMail.Body)
MsgBox "The RetCode from Reg1.Test(olMail.Body) equals" + Str(RetCode)
' If the regular expression test for URLs in the message body finds one or more
If RetCode Then
       PlayTheSound "chimes.wav"
'      Use the RegEx to return all instances that match it to the AllMatches group
       Set AllMatches = Reg1.Execute(olMail.Body)
       For Each M In AllMatches
               strURL = M.SubMatches(0)
'              Don't activate any URLs that are for unsubscribing; skip them
               If InStr(1, strURL, "unsubscribe") Then GoTo NextURL
'              If the URL ends with a > from being enclosed in darts, strip that > off
               If Right(strURL, 1) = ">" Then strURL = Left(strURL, Len(strURL) - 1)
'              The URL to activate to accept must contain both of the substrings in the IF statement
               PlayTheSound "tada.wav"
               If InStr(1, strURL, ".com") Then
                     PlayTheSound "TrainWhistle.wav"
'                    Activate that link to accept the job
                     RetCode = ShellExecute(0, "Open", strURL)
                     Set Reg1 = Nothing
                     Exit Sub
               End If

NextURL:
   Next

End If

Set Reg1 = Nothing

End Sub

Private Sub TestLaunchURL()
    Dim currItem As MailItem
    Set currItem = ActiveExplorer.Selection(1)
    OpenLinksMessage currItem
End Sub

测试 IF Reg1.Test(olMail.Body) 在从 Outlook 规则调用传入邮件时总是返回 0,当我使用调试器触发它时总是返回 -1 对于同一消息 来自我的收件箱.

The test IF Reg1.Test(olMail.Body) always returns a 0 when invoked from an Outlook rule on an incoming message and always returns a -1 when I use the debugger to trigger it for that same message from my inbox.

当代码被 Outlook 规则触发时,代码的行为几乎就像它有一个空邮件正文,而不是在我的收件箱中从完全相同的邮件中启动邮件正文.

The code is acting almost as though it has a null message body when it is triggered by an Outlook rule versus having the message body when kicked off by me from exactly the same message once it's in my inbox.

我完全糊涂了,因为我无法理解一个相同的消息,具有相同的正文,根据谁将消息交给子例程,会给出两种不同的结果.

I am completely flummoxed, as I can't understand how one and the same message, with one and the same body, can give 2 different results depending on who hands the message to the subroutine.

其他调试信息:由于问题似乎与消息正文的值有关,因此我添加了以下代码,该代码也检查了 HTMLBody:

Additional Debugging Information: Since the issue appears to surround the value of the Body of the message, I added the following code, that also examines the HTMLBody as well:

If IsNull(olMail.Body) Then
     MsgBox "The message body is null!!"
Else
     MsgBox "BODY:  " + "|" + olMail.Body + "|"
End If

If IsNull(olMail.HTMLBody) Then
     MsgBox "The message HTMLbody is null!!"
Else
     MsgBox "BODY:  " + "|" + olMail.HTMLBody + "|"
End If

当 Outlook 规则针对包含内容且仅包含内容的邮件触发脚本时,"http://britishtoolworks.com",当它到达时,这是两个消息框:

When the script is triggered by the Outlook rule on a message with the content, and only the content, "http://britishtoolworks.com", when it arrives these are the two message boxes:

[由于某种原因,我被禁止发布图片.这些在 BODY 和一些文本的两个管道字符之间绝对没有显示任何内容,但对于 HTMLBody 没有显示其中的 URL]

[I am being forbidden to post images for some reason. These show absolutely nothing between the two pipe characters for BODY and some text, but nothing with the URL in it, for the HTMLBody]

如果我在收件箱中同样的消息后通过 TestLaunchURL 触发脚本,这些是消息框:

while these are the message boxes if I trigger the script via TestLaunchURL after that very same message is sitting in my inbox:

[显示实际的预期内容.我被禁止发布更多图片.]

[Shows the actual expected content. I am forbidden from posting more images.]

如果有人能解释这种差异,请解释.

If anyone can explain this discrepancy, please do.

推荐答案

这是最终有效的代码.很明显,olMail 的 .Body 成员在某种幕后处理有时间发生之前不可用,并且如果您等待的时间不够长,那么当您去测试使用它时,它就不会出现.专注于出现问题的公共子 OpenLinksMessage.

Here is the code that finally works. It's clear that the .Body member of olMail is not available until some sort of behind the scenes processing has had time to occur and if you don't wait long enough it won't be there when you go to test using it. Focus on the Public Sub OpenLinksMessage which is where the problem had been occurring.

允许 olMail.Body 的预期处理发生的主要(也是唯一)更改显然是添加了以下代码行:Set InspectMail = olMail.GetInspector.CurrentItem.运行此 set 语句所需的时间允许 .Body 在 Outlook 规则传入的 olMail 参数上变得可用.有趣的是,如果您在 set 语句之后立即显示 InspectMail.Body,它会显示为空,就像 olMail.Body 过去那样.

The major (and only) change that allowed the expected processing of olMail.Body to take place, apparently, was the addition of the line of code: Set InspectMail = olMail.GetInspector.CurrentItem. The time it takes for this set statement to run allows the .Body to become available on the olMail parameter that's passed in by the Outlook rule. What's interesting is that if you immediately display InspectMail.Body after the set statement it shows as empty, just like olMail.Body used to.

Option Explicit

Private Declare Function ShellExecute _
  Lib "shell32.dll" Alias "ShellExecuteA" ( _
  ByVal hWnd As Long, _
  ByVal Operation As String, _
  ByVal Filename As String, _
  Optional ByVal Parameters As String, _
  Optional ByVal Directory As String, _
  Optional ByVal WindowStyle As Long = vbMinimizedFocus _
  ) As Long



Public Sub OpenLinksMessage(olMail As Outlook.MailItem)

 Dim InspectMail As Outlook.MailItem
 Dim Reg1 As RegExp
 Dim AllMatches As MatchCollection
 Dim M As Match
 Dim strURL As String
 Dim SnaggedBody As String
 Dim RetCode As Long

' The purpose of the following Set statement is strictly to "burn time" so that the .Body member of
' olMail is available by the time it is needed below.  Without this statement the .Body is consistently
' showing up as empty.  What's interesting is if you use MsgBox to display InspectMail.Body immediately after
' this Set statement it shows as empty.
Set InspectMail = olMail.GetInspector.CurrentItem

Set Reg1 = New RegExp

With Reg1
 .Pattern = "(https?[:]//([0-9a-z=\?:/\.&-^!#$;_])*)"
 .Global = True
 .IgnoreCase = True
End With

RetCode = Reg1.Test(olMail.Body)
' If the regular expression test for URLs in the message body finds one or more
If RetCode Then
'      Use the RegEx to return all instances that match it to the AllMatches group
       Set AllMatches = Reg1.Execute(olMail.Body)
       For Each M In AllMatches
               strURL = M.SubMatches(0)
'              Don't activate any URLs that are for unsubscribing; skip them
               If InStr(1, strURL, "unsubscribe") Then GoTo NextURL
'              If the URL ends with a > from being enclosed in darts, strip that > off
               If Right(strURL, 1) = ">" Then strURL = Left(strURL, Len(strURL) - 1)
'              The URL to activate to accept must contain both of the substrings in the IF statement
               If InStr(1, strURL, ".com") Then
'                    Activate that link to accept the job
                     RetCode = ShellExecute(0, "Open", strURL)
                     Set InspectMail = Nothing
                     Set Reg1 = Nothing
                     Set AllMatches = Nothing
                     Set M = Nothing
                     Exit Sub
               End If

NextURL:
   Next

End If

Set InspectMail = Nothing
Set Reg1 = Nothing
Set AllMatches = Nothing
Set M = Nothing

End Sub

特别感谢 niton 在构成本问题基础的其他问题上的耐心和帮助.他引导我找到解决方案.

Special thanks to niton for his patience and assistance on other questions that formed the basis for this one. He led me to the solution.

附录: 另一个在别处协助我的人提出了一些值得注意的事情,因为我认为她做对了.我正在通过 IMAP 访问使用 Gmail 来下载我的邮件.似乎正在发生的是,一旦将标头信息填充到 MailItem 对象中,就会立即触发 Outlook 规则.该对象的其余成员,包括 .Body,似乎在幕后异步填充.脚本中的处理速度与填充处理速度的对比可能导致脚本使用标头信息触发并在 Outlook 本身填充 .Body 之前访问它的点.有趣的是,当这种情况发生时,并且在找到此解决方案之前的大部分时间里,.Body 不被认为是 NULL.IsNull 测试从未通过,但打印时的内容没有任何内容,因为我用作分隔符的两个管道字符之间绝对没有内容.什么是没有任何字符"但也不是 NULL?

Addendum: Another individual assisting me elsewhere brought up something that deserves noting here, as I think she's got it right. I am using Gmail via IMAP access to download my messages. What appears to be happening is that once the header information is populated into the MailItem object, the Outlook Rule is immediately being triggered. The rest of the members of that object, including .Body, appear to be being populated asynchronously behind the scenes. The speed of processing in your script versus the speed of population processing can lead to situations where the script is triggered with the header information and gets to the point where it accesses the .Body before it's been populated by Outlook itself. What's interesting is when this occurred, and that was most of the time until this solution was found, .Body was not considered to be NULL. The IsNull test never passed, but the content when printed was nothing, as in absolutely nothing between the two pipe characters I used as delimiters. What is "nothing that takes up any characters" but that also is not NULL?

显然,通过的整个 MailItem 不会通过Is Nothing"测试,而且我不认为用Is Nothing"测试对象的单个成员.

Clearly the whole MailItem passed would not pass the "Is Nothing" test, and I would not think to test an individual member of an object with "Is Nothing."

就我自己而言,我认为这是错误的.在将 MailItem 对象移交以进行脚本处理之前,逻辑上假设可以预填充的该对象的所有成员都将在移交之前由 Outlook 进行预填充.它似乎不是那样发生的,这是在我的机器上的 Outlook 2010 和另一台机器上的 Outlook 2016 下.如果您得到一个尚未填充的成员,它应该始终具有 NULL 值,因为这应该是填充过程发生之前所有内容的初始化.

For myself, I consider this to be buggy. Before a MailItem object is ever handed off for script processing it would be the logical presumption that all Members of that object that can be prepopulated will be prepopulated by Outlook before the handoff. It just doesn't appear to be happening that way, and this is under Outlook 2010 on my machine and Outlook 2016 on another. If you get a member that has not yet been populated it should always have the NULL value, as that should be what everything is initialized to prior to the population process taking place.

这篇关于为什么这个正则表达式测试对于应该是相同的正文文本给出不同的结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆