连续运行VBScript

连续运行VBScript,vbscript,Vbscript,我有一个关于Outlook的规则,它启动一个批处理语句,该语句启动一个VBScript,然后根据发件人和主题标题启动其他VBScript。如果来自同一发件人的两封电子邮件同时进入收件箱,它将正确启动第一个实例。但是,第二个将启动并返回一个错误,说明“权限被拒绝”。我想连续运行每封电子邮件 我已经尝试过睡眠函数和其他限时延迟,但是由于数据的大小,查询时间不一致 这是我一直在使用的基本脚本 Set olApp = CreateObject("Outlook.Application") Set ol

我有一个关于Outlook的规则,它启动一个批处理语句,该语句启动一个VBScript,然后根据发件人和主题标题启动其他VBScript。如果来自同一发件人的两封电子邮件同时进入收件箱,它将正确启动第一个实例。但是,第二个将启动并返回一个错误,说明“权限被拒绝”。我想连续运行每封电子邮件

我已经尝试过睡眠函数和其他限时延迟,但是由于数据的大小,查询时间不一致

这是我一直在使用的基本脚本

Set olApp = CreateObject("Outlook.Application") 
Set olMAPI = olApp.GetNameSpace("MAPI") 
Set oFolder = olMAPI.Folders("FieldFinanceAutomatedReports@xxxxx.com").Folders("Inbox").Folders("Requested Report People")
Set allEmails = oFolder.Items 
Set firstemail = allEmails.GetLast

unreadCount = 0 
For Each email In oFolder.Items 
    If email.Unread = True Then 
        If email.Sender= "Sender_of_email@email.com" Then
            Set objcreate = CreateObject("Scripting.FileSystemObject")
            Set objread = objcreate.OpenTextFile("C:\path_to_script\script.vbs")
            request = objread.ReadAll()
            objread.Close
            Set objread = Nothing
            Execute request
            Set request = Nothing
            Set objcreate = Nothing
        End If
        WScript.Sleep 500

        If email.Sender = "Another_Sender_of_email@email.com" Then
            Set objcreate = CreateObject("Scripting.FileSystemObject")
            Set objread = objcreate.OpenTextFile("C:\path_to_script\another_script.vbs")
            another_request = objread.ReadAll()
            objread.Close
            Set objread = Nothing
            Execute another_request
            Set another_request = Nothing
            Set objcreate = Nothing
        End If
        WScript.Sleep 500

        unreadCount = unreadCount + 1 
    End If 
Next 
我希望每个实例都等待第一个过程完成。

您需要的称为or。本质上,这是一种一次只能由一个进程或线程持有的资源。在VBScript中,您可以通过尝试执行以下操作来实现这一点。第一个这样做的进程获胜,随后的尝试将失败,因为文件已经存在

Set sh  = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")

filename = sh.ExpandEnvironmentStrings("%TEMP%\mutex.txt")

'this will throw an error if the file is already opened
Set f = fso.OpenTextFile(filename, 2, True)
请注意,您需要打开文件进行写入(第二个参数设置为2)。打开它进行读取(第二个参数设置为1)是不够的

在循环中运行该操作,您可以等待另一个进程完成并释放互斥锁

Set sh  = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")

filename = sh.ExpandEnvironmentStrings("%TEMP%\mutex.txt")

On Error Resume Next
Do
    Err.Clear
    Set f = fso.OpenTextFile(filename, 2, True)
    If Err Then WScript.Sleep 100
Loop While Err
On Error Goto 0
确保在脚本离开关键部分(或终止)时删除该文件,否则其他脚本以后可能无法获取互斥体。一种方便的方法是将互斥体作为类实现。这样,即使脚本意外终止,也会自动清理

Class Mutex
    Private f_

    Private Sub Class_Initialize
        Set sh  = CreateObject("WScript.Shell")
        Set fso = CreateObject("Scripting.FileSystemObject")

        filename = sh.ExpandEnvironmentStrings("%TEMP%\mutex.txt")

        On Error Resume Next
        Do
            Err.Clear
            Set f_ = fso.OpenTextFile(filename, 2, True)
            If Err Then WScript.Sleep 100
        Loop While Err
        On Error Goto 0
    End Sub

    Private Sub Class_Terminate
        f_.Close
    End Sub
End Class
在代码中使用
Mutex
类如下:

Set m = New Mutex   'acquire mutex
'...
'critical section goes here
'...
Set m = Nothing     'release mutex

你所需要的叫做手术室。当脚本进入一个关键部分(您不希望在其中并发执行)时,让它运行,并在循环中重复该过程,直到成功为止(不会发生错误)。在关键部分之后删除该文件。这非常有效。谢谢,很好的解释。我很好奇为什么要使用
IsEmpty()
而不是仅仅捕获文件上的锁生成的错误?类似于
如果错误号为0,那么
或者甚至是特定的错误?例如,想知道如果
Err
返回了权限错误会发生什么。不管怎样,这是一个很好的答案+1@Lankymart当文件已打开时,
Err
应该有权限错误(错误70,权限被拒绝)。但你是对的,我应该对睡眠和循环终止使用相同的条件。固定的。如果想要使条件更加具体(以区分不同的错误类型),他们可以检查
Err.Number=70
,而不仅仅是检查是否存在错误。