views:

888

answers:

4
+2  Q: 

subprocess.Popen

I am running an msi installer in silent mode and caching logs in the specific file. the following is the command i need to execute.

C:\Program Files\ My Installer\Setup.exe /s /v "/qn /lv %TEMP%\log_silent.log"

I used:

subprocess.Popen(['C:\Program Files\ My Installer\Setup.exe', '/s /v "/qn /lv %TEMP%\log_silent.log"'],stdout=subprocess.PIPE).communicate()[0]

to execute the command however it does not recognise the operation and gives error regarding wrong option selected. I have cross verified and found that the command only works this way.

Thanks and regards,

+1  A: 

The problem is that you effectively supply Setup.exe with only one argument. Don't think in terms of the shell, the string you hand over as an argument does not get splitted on spaces anymore, that's your duty!

So, if you are absolutely sure that "/qn /lv %TEMP%\log_silent.log" should be one argument, then use this:

subprocess.Popen(['C:\Program Files\ My Installer\Setup.exe', '/s', '/v', '/qn /lv %TEMP%\log_silent.log'],stdout=subprocess.PIPE).communicate()[0]

Otherwise (I guess this one will be correct), use this:

subprocess.Popen(['C:\Program Files\ My Installer\Setup.exe', '/s', '/v', '/qn', '/lv', '%TEMP%\log_silent.log'],stdout=subprocess.PIPE).communicate()[0]
paprika
having each argument which is seperated by space helped.
Neer
Quotes are needed. Dont know why. Even switch v is repeated. I
Neer
A: 

Try putting each argument in its own string (reformatted for readability):

cmd = ['C:\Program Files\ My Installer\Setup.exe',
       '/s',
       '/v',
       '"/qn',
       '/lv',
       '%TEMP%\log_silent.log"']

subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]

I have to say though, those double quotes do not look in the right places to me.

Harley
+8  A: 

The problem is very subtle.

You're executing the program directly. It gets:

argv[0] = "C:\Program Files\ My Installer\Setup.exe"

argv[1] = /s /v "/qn /lv %TEMP%\log_silent.log"

Whereas it should be:

argv[1] = "/s"

argv[2] = "/v"

argv[3] = "/qn"

argv[4] = "/lv %TEMP%\log_silent.log"

In other words, it should receive 5 arguments, not 2 arguments.

Also, %TEMP% is directly unknown to the program!

There are 2 ways to fix this problem:

  1. Calling the shell.

    p = subprocess.Popen('C:\Program Files\ My Installer\Setup.exe /s /v "/qn /lv %TEMP%\log_silent.log"', shell=True)

    output = p.communicate()[0]

  2. Directly call program (more safer)

    s = ['C:\Program Files\ My Installer\Setup.exe', '/s /v "/qn /lv %TEMP%\log_silent.log"']

    safes = [os.path.expandvars(p) for p in argument_string]

    p = subprocess.Popen(safes[0], safes[1:])

    output = p.communicate()[0]

kylebrooks
Also, "C:\Program Files\ My Installer\Setup.exe" should be r"C:\Program Files\ My Installer\Setup.exe". The \'s either need to be doubled, or the string needs to be an r"" string.
S.Lott
A: 

You said:

subprocess.Popen(['C:\Program Files\ My Installer\Setup.exe', '/s /v "/qn /lv %TEMP%\log_silent.log"'],stdout=subprocess.PIPE).communicate()[0]

Is the directory name really " My Installer" (with a leading space)?

Also, as a general rule, you should use forward slashes in path specifications. Python should handle them seamlessly (even on Windows) and you avoid any problems with python interpreting backslashes as escape characters.

(for example:

>>> s = 'c:\program files\norton antivirus'
>>> print s
c:\program files
orton antivirus

)

John Fouhy
No leading space.
Neer
...then if your code has a leading space in the path, that's an obvious source of error.
John Fouhy