I am executing Ironpython scripts from a Windows application that has an embedded Ironpython shell. I can launch the application, load a script and start their execution from a (.bat) file. I would like to close the application once the test scripts finish. However, the application vendor has not provided the functionality to close the application programmatically.
My first thought was to use a PIPE to monitor a specific string which will terminate the subprocess. My test script opens up a form which gets populated with data needed for testing. There are other complications which I am not sure how to handle in printing to the PIPE. Any printing goes directly to the application's shell window.
The method I am pursuing is to close the application by making the application's window active. Below is my code which is based on
Python's pywin32 extension
import ctypes
import re
EnumWindows = ctypes.windll.user32.EnumWindows
EnumWindowsProc = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int))
GetWindowText = ctypes.windll.user32.GetWindowTextW
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
IsWindowVisible = ctypes.windll.user32.IsWindowVisible
class my_test():
def __init__ (self):
"""Constructor"""
self._handle = None
self.wildcard = "Program name"
self.titles = []
def foreach_window(self, hwnd, lParam):
'''Pass to EnumWindows() to check all the opened windows'''
if IsWindowVisible(hwnd):
length = GetWindowTextLength(hwnd)
#print 'length', length
buff = ctypes.create_unicode_buffer(1024)
#buff = ctypes.create_unicode_buffer(length + 1)
#print 'buff', buff
GetWindowText(hwnd, buff, length + 1)
self.titles.append(buff.value)
if re.match(self.wildcard, str(buff.value)) != None:
self._handle = hwnd
print 'self._handle', self._handle
print 'str(buff.value)', str(buff.value)
return True
def find_window(self):
EnumWindows(EnumWindowsProc(self.foreach_window), 0)
def set_foreground(self):
"""put the window in the foreground"""
ctypes.windll.user32.SetActiveWindow(self._handle)
ctypes.windll.user32.SetForegroundWindow(self._handle)
ctypes.windll.user32.PostMessage(self._handle, win32con.WM_CLOSE, 0, 0)
def main():
w = my_test()
w.find_window()
w.set_foreground()
I found another discussion on closing application (I think using pywin32 extensions) 2. The author refers to win32process and win32gui. Do these modules have a ctypes equivalent?
I added the following lines to the code.
SendMessage = ctypes.windll.user32.SendMessageW
WM_SYSCOMMAND = ctypes.c_int(0x0112)
SC_CLOSE = ctypes.c_int(0xF060)
Replaced line
ctypes.windll.user32.PostMessage(self._handle, win32con.WM_CLOSE, 0, 0)
with
SendMessage(my_window, WM_SYSCOMMAND, SC_CLOSE, 0)
This works as long as I execute this script in a separate IronPython shell.
taskkill did the trick, see