user5544
user5544

Reputation: 171

weird powershell behaviour with a string parameter and a script file

I have a powershell script file which is as follows

param(
[parameter(Mandatory = $true)]
[string] $db_server,
[parameter (Mandatory = $true)]
[string[]] $db_server_list

)

write-output "My DB server is $db_server"
foreach ($list in $db_server_list)
{
    write-output $list
}

Let us assume the file is saved as script1.ps1

On my development laptop, I can run this from visual studio code without any issues.

.\script1.ps1 -db_Server 'my_db_server,999' -db_server_list ("server1,5694","server2,7788")

It runs fine, the value of db_Server is as specified that is my_db_server,999 and i am able to loop through the db_Server_list without loosing the comma which is the port number.

I am calling the file from an external orchestration program, and to do so. I need to run

powershell.exe  .\script1.ps1 -db_Server 'my_db_server,999' -db_server_list ("server1,5694","server2,7788")

And all of a sudden i get errors.

Cannot process argument transformation on parameter 'db_server'. cannott convert value to type System.string. I do not want db_server to be an array even though it has a comma, I need it back as a single string as I used this for a connection string, and if the value after the comma is stripped off, it will break my script.

Please note that this only happens when i call powershell.exe scriptfile.ps1. Running from VS code doesnt result in such errors.

Thanks all.

I have ran it again, its thesame issue. enter image description here

The reason why I need to add powershell.exe is because I am calling the script from an ansible playbook.

Upvotes: 1

Views: 281

Answers (1)

mklement0
mklement0

Reputation: 440471

Note:

  • Ansible also offers the ansible.windows.win_shell module, which uses a shell to process the specified command line, and that shell is PowerShell.

    • If you use this method, you can therefore use your original PowerShell command as-is (note that I've removed the unnecessary (...) around the array passed to -db_server_list and have switched to single-quoting):

      .\script1.ps1 -db_Server 'my_db_server,999' -db_server_list 'server1,5694', 'server2,7788'
      
  • By contrast, if you use ansible.windows.win_command, no shell is involved and you must indeed call (Windows) PowerShell's CLI, powershell.exe, explicitly, as shown below.


Note:

  • The command below is meant to be run from outside PowerShell and only works there[1]; from inside PowerShell, you wouldn't need to call powershell.exe to begin with, but if you did, you'd either have to enclose everything after -c in "..." in this case (which would also work from outside PowerShell) or, from inside PowerShell only, in { ... } - but note that neither approach is a valid test for whether a given a command line will work when called from OUTSIDE PowerShell.

  • If you were to call from cmd.exe, it is generally preferable to enclose the entire argument list passed to -c (-command) in "...", so as to prevent inadvertent interpretation of special characters such as & by cmd.exe up front. This is not necessary in shell-free invocation scenarios, such as with ansible.windows.win_command or from a scheduled task, for instance.

  • Either way, if you want " characters to be seen by PowerShell's -c parameter as part of the command to (ultimately) execute, you must escape them as \" - unescaped " characters are stripped during command-line parsing, which explains why your attempt didn't work: -db_server_list ("server1,5694","server2,7788"), when passed from outside PowerShell, is ultimately seen as
    -db_server_list (server1,5694,server2,7788), which is broken syntax.

  • By contrast, ' characters need no escaping, and switching to using '...' arguments exclusively offers the simplest solution in your case.

powershell.exe -c .\script1.ps1 -db_Server 'my_db_server,999' -db_server_list 'server1,5694', 'server2,7788'

[1] The reason it doesn't work from PowerShell is that the calling PowerShell session interprets the '...' strings, and in this case passes their content unquoted, because the content happens not to contain space characters.

[2] Note that pwsh, the PowerShell (Core) 7+ CLI now defaults to -File instead. See this answer for details on how arguments passed to -c (-Command) are parsed, juxtaposed with -f (-File) arguments, and when to use which parameter.

Upvotes: 2

Related Questions