Looks like you have a nice and complex command to run which makes these things really difficult but luckily you are running Ansible 2.4 where the escaping rules are now aligned to Microsoft standard
https://msdn.microsoft.com/en-us/library/17w5ykft(v=vs.85).aspx. We've created a very basic executable that you are more than welcome to use to test how your arguments look when being passed to an application from win_command. To test it out you can run the following playbook.
- hosts: windows
gather_facts: no
vars:
app_url: http://google.com
tasks:
- name: download argv executable
win_get_url:
url: https://s3.amazonaws.com/ansible-ci-files/test/integration/roles/test_win_module_utils/PrintArgv.exe
dest: C:\temp\PrintArgv.exe
- name: output args found
win_command: C:\temp\PrintArgv.exe set config -section:system.applicationHost/sites /+\"[name='{{ app_url }}'].logFile.customFields.[logFieldName='X-Forwarded-For',sourceName='X-Forwarded-For',sourceType='RequestHeader']\" /commit:apphost
register: output
- debug:
var: output.stdout_lines This tests your example and it results in
ok: [SERVER2016.domain.local] => {
"output.stdout_lines": [
"set",
"config",
"-section:system.applicationHost/sites",
"/+\"[name='http://google.com'].logFile.customFields.[logFieldName='X-Forwarded-For',sourceName='X-Forwarded-For',sourceType='RequestHeader']\"",
"/commit:apphost"
]
} Once you take into account basic JSON escaping rules (\\ becomes \ and \" becomes "), you can see the following arguments in your example are;
Argv[0] - set
Argv[1] - config
Argv[2] - -section:system.applicationHost/sites
Argv[3] - /+"[name='
http://google.com'].logFile.customFields.[logFieldName='X-Forwarded-For',sourceName='X-Forwarded-For',sourceType='RequestHeader']"
Argv[4] - /commit:apphost
While this is what your raw command looks like, if when you saw raw command you mean this is what you run in cmd.exe and it works the double quotes in Argv[3] are probably what's causing the issues. When reading the rules for command-line arguments, 2 rules that pertain to double quotes are;
* A string surrounded by double quotation marks ("
string") is
interpreted as a single argument, regardless of white space contained
within. A quoted string can be embedded in an argument.
* A double quotation mark preceded by a backslash (\") is interpreted as a literal double quotation mark character (").
This means that when you just have " without a preceding \, the parser will interpret that as the start of a quoted argument and ignore whitespaces as an argument delimiter until another double quote is found. If you preceed the double quote with \, it will use the double quote as an argument char and not start/end the whitespace escaping. This means in your example, the " char is being passed into the appcmd.exe (we can see this in the PrintArgv.exe test) as an argument whereas your raw command indicates it is just being used as a whitespace switch. I would try the following command in Ansible and see how that goes (I changed \" in the complex arg to just " so that the " literal isn't passed into the application).
- win_command: C:\temp\PrintArgv.exe set config -section:system.applicationHost/sites /+"[name='{{ app_url }}'].logFile.customFields.[logFieldName='X-Forwarded-For',sourceName='X-Forwarded-For',sourceType='RequestHeader']" /commit:apphost
When testing that with the PrintArgv.exe test I can see the following arguments are being passed into the application
TASK [debug] ************************************************************************************************************************************************
ok: [SERVER2016.domain.local] => {
"output.stdout_lines": [
"set",
"config",
"-section:system.applicationHost/sites",
"/+[name='http://google.com'].logFile.customFields.[logFieldName='X-Forwarded-For',sourceName='X-Forwarded-For',sourceType='RequestHeader']",
"/commit:apphost"
]
} Once again, escaping the JSON escaping rules we can see the following arguments are being passed into the application;
Argv[0] - set
Argv[1] - config
Argv[2] - -section:system.applicationHost/sites
Argv[3] - /+[name='
http://google.com'].logFile.customFields.[logFieldName='X-Forwarded-For',sourceName='X-Forwarded-For',sourceType='RequestHeader']
Argv[4] - /commit:apphost
Also because you don't have any whitespace characters in Argv[3], you probably don't even need the double quotes at all but I'll leave that up to you for testing, it may be prudent to leave them in there depending on what the value for name is.
I honestly don't know the rules for appcmd.exe so I don't really know how it actually expects the argument to be but I'm just going by your raw command example and trying to predict what it is expecting.
Thanks
Jordan