I have a Windows service that runs as mydomain\\userA. I want to be able to run arbitrary .exes from the service. Normally, I use Process.Start() and it works fine, but in s
I have reimplemented Martin Prikryl's answer in Python, which I hope someone finds useful.
I ran into this problem running a subprocess in a Python script. I was using the pythonnet package to run System.Diagnostics.Process as different user. My issue was that the subprocess was not running and I received no stdout or stderr.
# Import .NET objects using pythonnet
from System.Diagnostics import Process
# Use .NET API to run a subprocess using the given executable
# as the target user, in the provided working directory.
process = Process()
process.StartInfo.UseShellExecute = False
process.StartInfo.CreateNoWindow = True
process.StartInfo.LoadUserProfile = True
process.StartInfo.RedirectStandardOutput = True
process.StartInfo.RedirectStandardError = True
process.StartInfo.WorkingDirectory = working_dir
process.StartInfo.Domain = "mydomain"
process.StartInfo.UserName = username.lower().replace("mydomain\\", "")
process.StartInfo.PasswordInClearText = password
process.StartInfo.FileName = executable
process.StartInfo.Arguments = " ".join(args)
# Run the subprocess.
process.Start()
# Read subprocess console output
stdout = process.StandardOutput.ReadToEnd()
stderr = process.StandardError.ReadToEnd()
log.info(f"\n{executable} subprocess stdout:\n\n{stdout}")
log.info(f"{executable} subprocess stderr:\n\n{stderr}")
log.info(f"Done running {executable} as {username}.")
I used Martin Prikryl's answer, but I reimplemented it in Python using the pyWin32 library, which solved my issue.:
import win32api, win32process, win32service, win32security
WINDOW_STATION_ALL_ACCESS = 983935
DESKTOP_RIGHTS_ALL_ACCESS = 983551
SE_WINDOW_OBJECT = 7
DACL_SECURITY_INFORMATION = 4
def set_access(user, handle, access):
info = win32security.GetSecurityInfo(
handle, SE_WINDOW_OBJECT, DACL_SECURITY_INFORMATION
)
dacl = info.GetSecurityDescriptorDacl()
dacl.AddAccessAllowedAce(win32security.ACL_REVISION, access, user)
win32security.SetSecurityInfo(
handle, SE_WINDOW_OBJECT, DACL_SECURITY_INFORMATION, None, None, dacl, None
)
username = "mattsegal"
user, domain, user_type = win32security.LookupAccountName("", username)
thread_id = win32api.GetCurrentThreadId()
station_handle = win32process.GetProcessWindowStation()
desktop_handle = win32service.GetThreadDesktop(thread_id)
set_access(user, station_handle, WINDOW_STATION_ALL_ACCESS)
set_access(user, desktop_handle, DESKTOP_RIGHTS_ALL_ACCESS)