从.bat文件启动带多行参数的PowerShell脚本遇故障
问题场景
我需要通过BAT文件启动一个带复杂参数的PowerShell脚本,当前单行命令可以正常运行,但可读性极差且后续参数会增加,希望拆分为多行写法。
原可用单行命令
cmd.exe /C pwsh.exe -Command "& {C:\temp\test.ps1 -ForceFullSync -AzureUserFilterOverride { $users | Where-Object { ($_.assignedLicenses.Count -ge 1) -and ($_.userPrincipalName -match 'domain\.com') } } -CompanyId bb8083d14755f910291fe0e8036d43ea -ManageObjects Contact -AzureUserPropertyList @(@{ msProp = 'accountEnabled'; mappedProp = 'active' }, @{ msProp = 'businessPhones'; mappedProp = 'phone' }, @{ msProp = 'givenName'; mappedProp = 'first_name' }, @{ msProp = 'mail'; mappedProp = 'email' }, @{ msProp = 'mobilePhone'; mappedProp = 'mobile_phone' }, @{ msProp = 'onPremisesImmutableId'; mappedProp = 'u_correlation_id' }, @{ msProp = 'surname'; mappedProp = 'last_name' }, @{ msProp = 'userPrincipalName'; mappedProp = 'user_name' }, @{ msProp = 'assignedLicenses'; mappedProp = '' }) -SecretId 120953 -AzureAdTenantDomain domain.onmicrosoft.com -ServiceNowBaseUri 'https://testinstance.service-now.com' -IdentityProviderSysId '5ffa40e4975a391077dd7a76f053afbf' -LogPath C:\temp\domain\log.txt -Verbose; Exit $LASTEXITCODE }"
第一次多行尝试(报错)
尝试用PowerShell的`作为续行符,写法如下:
cmd.exe /C pwsh.exe -Command "& { C:\temp\test.ps1 ` -ForceFullSync ` -AzureUserFilterOverride { `$users | Where-Object { ($_.assignedLicenses.Count -ge 1) -and ($_.userPrincipalName -match 'domain\.com') } } ` -CompanyId bb8083d14755f910291fe0e8036d43ea ` -ManageObjects Contact ` -AzureUserPropertyList @( @{ msProp = 'accountEnabled'; mappedProp = 'active' }, @{ msProp = 'businessPhones'; mappedProp = 'phone' }, @{ msProp = 'givenName'; mappedProp = 'first_name' }, @{ msProp = 'mail'; mappedProp = 'email' }, @{ msProp = 'mobilePhone'; mappedProp = 'mobile_phone' }, @{ msProp = 'onPremisesImmutableId'; mappedProp = 'u_correlation_id' }, @{ msProp = 'surname'; mappedProp = 'last_name' }, @{ msProp = 'userPrincipalName'; mappedProp = 'user_name' }, @{ msProp = 'assignedLicenses'; mappedProp = '' } ) ` -SecretId 120953 ` -AzureAdTenantDomain domain.onmicrosoft.com ` -ServiceNowBaseUri 'https://testinstance.service-now.com' ` -IdentityProviderSysId '5ffa40e4975a391077dd7a76f053afbf' ` -LogPath C:\temp\domain\log.txt ` -Verbose; ` Exit `$LASTEXITCODE }"
运行后错误提示:
c:\temp>test.bat
c:\temp>cmd.exe /C pwsh.exe -Command "& {C:\temp\test.ps1 `
c:\temp>-ForceFullSync ` '-ForceFullSync' is not recognized as an internal or external command, operable program or batch file.
c:\temp>-AzureUserFilterOverride {
$users | Where-Object { ($_.assignedLicenses.Count -ge 1) -and ($_.userPrincipalName -match 'domain\.com') } }'-AzureUserFilterOverride' is not recognized as an internal or external command, operable program or batch file.c:\temp>
第二次多行尝试(报错)
改用CMD的^作为续行符,写法如下:
cmd.exe /C pwsh.exe -Command "& { C:\temp\test.ps1 ^ -ForceFullSync ^ -AzureUserFilterOverride { `$users | Where-Object { ($_.assignedLicenses.Count -ge 1) -and ($_.userPrincipalName -match 'domain\.com') } } ^ -CompanyId bb8083d14755f910291fe0e8036d43ea ^ -ManageObjects Contact ^ -AzureUserPropertyList @( @{ msProp = 'accountEnabled'; mappedProp = 'active' }, @{ msProp = 'businessPhones'; mappedProp = 'phone' }, @{ msProp = 'givenName'; mappedProp = 'first_name' }, @{ msProp = 'mail'; mappedProp = 'email' }, @{ msProp = 'mobilePhone'; mappedProp = 'mobile_phone' }, @{ msProp = 'onPremisesImmutableId'; mappedProp = 'u_correlation_id' }, @{ msProp = 'surname'; mappedProp = 'last_name' }, @{ msProp = 'userPrincipalName'; mappedProp = 'user_name' }, @{ msProp = 'assignedLicenses'; mappedProp = '' } ) ^ -SecretId 120953 ^ -AzureAdTenantDomain domain.onmicrosoft.com ^ -ServiceNowBaseUri 'https://testinstance.service-now.com' ^ -IdentityProviderSysId '5ffa40e4975a391077dd7a76f053afbf' ^ -LogPath C:\temp\domain\log.txt ^ -Verbose; ^ Exit `$LASTEXITCODE }"
运行后错误提示:
c:\temp>test.bat
c:\temp>cmd.exe /C pwsh.exe -Command "& {
c:\temp>C:\temp\test.ps1 -ForceFullSync
-AzureUserFilterOverride { `$users | Where-Object { ($.assignedLicenses.Count -ge 1) -and ($.userPrincipalName -match 'domain.com') } } -CompanyId bb8083d14755f910291fe0e8036d43ea
-ManageObjects Contact -AzureUserPropertyList @( 'Where-Object' is not recognized as an internal or external command, operable program or batch file.c:\temp>
解决方案
问题核心是CMD和PowerShell的转义、续行规则冲突,以下是正确的多行BAT写法:
cmd.exe /C pwsh.exe -Command ^"& { ^ C:\temp\test.ps1 ^ -ForceFullSync ^ -AzureUserFilterOverride { ^`$users | Where-Object { ($_.assignedLicenses.Count -ge 1) -and ($_.userPrincipalName -match 'domain\.com') } } ^ -CompanyId bb8083d14755f910291fe0e8036d43ea ^ -ManageObjects Contact ^ -AzureUserPropertyList @( ^ @{ msProp = 'accountEnabled'; mappedProp = 'active' }, ^ @{ msProp = 'businessPhones'; mappedProp = 'phone' }, ^ @{ msProp = 'givenName'; mappedProp = 'first_name' }, ^ @{ msProp = 'mail'; mappedProp = 'email' }, ^ @{ msProp = 'mobilePhone'; mappedProp = 'mobile_phone' }, ^ @{ msProp = 'onPremisesImmutableId'; mappedProp = 'u_correlation_id' }, ^ @{ msProp = 'surname'; mappedProp = 'last_name' }, ^ @{ msProp = 'userPrincipalName'; mappedProp = 'user_name' }, ^ @{ msProp = 'assignedLicenses'; mappedProp = '' } ^ ) ^ -SecretId 120953 ^ -AzureAdTenantDomain domain.onmicrosoft.com ^ -ServiceNowBaseUri 'https://testinstance.service-now.com' ^ -IdentityProviderSysId '5ffa40e4975a391077dd7a76f053afbf' ^ -LogPath C:\temp\domain\log.txt ^ -Verbose; ^ Exit ^`$LASTEXITCODE ^ }^"
关键调整说明
- CMD续行符规则:所有需要续行的行尾必须用
^,且^是该行最后一个字符,后面不能有空格、换行或其他字符,确保CMD将多行合并为一行传递给PowerShell。 - PowerShell转义字符处理:PowerShell中需要的
(用于转义$),在BAT文件中要写成`,因为CMD会解析`作为转义符,最终传递给PowerShell的是单个。 - 引号转义:包裹PowerShell命令的双引号前要加
^(即^"),避免CMD提前解析引号内部的内容,导致命令被拆分。 - 脚本块内部续行:PowerShell的数组、脚本块内部的换行,同样需要用CMD的
^续行,确保整个结构被完整传递,不会被CMD当作独立命令执行。
内容的提问来源于stack exchange,提问作者StackExchangeGuy

