首页 > 解决方案 > 从 powershell 超时 MS Access ComObject

问题描述

我有一个 powershell 脚本,它创建一个 MS Access ComObject 并使用它在 MS Access 数据库中运行一个宏,如下所示:

$AccessDb= 新对象 -ComObject Access.Application

try{ 

 foreach($file in $Files)
  { 
    ...
    $AccessDb.DoCmd.RunMacro('mcrScr')
    ...
 }

}
catch { ... }

问题是当出现运行时错误时,MS Access 会在交互式窗口或对话框中抛出错误,这会导致 powershell 挂起;只是等待窗口关闭,因此其他 .mdb 文件的宏不会运行。我一直在尝试在线文章中的选项来超时我的这段代码 $AccessDb.DoCmd.RunMacro('mcrScr'),如果它运行超过 x 秒数。我使用了作业、运行空间和 [system.diagnostics.stopwatch],但没有成功。有没有更好的方法来做到这一点。我有点没有选择了。

编辑:@Paul,作为对您的评论的回应,我正在添加我如何使用运行空间来解决问题。

function Script-Timeout {
    param([scriptblock]$Command,[int]$Timeout)

    $Runspace = [runspacefactory]::CreateRunspace()
    $Runspace.Open()

    $PS = [powershell]::Create().AddScript($Command)
    $PS.Runspace = $Runspace

    $chk = $PS.BeginInvoke()
    if($chk.AsyncWaitHandle.WaitOne($Timeout))
    {
     $PS.EndInvoke($chk)
    }
    else
    {
       
       throw "Command taking too long to run. Timeout exceeded." 
       $PS.EndInvoke($chk)
    }


}

然后在运行 MS Acess 宏的脚本部分中使用 Script-Timeout 函数,如下所示:

Try{
    forEach($mdbfile in Files)
    {
        ...
        Script-Timeout -Command {
             $AccessDb= New-Object -ComObject Access.Application
            $AccessDb.OpenCurrentDatabase($mdbfile)

            $AccessDb.DoCmd.RunMacro('mcrUpdate') 

            $AccessDb.CloseCurrentDatabase() 
            } -Timeout 20
        ...    
     }
 }
 catch
 {
  #catch exception
 }

我在 VBA 中人为地创建了一个运行时错误,它会引发一个错误对话框。这样,如果脚本的 RunMacro 部分运行,它将挂起 powershell。这是我希望运行空间在 x 秒后从 powershell 超时运行宏的地方。运行空间的问题是 MS Access 宏根本没有运行。在 powershell 调试模式下,我看到脚本超时函数的 if 块总是成功执行,无论是否存在人为运行时错误

标签: powershellms-accessvba

解决方案


推荐阅读