The latest Python Sendkeys module is for Python 2.6. I can't upgrade it myself as it needs the C module to be recompiled.
Does anyone know of a fairly easy alternative way to send keys to a window?
Using win32ui.FindWindow() I can find the right window, then make it active with PyCWnd.SetActiveWindow(), so all that's needed is a simple way to send keystrokes to the active window.
The purpose is to execute a menu item.
The app was written in Delphi, and doesn't have any inter-process interface that I know about.
Here is a working module that calls user32.SendInput().
Not perfect, but usable.
Edit:
Yesterday I did a version with a class, and am using it in a working tkinter app. Will put it here when i get time to clean it up.
Have added this in the doc string below:
[ It is OK if I work from a folder within my profile.
These problems happened when working on another partition.
File permissions were OK, so do not know what blocked SendInput. ]
SciTE still needs the full exact window title.
#!/usr/bin/python
# -*- coding: utf-8 -*-
''' send_input for python 3, from jh45dev#gmail.com
code from Daniel F is adapted here. The original is at:
http://mail.python.org/pipermail/python-win32/2005-April/003131.html
SendInput sends to the window that has the keyboard focus.
That window must not be minimized.
There seem to be some strange limitations with user32.SendInput()
Here is what happened in my testing (on Vista sp2).
[edit: It is OK if I work from a folder within my profile.
These problems happened when working on another partition.
File permissions were OK, so do not know what blocked SendInput.]
1
I opened Notepad from the Start menu,
then in Notepad opened test.txt,
and all worked fine.
2
I opened Notepad by opening test.txt in Explorer.
find_window() found Notepad, but user32.SendInput() had no effect.
If Notepad was minimized, it did not get restored or focussed.
The same happened with SciTE and Notepad2.
Another strangeness:
For SciTE I had to put in the whole window title, eg "test.txt - SciTE",
but for Notepad and Notepad2, only the app name, eg "Notepad".
'''
import ctypes as ct
from win32con import SW_MINIMIZE, SW_RESTORE
from win32ui import FindWindow, error as ui_err
from time import sleep
class cls_KeyBdInput(ct.Structure):
_fields_ = [
("wVk", ct.c_ushort),
("wScan", ct.c_ushort),
("dwFlags", ct.c_ulong),
("time", ct.c_ulong),
("dwExtraInfo", ct.POINTER(ct.c_ulong) )
]
class cls_HardwareInput(ct.Structure):
_fields_ = [
("uMsg", ct.c_ulong),
("wParamL", ct.c_short),
("wParamH", ct.c_ushort)
]
class cls_MouseInput(ct.Structure):
_fields_ = [
("dx", ct.c_long),
("dy", ct.c_long),
("mouseData", ct.c_ulong),
("dwFlags", ct.c_ulong),
("time", ct.c_ulong),
("dwExtraInfo", ct.POINTER(ct.c_ulong) )
]
class cls_Input_I(ct.Union):
_fields_ = [
("ki", cls_KeyBdInput),
("mi", cls_MouseInput),
("hi", cls_HardwareInput)
]
class cls_Input(ct.Structure):
_fields_ = [
("type", ct.c_ulong),
("ii", cls_Input_I)
]
def find_window( s_app_name ):
try:
window1 = FindWindow( None, s_app_name,)
return window1
except ui_err:
pass
except:
raise
try:
window1 = FindWindow( s_app_name, None, )
return window1
except ui_err:
return None
except:
raise
def make_input_objects( l_keys ):
p_ExtraInfo_0 = ct.pointer(ct.c_ulong(0))
l_inputs = [ ]
for n_key, n_updown in l_keys:
ki = cls_KeyBdInput( n_key, 0, n_updown, 0, p_ExtraInfo_0 )
ii = cls_Input_I()
ii.ki = ki
l_inputs.append( ii )
n_inputs = len(l_inputs)
l_inputs_2=[]
for ndx in range( 0, n_inputs ):
s2 = "(1, l_inputs[%s])" % ndx
l_inputs_2.append(s2)
s_inputs = ', '.join(l_inputs_2)
cls_input_array = cls_Input * n_inputs
o_input_array = eval( "cls_input_array( %s )" % s_inputs )
p_input_array = ct.pointer( o_input_array )
n_size_0 = ct.sizeof( o_input_array[0] )
# these are the args for user32.SendInput()
return ( n_inputs, p_input_array, n_size_0 )
'''It is interesting that o_input_array has gone out of scope
by the time p_input_array is used, but it works.'''
def send_input( window1, t_inputs, b_minimize=True ):
tpl1 = window1.GetWindowPlacement()
was_min = False
if tpl1[1] == 2:
was_min = True
window1.ShowWindow(SW_RESTORE)
sleep(0.2)
window1.SetForegroundWindow()
sleep(0.2)
window1.SetFocus()
sleep(0.2)
rv = ct.windll.user32.SendInput( *t_inputs )
if was_min and b_minimize:
sleep(0.3) # if the last input was Save, it may need time to take effect
window1.ShowWindow(SW_MINIMIZE)
return rv
# define some commonly-used key sequences
t_ctrl_s = ( # save in many apps
( 0x11, 0 ),
( 0x53, 0 ),
( 0x11, 2 ),
)
t_ctrl_r = ( # reload in some apps
( 0x11, 0 ),
( 0x52, 0 ),
( 0x11, 2 ),
)
def test():
# file > open; a non-invasive way to test
t_ctrl_o = ( ( 0x11, 0 ), ( 0x4F, 0 ), ( 0x11, 2 ), )
# writes "Hello\n"
# 0x10 is shift. note that to repeat a key, as with 4C here, you have to release it after the first press
t_hello = ( ( 0x10, 0 ), ( 0x48, 0 ), ( 0x10, 2 ), ( 0x45, 0 ), ( 0x4C, 0 ), ( 0x4C, 2 ), ( 0x4C, 0 ), ( 0x4F, 0 ), ( 0x0D, 0 ), )
l_keys = [ ]
## l_keys.extend( t_ctrl_o )
l_keys.extend( t_hello )
l_keys.extend( t_ctrl_s )
## s_app_name = "SciTE"
## s_app_name = "(Untitled) - SciTE"
s_app_name = "test.txt - SciTE"
## s_app_name = "Notepad2"
## s_app_name = "Notepad"
window1 = find_window( s_app_name )
if window1 == None:
print( "%r has no window." % s_app_name )
input( 'press enter to close' )
exit()
t_inputs = make_input_objects( l_keys )
n = send_input( window1, t_inputs )
## print( "SendInput returned: %r" % n )
## print( "GetLastError: %r" % ct.windll.kernel32.GetLastError() )
## input( 'press enter to close' )
if __name__ == '__main__':
test()
I rewrote the C bits of sendkeys in ctypes a while ago...
https://bitbucket.org/markm/sendkeysctypes
and I see someone else did it too:
http://code.google.com/p/sendkeys-ctypes/
If I remember it should be a drop in replacement for sendkeys (only the import line has to change)
Got something that works, using win32api.keybd_event.
Looks like SendInput would be safer, but pywin32 does not include it.
[ edit: See a SendInput version in the accepted answer below. I leave this message here in case someone prefers to use sendkeys. jh ]
This page helped: http://social.msdn.microsoft.com/Search/en-us/?Query=keybd_event
Code that works:
import win32api;
import win32ui
PyCWnd1 = win32ui.FindWindow( None, "an_app" )
PyCWnd1.SetForegroundWindow()
PyCWnd1.SetFocus()
win32api.keybd_event(0x12, 0, ) # Alt
win32api.keybd_event(0x12, 0, 2 ) # Alt release
win32api.keybd_event(0x46, 0, ) # F
win32api.keybd_event(0x52, 0, ) # R
This does File > Reload in the app. Does not work if the app is minimized
Without releasing Alt, after running this, the keyboard behaved like i was holding the Alt key!
Don't seem to need to release the other keys
You want the keybd_event API. My PushKeys program is syntax compatible with SendKeys and has a sleep function built in. Although it isn't in Python it should be translatable readily enough (its been translated into a lot of languages - at least it should show you the API to use). It is available here in a variety of languages.
Related
I'm trying to create a function that creates emitters (emitting from objects), but I'm having trouble getting it to work with multiple objects at the same time.
I want emitter1 to be connected to nParticle1 and emitter2 to nParticle2.
def particalWebSystem(webDensity,genoration):
selectedObject = cmds.ls( selection = True )
print selectedObject
if len(selectedObject)==0:
cmds.confirmDialog( title='Warning', message='Please select at least one object', button=['Close'], defaultButton='Close', cancelButton='Close', dismissString='Close' )
if len(selectedObject)==1:
print "<2"
else:
print ">2"
emitting = cmds.emitter( selectedObject, n='emitter' )
cmds.particle( n = 'nParticle#' )
cmds.connectDynamic( 'nParticle#', em = 'emitter' )
cmds.setAttr( "emitter.emitterType", 2 )
cmds.setAttr( "nParticle#Shape.lifespanMode", 2 )
cmds.setAttr( "nParticle#Shape.maxCount", webDensity )
cmds.setAttr( "nParticle#Shape.lifespanRandom", generation )
You can simplify this problem by making sure you use the name of the emitter you actually create -- you never know what name you'll really get because Maya will rename things. It's best to always capture the names of things you create and work on them instead of hoping you get the names you asked for.
This version makes a function and just calls it on every selected object. It will silently do nothing for empty selections it also returns the objects created in case you need them later.
import maya.cmds as cmds
def setup_emitter(source_object, maxcount, life_random):
source_object, emitting = cmds.emitter( source_object, n=source_object + "_emitter" )
particle, particleshape = cmds.particle( n = source_object + "_particles" )
cmds.connectDynamic( particle, em = emitting)
cmds.setAttr( emitting + ".emitterType", 2 )
cmds.setAttr( particleshape + ".lifespanMode", 2 )
cmds.setAttr( particleshape + ".maxCount", maxcount )
cmds.setAttr( particleshape + ".lifespanRandom", life_random )
return emitting, particleshape
for selection in cmds.ls(sl=True, type='transform'):
print setup_emitter(selection, 100, 100) # your values here
The document for bit manipulation in python states
https://wiki.python.org/moin/BitManipulation
as example, the following code
import ctypes
c_uint8 = ctypes.c_uint8
class Flags_bits( ctypes.LittleEndianStructure ):
_fields_ = [
("logout", c_uint8, 1 ), # asByte & 1
("userswitch", c_uint8, 1 ), # asByte & 2
("suspend", c_uint8, 1 ), # asByte & 4
("idle", c_uint8, 1 ), # asByte & 8
]
class Flags( ctypes.Union ):
_anonymous_ = ("bit",)
_fields_ = [
("bit", Flags_bits ),
("asByte", c_uint8 )
]
flags = Flags()
flags.asByte = 0x2 # ->0010
print( "logout: %i" % flags.bit.logout )
# `bit` is defined as anonymous field, so its fields can also be accessed directly:
print( "logout: %i" % flags.logout )
print( "userswitch: %i" % flags.userswitch )
print( "suspend : %i" % flags.suspend )
print( "idle : %i" % flags.idle )
so i figured out that setting the value to asByte is leading to the value being parsed into the c_uint8, but i am unable to understand the logic behind this. When we set the asByte value, does python work back from the asByte value set to update the value for individual components that make the class. Also as a side note, i was not able to find documentation for asByte. If someone can point me to it, it'd be great.
Using a python based disassembler + debugger I've found below instructions(example). Now I want to parse Microsoft provided public symbols to find exact functions its calling.
I want to know what are the available options/ modules to do the same. Can we just simply get the info from a static PDB files or its required to load that in memory while debugging ?
call ntdll!0x33dec
call ntdll!0x22280
call ntdll!0x2df40
call ntdll!0x33cdb
call ntdll!0x2df29
call ntdll!0x325a0
call ntdll!0x32a96
call ntdll!0x32a79
call ntdll!0x220a4
A sample that uses capstone for dis-assembly and dbghelp apis for symbol resolving of an immediate E8 call
import sys #for argv[]
import binascii #for hexlify repr() spits out ugly mix like
#'\xe8y\xff\' instead of '\xe8\x79\xff' :(
from ctypes import *
from capstone import *
class SYMBOL_INFO(Structure):
_fields_ = [
( 'SizeOfStruct', c_ulong ),
( 'TypeIndex', c_ulong ),
( 'Reserved', c_ulonglong * 2 ),
( 'Index', c_ulong ),
( 'Size', c_ulong ),
( 'ModBase', c_ulonglong ),
( 'Flags', c_ulong ),
( 'Value', c_ulonglong ),
( 'Address', c_ulonglong ),
( 'Register', c_ulong ),
( 'Scope', c_ulong ),
( 'Tag' , c_ulong ),
( 'NameLen', c_ulong ),
( 'MaxNameLen', c_ulong ),
( 'Name', c_char * 2001 )
]
modname = sys.argv[1]
offset = long(sys.argv[2],16)
sympath = "xxx:\\yyyyy" # substitute actual path
base = windll.LoadLibrary(modname)._handle
symaddr = c_ulonglong(base + offset)
print "Module name = %s\nModule Base = %s\nSymFromAddr = %s" % \
(modname,hex(base),hex(symaddr.value))
dbghelp = windll.dbghelp
k32 = windll.kernel32
hproc = k32.GetCurrentProcess()
dbghelp.SymInitialize(hproc,sympath,1)
sinfo = SYMBOL_INFO()
sinfo.SizeOfStruct = sizeof(SYMBOL_INFO) - 2000
sinfo.MaxNameLen = 2000
Displacement = c_ulonglong()
dbghelp.SymFromAddr(hproc,symaddr,addressof(Displacement),addressof(sinfo))
print "Sym At Addr = %s + %s" % (sinfo.Name,str(hex(Displacement.value)))
opcodebuff = create_string_buffer(16)
memmove(opcodebuff,symaddr.value,16)
for i in range(0,16,1):
print binascii.hexlify(opcodebuff.raw[i]),
print
MyDisasm = Cs(CS_ARCH_X86, CS_MODE_32)
for i in MyDisasm.disasm(opcodebuff, symaddr,1):
print "0x%x: %s %s %s" % ( i.address ,binascii.hexlify(i.bytes),
i.mnemonic, i.op_str)
if(i.mnemonic == 'call'):
try:
symaddr = c_ulonglong(long(i.op_str,16))
dbghelp.SymFromAddr(hproc,symaddr,addressof(Displacement),addressof(sinfo))
print "(%s+%s)" % (sinfo.Name,str(hex(Displacement.value))),
print "(%s+0x%X)"% (modname ,long(i.op_str,16)-base)
except:
print "Indirect/register Calls Not Handled Yet"
pass
usage as follows
python dumpsym.py ntdll 1041
first argument is a string that represents a module
second argument is a string that represents an offset in the module
so if module is loaded at 0xxxxxxxxx offset 1041 will point to the address
0xxxxxxxxx+0x1041
output
Module name = ntdll
Module Base = 0x7c900000
SymFromAddr = 0x7c901041L
Sym At Addr = RtlEnterCriticalSection + 0x41L
e8 79 a1 01 00 64 8b 0d 18 00 00 00 8b 54 24 04
0x7c901041: e879a10100 call 0x7c91b1bf
(RtlpWaitForCriticalSection+0x0L) (ntdll+0x1B1BF)
You can get symbols from PDB file using DbgHelp API. This is the same API WinDbg uses, and you can use it to debug live processes as well as simply extract symbols based on offset of the loaded module. In your case SymFromAddr function would be easiest to use to get symbol from an address.
One non-automated but quick way to do that would be :
Load ntdll.dll in the debugger as a dump file.
Load the symbols using the public symbol path - or local cache.
Use the ln command. Like: ln ntdll!0x33dec
several month ago,I wrote https://github.com/325862401/goagent/blob/master/local/ieproxysetting.cpp. that program can set internet proxy automatically.
Now I want to use ctypes.windll.Wininet to do the same thing.
But I donot know how to pass the argument to InternetQueryOptionW.
and I also don't find the class refer to the INTERNET_PER_CONN_OPTION_LIST structure.
is there any demo for the usage of InternetQueryOptionW or InternetSetOptionW in python.
this https://bitbucket.org/canassa/switch-proxy/src/685ac447783a7cb3ead6ce8369b66483790c26be/proxy.py?at=default maybe be helpful.
but I donot want to modify Registry.
just use the api.
Thanks a lot.
sorry for poor English.
Here is Python equivalent to your cpp code, pretty much straight forward conversation (I didn't test it that much):
#-*- coding: utf-8 -*-
#!python
from ctypes import *
from ctypes.wintypes import *
# stick to unicode version
LPWSTR = POINTER(WCHAR)
HINTERNET = LPVOID
INTERNET_PER_CONN_FLAGS = 1
INTERNET_PER_CONN_AUTOCONFIG_URL = 4
INTERNET_PER_CONN_AUTODISCOVERY_FLAGS = 5
INTERNET_OPTION_REFRESH = 37
INTERNET_OPTION_SETTINGS_CHANGED = 39
INTERNET_OPTION_PER_CONNECTION_OPTION = 75
PROXY_TYPE_AUTO_PROXY_URL = 4
class INTERNET_PER_CONN_OPTION(Structure):
class Value(Union):
_fields_ = [
('dwValue', DWORD),
('pszValue', LPWSTR),
('ftValue', FILETIME),
]
_fields_ = [
('dwOption', DWORD),
('Value', Value),
]
class INTERNET_PER_CONN_OPTION_LIST(Structure):
_fields_ = [
('dwSize', DWORD),
('pszConnection', LPWSTR),
('dwOptionCount', DWORD),
('dwOptionError', DWORD),
('pOptions', POINTER(INTERNET_PER_CONN_OPTION)),
]
InternetSetOption = windll.wininet.InternetSetOptionW
InternetSetOption.argtypes = [HINTERNET, DWORD, LPVOID, DWORD]
InternetSetOption.restype = BOOL
if __name__ == '__main__':
proxy = create_unicode_buffer('http://127.0.0.1:8086/proxy.pac')
List = INTERNET_PER_CONN_OPTION_LIST()
Option = (INTERNET_PER_CONN_OPTION * 2)()
nSize = c_ulong(sizeof(INTERNET_PER_CONN_OPTION_LIST))
Option[0].dwOption = INTERNET_PER_CONN_AUTOCONFIG_URL
Option[0].Value.pszValue = proxy
Option[1].dwOption = INTERNET_PER_CONN_FLAGS
Option[1].Value.dwValue = PROXY_TYPE_AUTO_PROXY_URL
List.dwSize = sizeof(INTERNET_PER_CONN_OPTION_LIST)
List.pszConnection = None
List.dwOptionCount = 2
List.dwOptionError = 0
List.pOptions = Option
assert InternetSetOption(None, INTERNET_OPTION_PER_CONNECTION_OPTION, byref(List), nSize) == True
assert InternetSetOption(None, INTERNET_OPTION_SETTINGS_CHANGED, None, 0) == True
assert InternetSetOption(None, INTERNET_OPTION_REFRESH, None, 0) == True
You don't need MultiByteToWideChar, create_unicode_buffer and the unicode version of InternetSetOption should do the job.
I'm trying to access a dll from python, following this guide. The first function I try and call from the dll seems to work fine, so I must be most of the way there, but the second one gives me an access violation.
Python code:
#create open function
openProto = ctypes.WINFUNCTYPE( ctypes.c_int, ctypes.c_void_p )
openParams = ( 1, "handle", 0 ) ,
open = openProto ( ( "SensorOpen", pm ), openParams )
#create zero function
zeroProto = ctypes.WINFUNCTYPE( ctypes.c_int, ctypes.c_int )
zeroParams = ( 1, "handle", 0 ),
zero = zeroProto ( ( "SensorZero", pm ), zeroParams )
handle = ctypes.c_int ( 0 )
status = ctypes.c_int ( 0 )
open( ctypes.byref(handle) )
print handle
zero( handle )
The access violation occurs when I call the zero( handle ).
The C++ code that does this is here:
SENSOR_HANDLE seHandle; // Sensor handle
double power;
char buff[80];
// Get handle for sensor
SensorOpen (&seHandle);
printf ("Sensor connected\nZeroing, please wait...\n");
while (SensorZero (seHandle) == SENSOR_ZERO_FAILED)
{
printf ("Zero failed.\nCheck no power is being applied.\nPress return key to retry ");
gets (buff);
}
Where SENSOR_HANDLE is just a typedef'd int
Any ideas? I assume it's ok not to do anything with the returned value.
Problem solved.
The c++ code was sample code provided with some documentation. Needless to say the sample code and the documentation were incorrect (the zero function still wanted its argument as a pointer).