Python - ctypes
Jump to navigation
Jump to search
Tutorials
See:
- http://docs.python.org/lib/ctypes-ctypes-tutorial.html
- http://starship.python.net/crew/theller/ctypes/tutorial.html
References
- http://wiki.python.org/moin/ctypes
- http://bytes.com/topic/python/answers/607023-c_string-missing-ctypes
Simple Examples
The API exported from the demo DLL is as follows:
extern "C" { __declspec(dllexport) char* next(int id); __declspec(dllexport) void next_s(char* buf, int buflen, int id); __declspec(dllexport) void xxx_s(char* buf, int buflen, int id); }
#!/usr/bin/env python import ctypes import pprint libx = ctypes.CDLL('x') pprint.pprint(x.__dict__) print type(x) x.next.restype = ctypes.c_char_p print "%s\n" % x.next(4)
GUI Examples
TestGUI
import win32api import win32con import win32gui ##a = 0 ##b = 1 ##while b < 10: ## print b ## a, b = b, a+b ##def windowEnumerationHandler(hwnd, resultList): ## ## '''Pass to win32gui.EnumWindows() to generate list of window handle, window text tuples.''' ## ## resultList.append((hwnd, win32gui.GetWindowText(hwnd))) ## print resultList; def windowEnumerationHandler(hwnd, resultList): '''Pass to win32gui.EnumWindows() to generate list of window handle, window text, window class tuples.''' resultList.append((hwnd, win32gui.GetWindowText(hwnd), win32gui.GetClassName(hwnd))) ## resultList.append((hwnd, win32gui.GetWindowText(hwnd))) # print resultList; import ctypes ##def getClassName(hwnd): ## resultString = ctypes.c_string("\000" * 32) ## ctypes.windll.user32.GetClassNameA(hwnd, resultString, len(resultString)) ## return resultString.value topWindows = [] win32gui.EnumWindows(windowEnumerationHandler, topWindows) ##def findTopWindow(wantedText=None, wantedClass=None): ## topWindows = [] ## win32gui.EnumWindows(windowEnumerationHandler, topWindows) ## for hwnd, windowText, windowClass in topWindows: ## if wantedText and not windowText.startswith(wantedText): ## continue ## if wantedClass and not windowClass == wantedClass: ## continue ## return hwnd # Please correct me if I'm wrong anywhere # # when a program executes it adds a top level window handle to the system # # window handles are unique across the system at any given time # window handles are assigned by the operating system for each execution of a program, # and therefore a window cannot be referred to by its window handle from a previous # execution run # # in order to find a particular window handle (control), for example a button (so that we # can send a win32con.WM_LBUTTONDOWN message) we need to start a the programs top level window # and search the window handle tree until we find the desired control. # # uniquely identifying a control requires prior knowledge about the hierarchical # layout of the interested program's windows, because even Control IDs can be used multiple # times for different windows # # while depth > 0 # check current handle against what we want (window text, window class, control ID?) # at the specified array[depth] # # if check is good # # hwnd = win32gui.GetParent() # if hwnd is NULL return # else # depth-- # # end while # return true! # win32event.WaitForInputIdle def findControl(topHwnd, selectionFunction): def searchChildWindows(currentHwnd): childWindows = [] try: win32gui.EnumChildWindows(currentHwnd, windowEnumerationHandler, childWindows) except win32gui.error, exception: # This seems to mean that the control does *cannot* have child windows return for childHwnd, windowText, windowClass in childWindows: print "Found ", childHwnd, windowText, windowClass print win32gui.HIWORD(childHwnd) if win32gui.IsWindow(childHwnd): print "it is a window" someID = 0x0000E900 try: dlgitem = win32gui.GetDlgItem(childHwnd, someID) print "WOOO", childHwnd, dlgitem except: print "not here" ## hTmp = ::GetDlgItem( m_hToolBarsParent, lId ); ## if( hTmp != NULL ) ## m_mapTool.insert( TIdMap::value_type( ::GetDlgCtrlID( hTmp ), hTmp ) ); ## ## lId++; if selectionFunction(childHwnd, windowText, windowClass): return childHwnd else: descendentMatchingHwnd = searchChildWindows(childHwnd) if descendentMatchingHwnd: return descendentMatchingHwnd return return searchChildWindows(topHwnd) def keystroke(hwnd, key): win32gui.SendMessage(hwnd, win32con.WM_KEYDOWN, key, 0) win32gui.SendMessage(hwnd, win32con.WM_KEYUP, key, 0) ##win32gui.FindWindow("None", "PythonWin") #eudoraMain = win32gui.FindWindow("EudoraMainWindow", "Eudora - [benjamin.lee (<Dominant>)]") # py_hwnd = win32gui.FindWindow("Afx:400000:8:10011:0:2a07cf", "PythonWin") py_hwnd = win32gui.FindWindow("Afx:400000:8:10011:0:6000d5", "PythonWin") win32gui.PostMessage(0x000100D0, win32con.WM_LBUTTONDOWN, 0x00000001, 0x000A0099) win32gui.PostMessage(0x000100D0, win32con.WM_LBUTTONUP, 0x00000000, 0x000A0099) print win32gui.GetActiveWindow() print win32gui.GetForegroundWindow() #win32gui.SendMessage(py_hwnd, win32con.WM_SYSKEYDOWN, win32con.VK_MENU, 0) print win32gui.GetActiveWindow() print win32gui.GetForegroundWindow() #win32gui.SendMessage(py_hwnd, win32con.WM_SYSKEYDOWN, ord('F'), 0) print win32gui.GetActiveWindow() print win32gui.GetForegroundWindow() #win32gui.SendMessage(py_hwnd, win32con.WM_SYSCHAR, ord('f'), 0) print win32gui.GetActiveWindow() print win32gui.GetForegroundWindow() # win32gui.SendMessage(py_hwnd, win32con.WM_SYSCOMMAND, win32con.SC_KEYMENU, 0) print win32gui.GetActiveWindow() print win32gui.GetForegroundWindow() # keystroke(py_hwnd, ord('F')) #win32gui.SendMessage(py_hwnd, win32con.WM_KEYDOWN, ord('o'), 0) #win32gui.SendMessage(py_hwnd, win32con.WM_CHAR, ord('o'), 0) #win32gui.SendMessage(py_hwnd, win32con.WM_KEYUP, win32con.VK_MENU, 0) print win32gui.GetActiveWindow() print win32gui.GetForegroundWindow() #win32gui.SendMessage(py_hwnd, win32con.WM_KEYUP, ord('F'), 0) # win32gui.SendMessage(py_hwnd, win32con.WM_COMMAND, 57601, 0) print "hello", win32gui.LOWORD(py_hwnd), win32gui.HIWORD(py_hwnd) # win32gui. # e900 # win32gui.SendMessage(py_hwnd, win32con.WM_SYSKEYUP, ord('F'), 0) ##optDialog = findTopWindow(wantedText="Options") ## print optDialog import time ##fgw = win32gui.GetForegroundWindow() ##win32gui.SetForegroundWindow(eudoraMain) ## ## ##def syskeystroke (key): ## win32api.keybd_event( key, ## 0x45, ## win32con.KEYEVENTF_EXTENDEDKEY | 0, ## 0 ); ## win32api.keybd_event( key, ## 0x45, ## win32con.KEYEVENTF_EXTENDEDKEY | win32con.KEYEVENTF_KEYUP, ## 0); ## ##syskeystroke (win32con.VK_NUMLOCK) ##syskeystroke (win32con.VK_MENU) ## ##print ord("F") ## ##syskeystroke (ord ("F")) ##syskeystroke (ord ("I")) ##time.sleep(2) ##syskeystroke (win32con.VK_ESCAPE) ## ####syskeystroke (win32con.VK_CONTROL) ####syskeystroke (ord ("N")) ## ### combo Ctrl+N ##win32api.keybd_event( win32con.VK_CONTROL, 0x45, win32con.KEYEVENTF_EXTENDEDKEY | 0, 0 ); ##win32api.keybd_event( ord ("N"), 0x45, win32con.KEYEVENTF_EXTENDEDKEY | 0, 0 ); ##win32api.keybd_event( ord ("N"), 0x45, win32con.KEYEVENTF_EXTENDEDKEY | win32con.KEYEVENTF_KEYUP, 0); ##win32api.keybd_event( win32con.VK_CONTROL, 0x45, win32con.KEYEVENTF_EXTENDEDKEY | win32con.KEYEVENTF_KEYUP, 0); ## ## ##time.sleep(2) ## ##win32gui.SetForegroundWindow(fgw) ## ##win32gui.SendMessage(eudoraMain, win32con.WM_SYSKEYDOWN, win32con.VK_MENU, 0) ###win32gui.SendMessage(eudoraMain, win32con.WM_SYSKEYDOWN, (ord("F") | 0x20000000 ), 0) ## ##win32gui.SendMessage(eudoraMain, win32con.WM_SYSKEYDOWN, ord("F"), 0) ###keystroke(eudoraMain, "f") ###keystroke(eudoraMain, "i") ###win32gui.SendMessage(eudoraMain, win32con.WM_SYSKEYDOWN, "F", 0) ## ##win32gui.SendMessage(eudoraMain, win32con.WM_SYSCHAR, "X", 0) ##win32gui.SendMessage(eudoraMain, win32con.WM_SYSKEYUP, ord("F"), 0) ## ##win32gui.SendMessage(eudoraMain, win32con.WM_SYSKEYUP, win32con.VK_MENU, 0) #win32gui.SendMessage(eudoraMain, win32con.WM_SYSKEYUP, (ord("F") | 0x20000000 ), 0) #win32gui.SendMessage(eudoraMain, win32con.WM_SYSKEYDOWN, (ord("X") | 0x20000000 ), 0) #win32gui.SendMessage(eudoraMain, win32con.WM_SYSKEYUP, (ord("X") | 0x20000000 ), 0) #win32gui.SendMessage(eudoraMain, win32con.WM_SYSKEYDOWN, 'I', 0) #win32gui.SendMessage(eudoraMain, win32con.WM_SYSKEYUP, 'I', 0) ## wm_syskeydown for VK_MENU (alt) ## wm_syskeydown for Ord('F') ## wm_syschar for 'F' ## wm_syskeyup for Ord('F'), ## wm_syskeyup for VM_MENU #keystroke(eudoraMain, "i") exit def findAButtonCalledOK(hwnd, windowText, windowClass): return windowClass == "Button" and windowText == "OK" def findAButtonCalledDate(hwnd, windowText, windowClass): return windowClass == "Button" and windowText == "S&ubject" #return windowClass == "Button" and windowText == "&Date" # okButton = findControl(eudoraMain, findAButtonCalledOK) #okButton = findControl(py_hwnd, findAButtonCalledOK) ## dateButton = findControl(eudoraMain, findAButtonCalledDate) def click(hwnd): win32gui.SendMessage(hwnd, win32con.WM_LBUTTONDOWN, 0, 0) win32gui.SendMessage(hwnd, win32con.WM_LBUTTONUP, 0, 0) # click(dateButton) ## ## ####optDialog = findTopWindow(wantedText="Options") #### ####okButton = findControl(optDialog, lambda hwnd, windowText, windowClass : windowClass == "Button" and windowText == "OK") #### ####click(okButton) ## ## ##def getEditText(hwnd): ## ## result = [] ## ## bufferlength = struct.pack('i', 255) ## ## linecount = win32gui.SendMessage(hwnd, win32con.EM_GETLINECOUNT, 0, 0) ## ## for line in range(linecount): ## ## linetext = bufferlength + "".ljust(253) ## ## linelength = win32gui.SendMessage(hwnd, win32con.EM_GETLINE, line, linetext) ## ## result.append(linetext[:linelength]) ## ## return result ## ## ##genTop = findTopWindow(wantedText="Generating the Runtime") ## ##def editFinder(hwnd, windowText, windowClass): return windowClass == "Edit" ## ##genEdit = findControl(genTop, editFinder) ## ##print getEditText(genEdit) ## ##def getMultipleWindowValues(hwnd, getCountMessage, getValueMessage): ## ## bufferlength = struct.pack('i', 255) ## ## count = win32gui.SendMessage(hwnd, getCountMessage, 0, 0) ## ## for itemIndex in range(count): ## ## value = array.array('c', bufferlength + str().ljust(253)) ## ## valueLength = win32gui.SendMessage(hwnd, getValueMessage, itemIndex, value) ## ## yield value.tostring()[:valueLength] ## ## ##def getComboboxItems(hwnd): return getMultipleWindowValues(hwnd, getCountMessage=win32con.CB_GETCOUNT, getValueMessage=win32con.CB_GETLBTEXT) ##def getEditText(hwnd): return getMultipleWindowValues(hwnd, getCountMessage=win32con.EM_GETLINECOUNT, getValueMessage=win32con.EM_GETLINE) ## ## ##def selectComboboxItem(hwnd, item): ## ## win32gui.SendMessage(hwnd, win32con.CB_SETCURSEL, item, 0) ## ## click(hwnd) ## ## keystroke(hwnd, win32con.VK_RETURN) ## ## ## ## ## ### Find the ACE window library selection combo ## ##def findAceLibrarySelectionFunction(hwnd, windowText, windowClass): return windowClass == "ComboBox" and ("EVO1" in getComboboxItems(hwnd)) ## ##libCombo = findControl(findTopWindow(wantedText="ACE"), findAceLibrarySelectionFunction) ## ## ### Get a list of the combo items ##items = getComboboxItems(libCombo) ##print "Items: " + str(items) ##import random ## ## ### Pick one at random, and select it ##selectItemIndex = random.randrange(len(items)) ##print "Selecting: " + items[selectItemIndex] ##selectComboboxItem(libCombo, selectItemIndex)
A scrap of sample code from a past SVT exercise implemented using Python and ctypes:
#!/usr/bin/env python ## import ctypes from ctypes import * from ctypes.wintypes import * import win32con import sys import time #dll = windll.MouseHook # the dll is called hooksm.dll dll = cdll.hooksm #startfn = dll.setMyHook #stopfn = dll.clearMyHook # startfn() dll.search_msg = c_int (win32con.WM_SETTEXT) #windll.user32.DefWindowProcA(c_int(hwnd), c_int(message), c_int(wParam), c_int(lParam)) txt = "Analysis is complete for:" startfn = dll.hksmSetHook #startfn.argtypes = [c_ulong, c_int, c_uint, c_long, c_char_p, c_ulong] startfn ( # c_ulong(0x00000238), c_ulong(0x00000000), c_int (win32con.WM_SETTEXT), c_uint(win32con.NULL), c_char_p(txt), 0x00000000 ) startt = time.time() print startt #time.sleep(20) print "sync pre" syncfn = dll.Synchronize print "sync start" syncfn() print "sync stop" endt = time.time() print endt print endt - startt dll.hksmUnsetHook () #stopfn() #flog = dll.log