سؤال

I need to run diskpart in my python3 script under Windows 7 and capture its output. I run the script in elevated mode; it runs but I can't capture the output and thus can't determine if it was successful. Here's its invocation:

win32api.ShellExecute(0, runas, diskpart, /s C:\TEMP\mapRHD.dp > C:\TEMP\diskpart.out, C:\Python3, 1)

The C:\TEMP\diskpart.out file doesn't get written.

I didn't really think that the redirection "> C:\TEMP\diskpart.out" would work here but I don't know what else to do. Any suggestions?

Thank you.

هل كانت مفيدة؟

المحلول

Redirection with '>' is shell syntax that instructs the shell how to direct the standard output stream of the created process. diskpart doesn't understand it. You can run the command via the shell (whatever COMSPEC is) with the '/c' option. This should work:

import os
import win32api

shell = os.environ['COMSPEC']  # e.g. cmd.exe
command = r'/c diskpart /s C:\TEMP\mapRHD.dp > C:\TEMP\diskpart.out'
win32api.ShellExecute(0, 'runas', shell, command, '', 1)

Edit:

To get the return code from diskpart, it's simpler to restart your script as an elevated process, as above. The script name is in __file__, and run sys.executable. On start, check win32com.shell.shell.IsUserAnAdmin() for elevated privileges. If the process is elevated, run diskpart with output = subprocess.check_output(r'diskpart /s C:\TEMP\mapRHD.dp'). You can post-process and log the output as desired.

If the command fails to execute, an OSError is raised. If diskpart exits with an error, subprocess.CalledProcessError will be raised, which has the returncode as an attribute.

A more complicated approach is to use win32com.shell.shell.ShellExecuteEx, which returns a handle to the new process. By keyword, set fmask = win32com.shell.shellcon.SEE_MASK_NOCLOSEPROCESS, nShow = win32con.SW_SHOWNORMAL (or whichever show level you need), lpVerb = 'runas', lpFile = os.environ['COMSPEC'], and lpParameters = command. You need the value of the hProcess key (the process handle) from the dict it returns.

Then use win32event.WaitForSingleObject to wait for the process to close. To wait indefinitely use win32event.INFINITE. Finally, call win32process.GetExitCodeProcess to get the exit code. As is, I think running via the shell means this code will either be 0 (success) or 1 (fail), but you could maybe get around that by appending command += " & exit /b %%errorlevel%%".

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top