【问题标题】:Powershell calls another PS1 in loop finishes after first foreach loop run completes在第一次 foreach 循环运行完成后,Powershell 在循环中调用另一个 PS1
【发布时间】:2020-04-01 03:34:03
【问题描述】:

我有 2 个 Powershell 脚本,一个是主脚本 (ServerInfo.ps1),另一个是用作包装器的辅助脚本,在循环中启动第一个脚本,由于查询,该脚本将在每个循环上使用不同的凭据被制作到不同的 AD 域/森林,每个域需要不同的域信用。

如果我从各个域中的机器手动和本地运行主脚本并根据需要运行(从远程机器获取详细信息并导出到 csv),则主脚本在单独运行时运行良好

以下是 Wrapper 脚本(出于安全原因更改了域名示例)。

# This is a Wrapper Script for ServerInfo.ps1
$username = Read-Host -Prompt 'Enter User Account to be used - Do not specify domain'
$Password = Read-Host -Prompt 'Input User Password - NOTE must be the same on all domains' -AsSecureString
$domains = "d1.contoso.com","d2.contoso.com","dev.contosodev1.com","test.contosotest1.com"
$Arguments = "-file c:\serverinfo\ServerInfo.ps1", "-ServerType 'DCs'"

ForEach ($domain in $domains) {
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "$domain\$username", $Password
Start-Process powershell.exe -Credential $credential -NoNewWindow -ArgumentList $Arguments -WorkingDirectory 'c:\Serverinfo\' -Wait
}

具体而言,这将用于查询具有在每个域上都相同的提升权限帐户的域控制器,因为在成员计算机上使用的帐户在域控制器上没有内置管理员或 AD(域/企业管理员)级别权限.目的也是从域成员运行脚本,而不是在 DC 上本地运行。

由于主脚本 (serverinfo.ps1) 超过 1000 行代码,我将简单地说,通过传递参数“-ServerType DCS”的包装器,ServerInfo.ps1 最初从相应的 AD 中获取所有域控制器名称帐户所属的域,并执行每个 DC 的 WMI 和注册表查询等操作,将输出导出到 CSV 文件。

对于第一个域,它运行良好,没有任何问题,并且 ServerInfo.ps1 脚本可以查询第一个域中的每个 DC,但随后两个 PowerShell 脚本都关闭/停止运行,而不会继续运行到包装器中的第二个域又名循环,一旦第一个域完成,“foreach ($Domain in $Domains)”循环就不起作用了。

由于我在包装器中没有看到任何脚本错误,并且 ServerInfo.Ps1 中没有退出或其他取消/完成命令,我不知道为什么包装器没有按预期工作。

【问题讨论】:

    标签: powershell loops foreach wrapper


    【解决方案1】:

    对于第一个域,它运行良好,没有任何问题,并且 ServerInfo.ps1 脚本首先会查询每个 DC 域,但随后两个 PowerShell 脚本在没有它的情况下关闭/停止运行 继续到包装器循环中的第二个域,即“foreach” ($Domain in $Domains)" 循环在第一个域中不起作用 完成。

    我很确定您的循环可以正常工作。只需在该循环中插入一个Write-Host "Iteration for domain: $domain",您就会看到它确实遍历了所有域。

    我更关心您调用其他脚本的方式。使用Start-Process -Credential,该进程将在提供的用户的用户空间中执行。在您的方案中,如果您想在所有域的任何域计算机上运行它,这将需要域之间的任何信任关系。你有什么? 如果没有,您必须以某种安全的方式将凭据传递给被调用的脚本,以便在使用远程控制 cmdlet 时进行身份验证。

    【讨论】:

    • 关于您的查询:在您的场景中,如果您想在所有域的任何域计算机上运行它,这将需要您的域之间的任何信任关系。你有什么?是的,我们确实在大多数森林中都有信任,所以这肯定不会成为问题(我们在 Prod 森林中有 6 个域,我将从 Prod 成员计算机运行它并在我的 prod 普通帐户下启动包装器与成员计算机相同的域,查询所有 Prod 域 DC,还查询单独的测试和开发林域 DC。
    • 我还接受了在循环中添加写入主机以报告正在查询的域的建议,并且当前正在运行查询,但我知道从所花费的时间长度来看,它只会完成第一个域而不查询其他域(第一个域在国际上由大约 40 个 DC 组成,因此完成第一个域大约需要 1 小时,然后脚本停止,而我预计还需要 3 个多小时才能完成完成所有域)
    • 脚本刚刚完成,在它按照我的预期运行通过第一个域之后,虽然循环中的 write-host 显示它确实循环遍历所有域但我没有明显的错误输出以识别似乎没有针对其他域实际运行 powershell 脚本的内容。我想我会在这里休息一下,通过在针对另一个域的循环外运行命令来进一步调试它,看看我得到了什么错误
    • 抓取了 $error 输出... Start-Process :由于以下错误,无法运行此命令:登录失败:您登录的计算机受到身份验证防火墙的保护。不允许指定的帐户对机器进行身份验证。在 line:11 char:1 + Start-Process powershell.exe -Credential $credential -NoNewWindow -Wo ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException + FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
    • 这看起来是我来自其他域/林的 $credential 帐户没有适当的访问权限来登录我正在运行脚本的计算机,我从错误中假设,所以我我想我又回到了如何使用每个域的备用帐户来做到这一点
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-19
    • 1970-01-01
    • 2016-08-11
    • 2021-09-15
    • 1970-01-01
    • 2019-03-25
    • 1970-01-01
    相关资源
    最近更新 更多