You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过ARM模板自定义脚本扩展调用PowerShell执行多个cmd文件

实现PowerShell DSC脚本调用多个CMD文件(适配ARM自定义脚本扩展)

我来帮你调整这个PowerShell DSC脚本,实现调用多个CMD文件的功能,同时适配ARM自定义脚本扩展的触发场景。首先你原来脚本里的Invoke-Item File 'sr...'写法是不对的,我们可以用DSC的Script资源来实现(这是推荐方式,支持依赖管理和重复执行检查),或者直接用Start-Process执行CMD脚本。

方法一:用DSC Script资源(推荐,支持依赖与幂等性)

这种方式能确保CMD脚本在IIS、ASP.NET等组件安装完成后再执行,还能避免重复执行(通过检查标记文件):

Configuration IIS {
    Node ("localhost") {
        # 安装IIS角色
        WindowsFeature IIS {
            Ensure = "Present"
            Name = "Web-Server"
        }

        # 安装ASP.NET 4.5,依赖IIS安装完成
        WindowsFeature ASP {
            Ensure = "Present"
            Name = "Web-Asp-Net45"
            DependsOn = "[WindowsFeature]IIS"
        }

        # 安装IIS管理控制台
        WindowsFeature WebServerManagementConsole {
            Name = "Web-Mgmt-Console"
            Ensure = "Present"
            DependsOn = "[WindowsFeature]IIS"
        }

        # 执行第一个CMD脚本
        Script RunFirstCmd {
            GetScript = { @{ Result = "FirstCmdCompleted" } }
            TestScript = { 
                # 检查标记文件,判断是否已经执行过
                $markerFile = "C:\DSCLogs\FirstCmd_Done.txt"
                return Test-Path $markerFile
            }
            SetScript = {
                # 替换成你的CMD文件实际路径
                $cmdPath = "C:\CustomScripts\FirstSetup.cmd"
                
                # 执行CMD,等待完成并捕获退出码
                $process = Start-Process -FilePath "cmd.exe" -ArgumentList "/c `"$cmdPath`"" -Wait -PassThru -NoNewWindow
                
                # 非0退出码则抛出错误,终止DSC配置
                if ($process.ExitCode -ne 0) {
                    throw "First CMD script failed with exit code $($process.ExitCode)"
                }

                # 创建标记文件,避免重复执行
                New-Item -Path "C:\DSCLogs\FirstCmd_Done.txt" -ItemType File -Force | Out-Null
            }
            # 依赖所有Windows功能安装完成
            DependsOn = "[WindowsFeature]ASP", "[WindowsFeature]WebServerManagementConsole"
        }

        # 执行第二个CMD脚本,依赖第一个完成
        Script RunSecondCmd {
            GetScript = { @{ Result = "SecondCmdCompleted" } }
            TestScript = { 
                $markerFile = "C:\DSCLogs\SecondCmd_Done.txt"
                return Test-Path $markerFile
            }
            SetScript = {
                $cmdPath = "C:\CustomScripts\SecondSetup.cmd"
                $process = Start-Process -FilePath "cmd.exe" -ArgumentList "/c `"$cmdPath`"" -Wait -PassThru -NoNewWindow
                
                if ($process.ExitCode -ne 0) {
                    throw "Second CMD script failed with exit code $($process.ExitCode)"
                }

                New-Item -Path "C:\DSCLogs\SecondCmd_Done.txt" -ItemType File -Force | Out-Null
            }
            DependsOn = "[Script]RunFirstCmd"
        }
    }
}

方法二:批量执行CMD脚本(适合简单场景)

如果不需要严格的顺序检查,也可以批量遍历CMD文件列表执行,同样放在Script资源里确保依赖:

Configuration IIS {
    Node ("localhost") {
        # 保留原有的WindowsFeature配置
        WindowsFeature IIS {
            Ensure = "Present"
            Name = "Web-Server"
        }

        WindowsFeature ASP {
            Ensure = "Present"
            Name = "Web-Asp-Net45"
            DependsOn = "[WindowsFeature]IIS"
        }

        WindowsFeature WebServerManagementConsole {
            Name = "Web-Mgmt-Console"
            Ensure = "Present"
            DependsOn = "[WindowsFeature]IIS"
        }

        # 批量执行所有CMD脚本
        Script RunAllCmds {
            GetScript = { @{ Result = "AllCmdsExecuted" } }
            TestScript = { 
                # 这里可以检查所有标记文件是否存在,或者直接返回$false每次都执行
                $allMarkersExist = @(
                    "C:\DSCLogs\FirstCmd_Done.txt",
                    "C:\DSCLogs\SecondCmd_Done.txt"
                ) | ForEach-Object { Test-Path $_ } | Where-Object { $_ -eq $false }
                
                return $allMarkersExist.Count -eq 0
            }
            SetScript = {
                # 定义要执行的CMD文件列表
                $cmdFiles = @(
                    "C:\CustomScripts\FirstSetup.cmd",
                    "C:\CustomScripts\SecondSetup.cmd",
                    "C:\CustomScripts\ThirdSetup.cmd"
                )

                foreach ($cmd in $cmdFiles) {
                    Write-Host "Starting execution of: $cmd"
                    $logFile = "C:\DSCLogs\$(Split-Path $cmd -Leaf)_Log.txt"
                    
                    # 执行并将输出写入日志文件
                    $process = Start-Process -FilePath "cmd.exe" -ArgumentList "/c `"$cmd`"" -Wait -PassThru -NoNewWindow `
                        -RedirectStandardOutput $logFile -RedirectStandardError $logFile

                    if ($process.ExitCode -ne 0) {
                        throw "Script $cmd failed! Check log at $logFile"
                    }

                    # 创建对应标记文件
                    $markerFile = "C:\DSCLogs\$(Split-Path $cmd -Leaf)_Done.txt"
                    New-Item -Path $markerFile -ItemType File -Force | Out-Null
                    Write-Host "Successfully executed: $cmd"
                }
            }
            DependsOn = "[WindowsFeature]ASP", "[WindowsFeature]WebServerManagementConsole"
        }
    }
}

适配ARM自定义脚本扩展的关键注意点

  • CMD文件路径:如果你的CMD文件是通过ARM模板的fileUris参数上传的,默认会被下载到C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\<版本号>\Downloads\<编号>目录下,你可以在ARM模板中指定commandToExecute先把文件复制到固定路径(比如C:\CustomScripts),或者直接使用这个默认路径。
  • 权限:自定义脚本扩展以系统权限运行,确保CMD文件和操作的目标资源有足够的权限,避免“访问被拒绝”的问题。
  • 日志排查:建议给每个CMD脚本添加日志输出,或者在PowerShell中重定向输出到日志文件,方便后续排查执行问题。

内容的提问来源于stack exchange,提问作者Helay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:30:24