【问题标题】:How do I call Start-Job which depends on a function in the same powershell module as the function calling Start-Job?如何调用 Start-Job,它依赖于与调用 Start-Job 的函数相同的 powershell 模块中的函数?
【发布时间】:2012-03-12 19:59:00
【问题描述】:

我正在编写一些 powershell 以在单个模块中与 AWS API 对话。我编写了一个函数 Get-CloudFormation,它返回 CloudFormation 的状态。我编写了另一个函数 Delete-CloudFormation,它在触发 delete-CF API 请求后,尝试使用我的 Get-CloudFormation 启动一项轮询 CloudFormation 状态的作业。

我在Get-CloudFormation 上调用Export-ModuleMember(但不是Delete-CloudFormation;这是一个私有函数)。 Get-CloudFormation 在模块文件中的定义早于 Delete-CloudFormation

我的Start-Job 电话(在Delete-CloudFormation 内)看起来像:

$job = Start-Job -Name "CloudFormationWaitForDeleteSuccess" -ScriptBlock {
    $status = ""
    $time = 0
    while($status -ne "DELETE_COMPLETE") {
        Write-Verbose ("Checking CloudFormation status")
        $stack = Get-CloudFormation -accessKey $accessKey -secretKey $secretKey -stackName $stackName
        $status = $stack.Status
        Start-Sleep -seconds 10
        $time += 10
    }
    Write-Host "CloudFormation delete-complete after $time seconds $stackName"
}

Delete-CloudFormation 运行时,我得到一个异常:

The term 'Get-CloudFormation' is not recognized as the name of a cmdlet, 
function, script file, or operable program. Check the spelling of the 
name, or if a path was included, verify that the path is correct and try again.
+ CategoryInfo          : ObjectNotFound: (Get-CloudFormation:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

为什么?我该如何解决?

我发现7152090 我认为是相似的,但是用-InitializationScript { Get-CloudFormation } 调用Start-Job 会产生大致相同的错误。

如果我用-InitializationScript { Import-Module ".\awsutils.psm1" } 调用Start-Job,那么. 是我个人资料的文档目录。即使我将一个变量绑定到Start-Job 之外的Get-Location 并像-InitializationScript { Import-Module "$location\awsutils.psm1" } 一样调用它。

【问题讨论】:

    标签: powershell jobs powershell-2.0 powershell-jobs


    【解决方案1】:
    $root = $PSScriptRoot
    
    $initScript = [scriptblock]::Create("Import-Module -Name '$root\Modules\Publish-Assigned_CB_Reports.psm1'")
    
    $job1 = Start-Job -InitializationScript $initScript -ScriptBlock {} -ArgumentList
    

    【讨论】:

    • 您能否为您的答案添加一些解释?仅代码的答案在 SO 上不受欢迎。
    • 这是我寻求的答案,我认为任何有足够知识尝试运行后台作业的人都会看到答案不言自明
    【解决方案2】:

    我最终做的是在调用Start-Job之前设置$env:WhereAmI = Get-Location,然后更改为-InitializationScript { Import-Module "$env:WhereAmI\awsutils.psm1 }。打完Start-Job之后,我打给Remove-Item env:\WhereAmI打扫。

    (我想要一个不需要我在 $PSModulePath 中开发模块的解决方案,因为这样设置源代码控制会更加痛苦。)

    感谢您的回复。

    【讨论】:

      【解决方案3】:

      将模块 awsutils.psm1 移动到 powershell 模块的规范路径中:

      $env:userprofile\documents\WindowsPowerShell\Modules\awsutils"
      

      然后像这样初始化start-job

      -InitializationScript { Import-Module awsutils }
      

      使用我的自定义模块进行测试并且开始工作。

      如果你不想移动你的 psm1,也可以试试:

      -InizializationScript { import-module -name c:\yourpath\yourmodulefolder\ }
      

      其中yourmoduleforder 仅包含一个 psm1 文件。

      【讨论】:

      • 我猜如果 OP 想要更加动态,主脚本可以将模块复制到 C:\Windows...\Powershell 模块目录中,这样它就可以使用 Import-Module 而没有完整路径.以后可以删了……呵呵
      【解决方案4】:

      后台作业是自主的事情。它们不是一个单独的线程共享资源,它们实际上是在一个全新的 PowerShell.exe 进程中运行的。所以我认为你需要在你的脚本块中使用Import-Module 来让你的模块成员在那里可用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-02
        • 2019-10-20
        相关资源
        最近更新 更多