I need to start a Powershell script from a .bat file and the Powershell script accepts parameters. Today, I run the script from a single line, like this:
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 }"
That works fine, but is difficult to read (and will be getting longer with additional parameters), so I would like to break it by line. I tried the following:
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
}"
But when I run the .bat file, all I get is Notepad opening c:\temp\test.ps1. When I close it, the command shell shows me:
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>
Based on Using multi-line PowerShell commands from cmd.exe I tried replacing the line-ending backticks with the caret character like this:
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
}"
But then the shell said,
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>
I feel like I must be close, but am missing something small.
cmd.exe, so preceding yourpwsh.execommand withcmd.exe /Cseems completely redundant, and potentially problematic. Effectively sending everything as arguments, (to be first passed to another instance of cmd.exe), means that a round of parsing by that interpreter takes place before its resulting strings are then passed topwsh.exe. I would strongly therefore advise that you begin by removing the first eleven characters from your command. You should also be using-Fileinstead of-Command.^and not a GRAVE ACCENT`as it is in pwsh.exe. How about putting the PowerShell code into anInvoke-test.ps1script as @Compo has suggested?cmd.exe /c.