Python - ctypes

From PeformIQ Upgrade
Jump to navigation Jump to search

Tutorials

See:

References

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