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