<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-22247650</id><updated>2011-11-20T23:49:09.109+08:00</updated><category term='betterbatch'/><category term='python'/><title type='text'>mark.py</title><subtitle type='html'>Things that spring to my mind on pywinauto, betterbatch and other stuff.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://pywinauto.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://pywinauto.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Mark Mc Mahon</name><uri>http://www.blogger.com/profile/13173865151939176401</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>19</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-22247650.post-8783310713948096386</id><published>2011-06-07T17:46:00.003+08:00</published><updated>2011-06-07T22:41:57.633+08:00</updated><title type='text'>Creating images of python code + pygments = WIN!</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-WZS_VxmuanI/Te44Fwk7VBI/AAAAAAAAAAQ/njXGQ6S6KYc/s1600/_5_unittest_quotes_no_fixture.py.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 400px; height: 187px;" src="http://3.bp.blogspot.com/-WZS_VxmuanI/Te44Fwk7VBI/AAAAAAAAAAQ/njXGQ6S6KYc/s400/_5_unittest_quotes_no_fixture.py.png" alt="" id="BLOGGER_PHOTO_ID_5615487456967873554" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Posted a short script to &lt;a href="http://paste.pocoo.org/show/402065/"&gt;http://paste.pocoo.org/show/402065/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Output PNG files using Pygments for the python code in a directory (used it for short snippets used in a presentation) :)&lt;br /&gt;&lt;br /&gt;(edit: Thanks to Marius for suggesting a sample.)&lt;br /&gt;&lt;br /&gt;Sample has one function highlighted (any line you want highlighted put ## at the end of the line).&lt;br /&gt;&lt;br /&gt;Currently the script has very few options - just what I needed RIGHT NOW :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22247650-8783310713948096386?l=pywinauto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pywinauto.blogspot.com/feeds/8783310713948096386/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pywinauto.blogspot.com/2011/06/creating-images-of-python-code-pygments.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/8783310713948096386'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/8783310713948096386'/><link rel='alternate' type='text/html' href='http://pywinauto.blogspot.com/2011/06/creating-images-of-python-code-pygments.html' title='Creating images of python code + pygments = WIN!'/><author><name>Mark M</name><uri>http://www.blogger.com/profile/09352622464096558516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-WZS_VxmuanI/Te44Fwk7VBI/AAAAAAAAAAQ/njXGQ6S6KYc/s72-c/_5_unittest_quotes_no_fixture.py.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22247650.post-1711460893843706330</id><published>2010-07-13T15:06:00.002+08:00</published><updated>2010-07-13T15:17:07.557+08:00</updated><title type='text'>Compiling Python modules on windows manually</title><content type='html'>So I wanted to use Pystemmer (http://snowball.tartarus.org/wrappers/PyStemmer-1.1.0.tar.gz not http://sourceforge.net/projects/pystemmer/ which seems to be out of date), but there is no included Visual Studio makefile or solution.&lt;br /&gt;&lt;br /&gt;So what to do?&lt;br /&gt;&lt;br /&gt;Below are the steps that I find work reasonably well (hopefully documented in a way that will allow other people to do the same for whatever library they are working with).&lt;br /&gt;&lt;br /&gt;Note - I assume the following:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;  The code as provided will compile with Visual C (if Visual C cannot compile it - then your job is way harder!)&lt;/li&gt;&lt;li&gt; No extra tools (autoconf, etc) are required&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;So the steps are:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Ensure directory with Python.h is in the %include% directories (menu item: Tools -&gt; Options, Projects and Solutions -&gt; VC++ Directories, Show directories for -&gt; Include Files)&lt;/li&gt;&lt;li&gt;Ensure directory with Python.lib is in the %lib% directories (as as steps for Include files - just select Library Files instead at the end)&lt;/li&gt;&lt;li&gt;In Visual Studio 2008 (for Python 2.6) select menu item  File -&gt; New -&gt; Project From Existing Code...&lt;/li&gt;&lt;li&gt;Select the directory with the downloaded code as the Project File Location&lt;/li&gt;&lt;li&gt;Give the project a name (generally a good idea to give it the name of the Python module - i.e. in my example "Stemmer" )&lt;/li&gt;&lt;li&gt;Ensure that the Release build is selected (if using the toolbar) because generally on windows you will not have the debug library: python_d.lib.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Modify the project properties:&lt;br /&gt;Set General -&gt; Configuration Type to "Dynamic Library (.dll)"&lt;br /&gt;Set file extenstion for Linker -&gt; General -&gt; Output File to ".pyd"&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Try and compile - here are some of the common problems and possible solutions:&lt;br /&gt;    &lt;ul&gt;&lt;br /&gt;        &lt;li&gt;"multiply defined symbols" &lt;blockquote&gt;&lt;br /&gt;                libstemmer_utf8.obj : error LNK2005: _sb_stemmer_length already defined in libstemmer.obj&lt;br /&gt;                ...&lt;br /&gt;                Release\Stemmer.pyd : fatal error LNK1169: one or more multiply defined symbols found &lt;/blockquote&gt; &lt;br /&gt;         The reason for this is that a symbol is defined in 2 source files, for PyStemmer this was because there is both libstemmer_utf8.c and libstemmer.c in the codebase which define the same symbols. The fix was to remove one from the project&lt;br /&gt;        &lt;/li&gt;&lt;br /&gt;        &lt;li&gt;   "Cannot open include file" &lt;blockquote&gt;&lt;br /&gt;                .\src\Stemmer.c(30) : fatal error C1083: Cannot open include file: 'libstemmer.h': No such file or directory &lt;/blockquote&gt; &lt;br /&gt;         This is a simple fix - find where the include file is and add it to the include path Project Properties dialog, C/C++ -&gt; General -&gt; Additional Include Directories&lt;br /&gt;        &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;This is as much a reminder for me - but if this helps you great :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22247650-1711460893843706330?l=pywinauto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pywinauto.blogspot.com/feeds/1711460893843706330/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pywinauto.blogspot.com/2010/07/compiling-python-modules-on-windows.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/1711460893843706330'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/1711460893843706330'/><link rel='alternate' type='text/html' href='http://pywinauto.blogspot.com/2010/07/compiling-python-modules-on-windows.html' title='Compiling Python modules on windows manually'/><author><name>Mark M</name><uri>http://www.blogger.com/profile/09352622464096558516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22247650.post-8903905073182623646</id><published>2010-04-25T13:29:00.003+08:00</published><updated>2010-04-25T13:42:13.683+08:00</updated><title type='text'>SendKeysCtypes release (for some value of released)</title><content type='html'>I finally got around to releasing SendKeysCtypes (Sending key strokes to the active app on Windows) to &lt;a href="http://bitbucket.org/markm/sendkeysctypes"&gt;http://bitbucket.org/markm/sendkeysctypes&lt;/a&gt;.&lt;p&gt;There is no setup.py yet, it is not registered on PYPI - but at least it is available.&lt;/p&gt;&lt;p&gt;I did a quick check and had to make a small change to make it work on Python 3.1 :)&lt;/p&gt;&lt;p&gt;Give it a try.&lt;/p&gt;&lt;p&gt;I would like to thank Oliver Rutherford for his sendkeys module (&lt;a href="http://www.rutherfurd.net/python/sendkeys/"&gt;http://www.rutherfurd.net/python/sendkeys/&lt;/a&gt;) which I have used for years as part of pywinauto.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;I only just realized while writing this that it is also posted to bitbucket &lt;a href="http://bitbucket.org/orutherfurd/sendkeys"&gt;http://bitbucket.org/orutherfurd/sendkeys&lt;/a&gt;)&lt;/p&gt;&lt;p&gt;The main benefits between this module and Oliver's that I can think of are:&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt; No compilation required (works on Python 3)&lt;/li&gt;&lt;li&gt;Support for Unicode Characters&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Code that works for one of these modules should work for the other also&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;br /&gt;import SendKeysCtypes&lt;br /&gt;import os, time&lt;br /&gt;os.system("start  notepad.exe")&lt;br /&gt;time.sleep(.5)&lt;br /&gt;SendKeysCtypes.SendKeys("Hello in  Notepad", with_spaces = True)&lt;br /&gt;SendKeysCtypes.SendKeys("%f")  # ALT + F  "File" menu&lt;br /&gt;SendKeysCtypes.SendKeys("x")   # Exit&lt;/blockquote&gt;&lt;pre&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22247650-8903905073182623646?l=pywinauto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pywinauto.blogspot.com/feeds/8903905073182623646/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pywinauto.blogspot.com/2010/04/sendkeysctypes-release-for-some-value.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/8903905073182623646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/8903905073182623646'/><link rel='alternate' type='text/html' href='http://pywinauto.blogspot.com/2010/04/sendkeysctypes-release-for-some-value.html' title='SendKeysCtypes release (for some value of released)'/><author><name>Mark M</name><uri>http://www.blogger.com/profile/09352622464096558516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22247650.post-4501632176100773856</id><published>2010-04-18T11:52:00.003+08:00</published><updated>2010-04-18T12:12:20.974+08:00</updated><title type='text'>I am speaking at PyCon Asia Pacific in June</title><content type='html'>I will be speaking at &lt;a href="http://pycon.sit.rp.sg/"&gt;PyCon Asia Pacific&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;My talk is titled "Writing Application Plugins in Python". I aim to show how Python can be used to implement plugin functionality for applications that never even heard of Python.&lt;br /&gt;&lt;br /&gt;The idea being, that if you write a small amount of shim code (using Pyrex/Cython to make it really easy) then you can pass most of the work off to Python. I work on Windows, and my examples will be on that OS, but very little of what I present will be specific to Windows.&lt;br /&gt;&lt;br /&gt;I am still searching around for a good Open Source application with a reasonably simple API/SDK that I can demonstrate with. Leave a comment if you have a suggestion. But the majority of the talk will be generic to any application giving introductions to the various tools and modules used.&lt;br /&gt;&lt;br /&gt;If you are in or around Singapoare in June - or feel like seeing South East Asia - then drop by :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22247650-4501632176100773856?l=pywinauto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pywinauto.blogspot.com/feeds/4501632176100773856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pywinauto.blogspot.com/2010/04/i-am-speaking-at-pycon-asia-pacific-in.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/4501632176100773856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/4501632176100773856'/><link rel='alternate' type='text/html' href='http://pywinauto.blogspot.com/2010/04/i-am-speaking-at-pycon-asia-pacific-in.html' title='I am speaking at PyCon Asia Pacific in June'/><author><name>Mark M</name><uri>http://www.blogger.com/profile/09352622464096558516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22247650.post-1708235877694139398</id><published>2010-04-18T11:41:00.003+08:00</published><updated>2010-04-18T12:56:05.856+08:00</updated><title type='text'>A small library wants to break out of pywinauto</title><content type='html'>I have been working on pywinauto for about 4 and a half years now and its not really moving in any direction. I make small tweaks here and there and make releases from time to time - but nothing major.&lt;br /&gt;&lt;br /&gt;This was the first open source project that I released and I think maybe I was a little over-enthusiastic :). I had hoped that I would be using it myself, I also wished it to be functional and easy enough thatthat it could replace expensive commercial software with similar functionality (but with their own annoying languages). But I am no longer working with said software and my main focus went to other things.&lt;br /&gt;&lt;br /&gt;I believe now that pywinauto should be split. There is at least 1 small library (and probobaly more) that should be freed from the overall project.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;Get information from windows controls (Maybe of the questions on the pywinauto list is how to get the values from text boxes, etc.)&lt;/li&gt;&lt;li&gt;A &lt;span style="font-weight: bold;"&gt;library&lt;/span&gt; for automating Windows, not an auotmation framework/language - a library. Meaning that it is up to the user to delay between clicks for windows to open/close. It is up to the user how they want to select controls.&lt;/li&gt;&lt;li&gt;SendKeysCtypes (I re-wrote &lt;a href="http://www.rutherfurd.net/python/sendkeys/"&gt;Python SendKeys&lt;/a&gt; so that it would support Unicode and not need to be compiled (uses Ctypes). This is more or less ready to release - I just haven't gotten around to doing that :(.  (if you need it - grab it from &lt;a href="https://svn.openqa.org/svn/pywinauto/trunk/pywinauto/SendKeysCtypes.py"&gt;Pywinauto SVN&lt;/a&gt;)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;pywinauto - which would use these previous components but would be much smaller itself, it would work as it does now, trying to help the user as much as possible in not having to worry about timing issues.&lt;/li&gt;&lt;/ul&gt;Seeing as it turned out that &lt;span style="font-weight: bold;"&gt;*I*&lt;/span&gt; don't really need an automation library/toolkit - it would be great to get some help with some of this work.&lt;br /&gt;&lt;br /&gt;Other directions I am thinking of are providing modules so that pywinauto (or the gui automation libarary) can work as an almost direct replacement of things like &lt;a href="http://www.autohotkey.com/"&gt;AutoHotkey&lt;/a&gt; or &lt;a href="http://www.autoitscript.com/autoit3/index.shtml"&gt;AutoIT&lt;/a&gt; or use a similar API as &lt;a href="http://ldtp.freedesktop.org/wiki/"&gt;LDTP&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I also need to fix the Pywinauto web presence - which is amazingly scattered - but this post is already long enough.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22247650-1708235877694139398?l=pywinauto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pywinauto.blogspot.com/feeds/1708235877694139398/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pywinauto.blogspot.com/2010/04/small-library-wants-to-break-out-of.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/1708235877694139398'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/1708235877694139398'/><link rel='alternate' type='text/html' href='http://pywinauto.blogspot.com/2010/04/small-library-wants-to-break-out-of.html' title='A small library wants to break out of pywinauto'/><author><name>Mark M</name><uri>http://www.blogger.com/profile/09352622464096558516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22247650.post-2742893360611149545</id><published>2010-03-07T22:20:00.002+08:00</published><updated>2010-03-07T22:39:55.087+08:00</updated><title type='text'>Added functions to betterbatch and debugging on the horizon</title><content type='html'>I was expecting function to be not so hard (just another way of&lt;br /&gt;running a few steps) but it took a little bit of time all the same.&lt;p&gt;I got it implemented (though no tests for it yet) and it seems OK, I&lt;br /&gt;will know better how it works when I get around to using it (hopefully&lt;br /&gt;in the next week). Weekends for the tool and weekdays for using the&lt;br /&gt;tool in production :)&lt;/p&gt;&lt;p&gt;With this addition I think the language definition is more or less&lt;br /&gt;complete I think. I can imagine tweaking it a bit, fixing bugs etc,&lt;br /&gt;but I don't expect to implement many other language constructs.&lt;/p&gt;&lt;p&gt;One of the next things that I am planning to implement is a simple&lt;br /&gt;debugger (step through statements, print variable value, maybe change&lt;br /&gt;variable values, etc). I was expecting this to be a fairly major&lt;br /&gt;undertaking but again Python and it's community come to the rescue.&lt;br /&gt;Right on cue&lt;/p&gt;&lt;p&gt;a) Catherine Devlin mentioned cmd2 on her blog,&lt;br /&gt;&lt;a href="http://catherinedevlin.blogspot.com/2008/01/introducing-cmd2.html"&gt;http://catherinedevlin.blogspot.com/2008/01/introducing-cmd2.html&lt;/a&gt;&lt;br /&gt;which made me look at cmd in the Python standard library&lt;br /&gt;b) I found the Python documentation a bit dry (or else I had very&lt;br /&gt;little patience) so googled for some examples - and Doug Hellmann's&lt;br /&gt;excellent PyMOTW (&lt;a href="http://blog.doughellmann.com/2008/05/pymotw-cmd.html"&gt;http://blog.doughellmann.com/2008/05/pymotw-cmd.html&lt;/a&gt;&lt;br /&gt;if you don't know it - bookmark it!) popped up with some good examples&lt;br /&gt;and great documentation.&lt;/p&gt;&lt;p&gt;I found that I was able to throw together a simple debugger (next,&lt;br /&gt;print_var, print_vars, etc)&lt;/p&gt;&lt;p&gt;So this means that a debugger is really easy to write - and is a much smaller task than I was hoping. Maybe next weekend I get the debugger implementation finished.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22247650-2742893360611149545?l=pywinauto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pywinauto.blogspot.com/feeds/2742893360611149545/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pywinauto.blogspot.com/2010/03/added-functions-to-betterbatch-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/2742893360611149545'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/2742893360611149545'/><link rel='alternate' type='text/html' href='http://pywinauto.blogspot.com/2010/03/added-functions-to-betterbatch-and.html' title='Added functions to betterbatch and debugging on the horizon'/><author><name>Mark M</name><uri>http://www.blogger.com/profile/09352622464096558516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22247650.post-4871479761498684862</id><published>2010-03-02T21:54:00.002+08:00</published><updated>2010-03-02T21:57:09.201+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='betterbatch'/><title type='text'>BetterBatch released</title><content type='html'>I have released BetterBatch (&lt;a href="http://code.google.com/p/betterbatch/"&gt;http://code.google.com/p/betterbatch/&lt;/a&gt;)&lt;br /&gt;and I would like more people to know about it.&lt;p&gt;I created it as something that I could use at work. We have many tasks&lt;br /&gt;that require adhoc automations which may have different people running&lt;br /&gt;them. These automations may not have a very long life so it often&lt;br /&gt;doesn't make sense to write it up as Python/Perl script. This work is&lt;br /&gt;done on Windows machines so not many of us (me included) do not have a&lt;br /&gt;lot of experience with shell scripting. Even if we did - shell&lt;br /&gt;scripting wouldn't necessarily be the ideal candidate.&lt;/p&gt;&lt;p&gt;So it was designed as a batch file replacement with some improvements:&lt;br /&gt;Some requirements I had while making this:&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;output from commands can be assigned to variables&lt;/li&gt;&lt;li&gt;  it needs to be just as easy to call external applications as a batch file&lt;/li&gt;&lt;li&gt;all actions should be logged&lt;/li&gt;&lt;li&gt;the return value of everything should be checked (and stop the script on error!)&lt;/li&gt;&lt;li&gt;  it should be prettier than a batch file&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;I have not tested this on any *nix style machine yet - but believe it&lt;br /&gt;should work (meaning that it probably won't work at first - but I am&lt;br /&gt;hoping that minimal changes will make it work)&lt;/p&gt;&lt;p&gt;Give it a try  (please :) )&lt;br /&gt;Download: &lt;a href="http://code.google.com/p/betterbatch/downloads/list"&gt;http://code.google.com/p/betterbatch/downloads/list&lt;/a&gt;&lt;br /&gt;Log an issue: &lt;a href="http://code.google.com/p/betterbatch/issues/entry"&gt;http://code.google.com/p/betterbatch/issues/entry&lt;/a&gt;&lt;br /&gt;Discuss: &lt;a href="http://groups.google.com/group/betterbatch-discuss/topics"&gt;http://groups.google.com/group/betterbatch-discuss/topics&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22247650-4871479761498684862?l=pywinauto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pywinauto.blogspot.com/feeds/4871479761498684862/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pywinauto.blogspot.com/2010/03/back-to-blogging.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/4871479761498684862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/4871479761498684862'/><link rel='alternate' type='text/html' href='http://pywinauto.blogspot.com/2010/03/back-to-blogging.html' title='BetterBatch released'/><author><name>Mark M</name><uri>http://www.blogger.com/profile/09352622464096558516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22247650.post-114737463733133277</id><published>2006-05-12T03:04:00.000+08:00</published><updated>2007-02-02T20:36:17.126+08:00</updated><title type='text'>Screencast on ShowMeDo</title><content type='html'>I have been quiet for a while - and no new releases of pywinauto for a bit either. &lt;br /&gt;&lt;br /&gt;I finally figured out that my metaclass problem was not a metaclass problem at all - but a logic problem in my code :-)&lt;br /&gt;&lt;br /&gt;I merged in that code into the trunk - and I should do another release soon (a small one!). This week has been busy - been in training almost all week - so that is feeding my programming need (and making me not want to touch the computer - some direct user queries always get me going - so if you have one let me know).&lt;br /&gt;&lt;br /&gt;The next few weeks will be very busy&lt;br /&gt;&lt;ul&gt;&lt;li&gt;with maybe a trip to San Francisco&lt;/li&gt;&lt;li&gt;my parents coming on the 19th and being around for a week&lt;/li&gt;&lt;li&gt;the day they leave then off on vacation :-) (for 10 days)&lt;/li&gt;&lt;/ul&gt;So next release will be the last one for some week (probably).&lt;br /&gt;&lt;br /&gt;Finally my reason for posting - Jeff has done a nice screencast of pywinauto at:&lt;br /&gt;&lt;a href="http://showmedo.com/videos/video?name=UsingpyWinAutoToControlAWindowsApplication&amp;fromSeriesID=7"&gt;http://showmedo.com/videos/video?name=UsingpyWinAutoToControlAWindowsApplication&amp;fromSeriesID=7&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Thank you Jeff!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22247650-114737463733133277?l=pywinauto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pywinauto.blogspot.com/feeds/114737463733133277/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pywinauto.blogspot.com/2006/05/screencast-on-showmedo.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/114737463733133277'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/114737463733133277'/><link rel='alternate' type='text/html' href='http://pywinauto.blogspot.com/2006/05/screencast-on-showmedo.html' title='Screencast on ShowMeDo'/><author><name>Mark Mc Mahon</name><uri>http://www.blogger.com/profile/13173865151939176401</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22247650.post-114600316304198144</id><published>2006-04-26T05:42:00.000+08:00</published><updated>2006-04-26T06:12:43.053+08:00</updated><title type='text'>How to work with Metaclasses</title><content type='html'>I just released another version of pywinauto - and I am quite happy with it. I even squeezed some more performance improvements (it is now approximately 10-20% faster then the previous release - though I think it will be waiting for the application itself to respond most of the time!).&lt;br /&gt;&lt;br /&gt;One thing that I had wanted to make into this release was a change from using a function to return the correct control Wrapper class, to having a __metaclass__ attribute in the base class, and add functionality to it's __new__ method.&lt;br /&gt;&lt;br /&gt;something like:  (paraphrased - not run!)&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class MetaWrapper(type):&lt;br /&gt;   registry = {}&lt;br /&gt;&lt;br /&gt;   # this is called when each class is defined&lt;br /&gt;   def __init__(cls, name, bases, attrs):&lt;br /&gt;       # add information defined in cls to the registry&lt;br /&gt;       # so that later we can return the correct class&lt;br /&gt;&lt;br /&gt;   def GetWrapper(handle):&lt;br /&gt;       # look in registry for correct class&lt;br /&gt;       return correct_class&lt;br /&gt;   GetWrapper = staticmethod(GetWrapper)&lt;br /&gt;&lt;br /&gt;class HwndWrapper(object):&lt;br /&gt;   __metaclass__ = MetaWrapper&lt;br /&gt;&lt;br /&gt;   # called before each instance is created&lt;br /&gt;   def __new__(cls, handle):&lt;br /&gt;       correct_class = cls.GetWrapper(handle)&lt;br /&gt;&lt;br /&gt;       # need to call base __new__ ?&lt;br /&gt;       obj = correct_class.__new__(correct_class)&lt;br /&gt;&lt;br /&gt;       # as we are returning a different class from HwndWrapper we need to&lt;br /&gt;       # initialize it&lt;br /&gt;       obj.__init__(handle)&lt;br /&gt;       return obj&lt;br /&gt;&lt;br /&gt;   def __init__(self, handle):&lt;br /&gt;       # rest of stuff here&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;But I was getting errors I could not explain! Now that I write that out - there were times when I &lt;span style="font-weight: bold;"&gt;was&lt;/span&gt; returning a HwndWrapper instance, would that mean that it was getting initialized twice? I don't think that would have caused the problems I was seeing (but then again - I can't think of anything else either!)&lt;br /&gt;&lt;br /&gt;Maybe one of you out there who knows this magic better can set me on the right track. Is this even something that I should be using - or are meta classes too much magic most of the time?&lt;br /&gt;&lt;br /&gt;Anyway - happy pythoneering :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22247650-114600316304198144?l=pywinauto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pywinauto.blogspot.com/feeds/114600316304198144/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pywinauto.blogspot.com/2006/04/how-to-work-with-metaclasses.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/114600316304198144'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/114600316304198144'/><link rel='alternate' type='text/html' href='http://pywinauto.blogspot.com/2006/04/how-to-work-with-metaclasses.html' title='How to work with Metaclasses'/><author><name>Mark Mc Mahon</name><uri>http://www.blogger.com/profile/13173865151939176401</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22247650.post-114262063189323479</id><published>2006-03-18T02:12:00.000+08:00</published><updated>2006-03-20T04:29:59.303+08:00</updated><title type='text'>Somethings are hard and something weren't mean to be easy  - but nothing is impossible ;-)</title><content type='html'>&lt;span style="font-family:arial;"&gt;Well I finally managed it. (well 80% of it!).&lt;br /&gt;&lt;br /&gt;What am I talking about? 'Application data' where you save information from one run of an automated GUI run and use that information next time to work with changed software (in my case Translated to a different spoken language!).&lt;br /&gt;&lt;br /&gt;There is still one small part that I want to implement before I release a 0.3.0 release. Currently it works for dialogs, controls and menu's - but I still need to implement looking up appdata for selecting items in controls (listboxes, treeviews, etc)&lt;br /&gt;&lt;br /&gt;The implementation is very basic - and certain things will not work without some form of user override (e.g. selecting the correct item in a sorted listbox/combobox). Unfortunately there is no override available (but I think I will need to look into that soon).&lt;br /&gt;&lt;br /&gt;The internal handling of appdata may well change (almost certainly) - but there is very little that a user uses at the moment - so not a big impact I think!&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;This code does not affect normal operation - so I am not worried about this code causing regressions in the normal use case if just automating a GUI.&lt;br /&gt;&lt;br /&gt;So for now I feel I have a working proof of concept - but I think I need to put more work into making it a robust, workable solution.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22247650-114262063189323479?l=pywinauto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pywinauto.blogspot.com/feeds/114262063189323479/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pywinauto.blogspot.com/2006/03/somethings-are-hard-and-something.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/114262063189323479'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/114262063189323479'/><link rel='alternate' type='text/html' href='http://pywinauto.blogspot.com/2006/03/somethings-are-hard-and-something.html' title='Somethings are hard and something weren&apos;t mean to be easy  - but nothing is impossible ;-)'/><author><name>Mark Mc Mahon</name><uri>http://www.blogger.com/profile/13173865151939176401</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22247650.post-114202142076991121</id><published>2006-03-11T04:01:00.000+08:00</published><updated>2006-03-11T04:12:14.666+08:00</updated><title type='text'>Passionate users, marketing and screencasts,</title><content type='html'>Wow - seems like I have at least one &lt;a href="http://headrush.typepad.com/"&gt;passionate user.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Jeff has been helping my make my wiki suck less :-) and he put together a nice little screencast of using pywinauto to automate Notepad.&lt;br /&gt;&lt;br /&gt;Please go watch it at:  &lt;a href="http://pywinauto.pbwiki.com"&gt;http://pywinauto.pbwiki.com&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;He has been coaching me a bit on marketing too - though I can't say pywinauto has the same problem as &lt;a href="http://www.artima.com/weblogs/viewpost.jsp?thread=150515"&gt;Python&lt;/a&gt; ;-). Though I feel that pywinauto is on the same level as many commercial automation tools, and it uses Python which is so far beyond many automation scripting languages.&lt;br /&gt;&lt;br /&gt;Have a good weekend everyone.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22247650-114202142076991121?l=pywinauto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pywinauto.blogspot.com/feeds/114202142076991121/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pywinauto.blogspot.com/2006/03/passionate-users-marketing-and.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/114202142076991121'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/114202142076991121'/><link rel='alternate' type='text/html' href='http://pywinauto.blogspot.com/2006/03/passionate-users-marketing-and.html' title='Passionate users, marketing and screencasts,'/><author><name>Mark Mc Mahon</name><uri>http://www.blogger.com/profile/13173865151939176401</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22247650.post-114184040006188830</id><published>2006-03-09T01:34:00.000+08:00</published><updated>2006-11-09T05:32:52.476+08:00</updated><title type='text'>Setting the foreground window</title><content type='html'>Ever found it annoying when you start an application that takes a long time to start up , start working on other things and the application decides to popup and annoy you after/while it starts up?&lt;br /&gt;&lt;br /&gt;Well you can now do the same with pywinauto :-)&lt;br /&gt;&lt;br /&gt;I had tried to get this right before and hadn't succeeded - but I managed it today. HwndWrapper.SetFocus will now make the window the foreground window - even if it is not  the current foreground window.&lt;br /&gt;&lt;br /&gt;This was easy enough really - and I had thought that I had tried this already - but obviously hadn't :-(&lt;br /&gt;&lt;br /&gt;Here is the new SetFocus method...&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;    def SetFocus(self):&lt;br /&gt;      """Set the focus to this control&lt;br /&gt;&lt;br /&gt;      Activate the window if necessary"""&lt;br /&gt;&lt;br /&gt;      # find the current foreground window&lt;br /&gt;      cur_foreground = win32functions.GetForegroundWindow()&lt;br /&gt;&lt;br /&gt;      # if it is already foreground then just return&lt;br /&gt;      if self.handle != cur_foreground:&lt;br /&gt;&lt;br /&gt;          # get the thread of the window that is in the foreground&lt;br /&gt;          cur_fore_thread = win32functions.GetWindowThreadProcessId(&lt;br /&gt;              cur_foreground, 0)&lt;br /&gt;&lt;br /&gt;          # get the thread of the window that we want to be in the foreground&lt;br /&gt;          control_thread = win32functions.GetWindowThreadProcessId(self, 0)&lt;br /&gt;&lt;br /&gt;          # if a different thread owns the active window&lt;br /&gt;          if cur_fore_thread != control_thread:&lt;br /&gt;              # Attach the two threads and set the foreground window&lt;br /&gt;              win32functions.AttachThreadInput(&lt;br /&gt;                  cur_fore_thread, control_thread, True)&lt;br /&gt;&lt;br /&gt;              win32functions.SetForegroundWindow(self)&lt;br /&gt;&lt;br /&gt;              # detach the thread again&lt;br /&gt;              win32functions.AttachThreadInput(&lt;br /&gt;                  cur_fore_thread, control_thread, False)&lt;br /&gt;&lt;br /&gt;          else:   # same threads - just set the foreground window&lt;br /&gt;              win32functions.SetForegroundWindow(self)&lt;br /&gt;&lt;br /&gt;          # make sure that we are idle before returning&lt;br /&gt;          win32functions.WaitGuiThreadIdle(self)&lt;br /&gt;&lt;br /&gt;          # only sleep if we had to change something!&lt;br /&gt;          time.sleep(.06)&lt;br /&gt;&lt;br /&gt;      return self&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And here is a short bit of code you can test it with&lt;br /&gt;&lt;pre&gt;from pywinauto.application import Application&lt;br /&gt;import time&lt;br /&gt;&lt;br /&gt;app = Application.start("Notepad.exe")&lt;br /&gt;app.UntitledNotepad.MenuSelect("Format-&gt;Font")&lt;br /&gt;&lt;br /&gt;for i in range(4):&lt;br /&gt;  time.sleep(2)&lt;br /&gt;  app.Font.Edit1.SetFocus()&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you run that code and work with other windows - then the Notepad Font dialog will popup (annoyingly :-) ) every 2 seconds.&lt;br /&gt;&lt;br /&gt;All is left now is to add a call to this method in those other methods that REQUIRE the window to have focus (TypeKeys() for sure, maybe the ...Input() methods - but they probably require a WindowFromPoint/RealChildWindowFromPoint/ChildWindowFromPoint call first to ensure it's necessary).&lt;br /&gt;&lt;br /&gt;(all happy with myself for getting that off the todo list - except it wasn't on the todo list :-D )&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22247650-114184040006188830?l=pywinauto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pywinauto.blogspot.com/feeds/114184040006188830/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pywinauto.blogspot.com/2006/03/setting-foreground-window.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/114184040006188830'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/114184040006188830'/><link rel='alternate' type='text/html' href='http://pywinauto.blogspot.com/2006/03/setting-foreground-window.html' title='Setting the foreground window'/><author><name>Mark Mc Mahon</name><uri>http://www.blogger.com/profile/13173865151939176401</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22247650.post-114175171337183349</id><published>2006-03-08T01:10:00.000+08:00</published><updated>2006-03-08T01:15:13.390+08:00</updated><title type='text'>Released 0.2.5 prior to Boston-PIG meeting</title><content type='html'>I wanted to roll up my various changes before I give my presentation to Boston-Pig meeting this Thursday.&lt;br /&gt;&lt;br /&gt;Also I will be traveling next Monday to Europe for work, that might mean that I can do more work on pywinauto - but it also might mean that I can do much less.&lt;br /&gt;&lt;br /&gt;Going forward I have more refactoring to do (probably code breaking - but I can leave methods in and deprecate them for a release or two), and I still need to work on the functionality that allows a script to work unchanged on different langauges.&lt;br /&gt;&lt;br /&gt;Have fun :-) - and don't worry about asking me questions or letting me know if you are using pywinauto - I really really don't get a lot of mails :-) (It is only since releasing my own package that I notice how little feedback I have given to others in the past!).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22247650-114175171337183349?l=pywinauto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pywinauto.blogspot.com/feeds/114175171337183349/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pywinauto.blogspot.com/2006/03/released-025-prior-to-boston-pig.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/114175171337183349'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/114175171337183349'/><link rel='alternate' type='text/html' href='http://pywinauto.blogspot.com/2006/03/released-025-prior-to-boston-pig.html' title='Released 0.2.5 prior to Boston-PIG meeting'/><author><name>Mark Mc Mahon</name><uri>http://www.blogger.com/profile/13173865151939176401</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22247650.post-114172448218785221</id><published>2006-03-07T17:06:00.000+08:00</published><updated>2006-03-08T01:21:59.953+08:00</updated><title type='text'>Usability, Consistency - RULES!</title><content type='html'>I just read an interesting list of  "new laws"  at http://pfeifferreport.com/trends/trend_userexperience.html (found from http://pyre.third-bit.com/blog/archives/000414.html (found from http://planet.python.org/index.html) .&lt;br /&gt;&lt;br /&gt;I find that a number of these resonate strongly with me, and put in words some of what I am trying to achieve with pywinauto.&lt;br /&gt;&lt;br /&gt;I should print the list and post it above my desk - then when I go to refactor or add new code I can ask myself if the changes obey the rules :-) (I think 6, 8 and 9 are the ones that will be most useful day to day).&lt;br /&gt;&lt;br /&gt;Getting the text of a container control is maybe not that critical for the everyday user of pywinauto - but it should be easy to find if they do need it. Here are some examples of how inconsistent this is at the moment...&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  listbox.ItemTexts()[item_index]&lt;br /&gt;  ListView.GetItem(item_index, subitem_index)['text']  # returned item is just a dict&lt;br /&gt;  TreeView.GetItem(0,2,4).Text()&lt;br /&gt;  Header.GetColumnText(col_index)&lt;br /&gt;  Statusbar.GetPartText(part_index) # at least these last two are similar&lt;br /&gt;  Rebar.GetBand(band_index).text # attribute set in returned ctypes structure!&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;These kinds of inconsistencies do not help anyone learn pywinauto (I hadn't realized it was so bad :-) )&lt;br /&gt;&lt;br /&gt;Just as a counter point to above - it's not all so bad.&lt;br /&gt;control.Select() is defined for most classes and behaves (hopefully) more or less as expected.&lt;br /&gt;&lt;br /&gt;So - going forward I am going to try and ensure usability and consistency of pywinauto.&lt;br /&gt;&lt;br /&gt;The other point is documentation - there IS documentation for pywinauto - but I definitely do not consider myself a tech writer. From reading the rules - it also occurred to me that my documentation is lacking in a major way - it is not easy to find what you are looking for.&lt;br /&gt;I think a new set of pages which describe in a succinct way how to work with controls will help.&lt;br /&gt;&lt;br /&gt;E.g.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Operations on controls:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;ListBox&lt;br /&gt;     Select&lt;br /&gt;     SetFocus&lt;br /&gt;     GetFocus&lt;br /&gt;ListView&lt;br /&gt;     Select&lt;br /&gt;     IsSelected&lt;br /&gt;     IsChecked&lt;br /&gt;     Check&lt;br /&gt;     UnCheck&lt;br /&gt;     IsFocused&lt;br /&gt;TreeView&lt;br /&gt;     Select&lt;br /&gt;     ...&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Even the list by itself helps - in that it would allow you to see what is available more easily then browsing the current documentation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22247650-114172448218785221?l=pywinauto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pywinauto.blogspot.com/feeds/114172448218785221/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pywinauto.blogspot.com/2006/03/usability-consistency-rules.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/114172448218785221'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/114172448218785221'/><link rel='alternate' type='text/html' href='http://pywinauto.blogspot.com/2006/03/usability-consistency-rules.html' title='Usability, Consistency - RULES!'/><author><name>Mark Mc Mahon</name><uri>http://www.blogger.com/profile/13173865151939176401</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22247650.post-114081827426643572</id><published>2006-02-25T04:29:00.000+08:00</published><updated>2006-02-25T06:00:00.536+08:00</updated><title type='text'>Wow - lots of stuff to try and remember...</title><content type='html'>I guess this little blog will get lost in the flood of PyCon blog stuff - or else everyone will be so busy at PyCon that this entry will stand out (whether that's a good thing or not I am not sure :-)&lt;br /&gt;&lt;br /&gt;It sounds like there are one or two people actively using pywinauto - and I am getting some feedback, some bug reports, some suggestions - It's great - but I need to be organized so I don't loose it. So I am going to put some of it here...&lt;br /&gt;&lt;br /&gt;First of all there is a Python meetup in Boston on Thursday 9th of March, and if I can get my act together (a Powerpoint presentation and a good demo I guess?) then I will be presenting pywinauto.&lt;br /&gt;&lt;br /&gt;So here are the things I want to track&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Some applications implement menu's as Toolbars (Internet Explorer for one) and of course MenuSelect() or &lt;span style="font-family:courier new;"&gt;MenuClick()&lt;/span&gt; doesn't work on those. I need to research if there is some style or setting that says a toolbar button will actually popup a menu. If there is I can update the MenuSelect/MenuClick function to use them, but if not they you will have to document to use one of the following methods:&lt;br /&gt;  &lt;span style="font-family:courier new;"&gt;app.dlg.TypeKeys("%FWF")  # &amp;File-&gt;Ne&amp;amp;amp;w-&gt;&amp;amp;Folder&lt;/span&gt;&lt;br /&gt;or&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  # this functionality is not implemented yet - still&lt;br /&gt;# need to change the interface&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; to Toolbar buttons.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  app.dlg.Toolbar.Button("File").Click()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  app.PopupMenu.MenuSelect("New-&gt;Folder")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For now I should just update the documentation (as I feel that will be the final outcome anyway). Especially as the example given was a control with class WTL_CommandBar (which is a different kettle of fish completely!)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;I wanted to add my reasoning for creating pywinauto to the documentation and say why I think it is better then a lot of automation tools out there (the idea at least - I hope the implementation doesn't let it down!)&lt;/li&gt;&lt;li&gt;Some way of specifying unique text when looking for a control. For example if you look for a control with the text "Click this button to save as PNG" (maybe there are other buttons "Click this button to save as XXX", etc), then it would be nice if &lt;span style="font-family:courier new;"&gt;app.dlg.PNG.Click()&lt;/span&gt;  would work - but it doesn't :-(. The reason is that the matching algorithm I use (using difflib) takes the overall text match - and the match of PNG in the overall text is low.&lt;br /&gt;The reason that I do not just select the best match (original code did do this) is that it matches sometimes when you don't want to. For example if you want to check if a dialog exists for example you could &lt;span style="font-family:georgia;"&gt;write&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;  if app.dlg.Exists():&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       # do something because this dialog exists&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;&lt;br /&gt;but if the searching is not strict enough it will find other dialogs and the script will be broken (and it might be hard to fix). Currently the way around is either specify more of the text:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   app.dlg.&lt;/span&gt;&lt;/span&gt;ClickbuttontosaveasPNG.Click()&lt;/span&gt;&lt;br /&gt;or use the window_ method...&lt;br /&gt; &lt;span style="font-family:courier new;"&gt;  app.dlg.window_(title_re =".*PNG$").Click()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-family:georgia;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;One idea was possibly to allow something like&lt;/span&gt;&lt;br /&gt; app.dlg.PNG_IN_.Click()&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;or maybe&lt;/span&gt;&lt;br /&gt; app.dlg[".*PNG$_RE_"].Click()&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;where the _IN_ and _RE_ specify that the text should be 'in' or should be tested using a regular expression.  I am not sure about either of these as they appear to be a bit 'magic'.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-family:georgia;"&gt;Finish off the Wait* functions. Currently in application.WindowSpecification (which is the class you get if you do app.dlg, or app.dlg.ctrl) there are the following methods:&lt;br /&gt;&lt;/span&gt;    Exists(self, timeout = exists_timeout))&lt;br /&gt;  WaitReady(self, timeout = window_find_timeout, wait_interval = window_retry_interval)&lt;br /&gt;  WaitNotEnabled(self, timeout = window_find_timeout, wait_interval = window_retry_interval)&lt;br /&gt;  WaitNotVisible(self, timeout = window_find_timeout, wait_interval = window_retry_interval)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;These should all have the same signature, and then I need to fill out the rest of the methods ^Wait(Not)?(Enabled|Visible|Ready)$. Though just writing that and thinking of duplicated lines of code - maybe I should just have a Wait() method e.g.&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    app.dlg.control.Wait(enabled = True, Visible = False)&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;would return the control being waited for once it is both Enabled and Hidden (unlikely to be very useful :-) or return None on timeout (or should it raise an exception?)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Clear up where to look for appropriate methods. Most methods are in the control wrapper for that particular control (or it's base class(es)) but some (important) methods are in WindowManager. So to be clear the available methods for a particular window are the union of&lt;br /&gt; - methods of WindowSpecification&lt;br /&gt; - methods of the Wrapper for this control&lt;br /&gt; - methods of the base class(s) of the wrapper&lt;/li&gt;&lt;li&gt;Look into pyAA to help getting information from 'difficult' controls (and possibly other uses for it too!)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Then all my various ToDo items:&lt;br /&gt;- Implement 'application data' that will allow the same script to run on many languages&lt;br /&gt;- Implement basic Recording functionality&lt;br /&gt;- Lots more of everything (wrapped controls, tests, examples, documentation, etc)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22247650-114081827426643572?l=pywinauto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pywinauto.blogspot.com/feeds/114081827426643572/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pywinauto.blogspot.com/2006/02/wow-lots-of-stuff-to-try-and-remember.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/114081827426643572'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/114081827426643572'/><link rel='alternate' type='text/html' href='http://pywinauto.blogspot.com/2006/02/wow-lots-of-stuff-to-try-and-remember.html' title='Wow - lots of stuff to try and remember...'/><author><name>Mark Mc Mahon</name><uri>http://www.blogger.com/profile/13173865151939176401</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22247650.post-114005463325479031</id><published>2006-02-16T09:45:00.000+08:00</published><updated>2006-02-16T10:12:46.536+08:00</updated><title type='text'>Test Infected</title><content type='html'>I haven't gotten around to reading much of the XP material (well a little online), but with pywinauto I finally started to do some unit tests. Even though my coverage is still quite minimal - I don't have even one test per method yet (and some require more then that!) - I have found that it has helped me to find numerous bugs that I hadn't known about - or wouldn't have known about until I released!&lt;br /&gt;&lt;br /&gt;I end up running the tests or at least part of the tests frequently. I am not quite to the point where I am first creating a test for the functionality that I have yet to code.&lt;br /&gt;&lt;br /&gt;I now understand why tests make refactoring easy - you change your code until you feel it is refrigerator ready - then you run your tests and make sure that they run like they did before you ripped out that gangrenous rotting piece of code that you smelled last week. :-)&lt;br /&gt;&lt;br /&gt;The next thing that I need to do is to add the examples to the tests - that way I will have some 'integration' tests along with all the unit tests. :-)&lt;br /&gt;&lt;br /&gt;I feel a release coming soon - and then I think I may need to take it easy for a little while.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22247650-114005463325479031?l=pywinauto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pywinauto.blogspot.com/feeds/114005463325479031/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pywinauto.blogspot.com/2006/02/test-infected.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/114005463325479031'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/114005463325479031'/><link rel='alternate' type='text/html' href='http://pywinauto.blogspot.com/2006/02/test-infected.html' title='Test Infected'/><author><name>Mark Mc Mahon</name><uri>http://www.blogger.com/profile/13173865151939176401</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22247650.post-113971402494032679</id><published>2006-02-12T10:58:00.000+08:00</published><updated>2006-02-12T11:15:06.766+08:00</updated><title type='text'>It's not only my code!</title><content type='html'>I made some progress this evening - but I seem to be doing more refactoring and catching up on unit test implementation then adding much to the code base.&lt;br /&gt;&lt;br /&gt;I have a lot of firsts (for me) with pywinauto.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;First project I release publicly&lt;/li&gt;&lt;li&gt;First time I have ever written a unit test (yeah I know - bad :-)&lt;/li&gt;&lt;li&gt;First time I have ever had to worry about non functional changes I make to code affecting others (Like changing the interfaces of classes)&lt;/li&gt;&lt;li&gt;First time I have used subversion or used SourceForge for hosting a project&lt;/li&gt;&lt;li&gt;First time I ever thought of blogging (and maybe you are wishing I never DID!)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;I'm enjoying the experience - and I think I am learning quite a bit. Here's hoping that my code is useful and I don't waste people's time with either bugs or excessive changes. &lt;/p&gt;&lt;p&gt;Maybe I should think of having the subversion repository hosted somewhere public - so that other's have a chance of contributing and keeping me in line. I think for now there is lots I can do myself, and I am not sure I want to anyway. I am not sure I have enough experience to be able to do it successfully - and with amazing tools like Python and ctypes - there is a lot one person can do :-)&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22247650-113971402494032679?l=pywinauto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pywinauto.blogspot.com/feeds/113971402494032679/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pywinauto.blogspot.com/2006/02/its-not-only-my-code.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/113971402494032679'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/113971402494032679'/><link rel='alternate' type='text/html' href='http://pywinauto.blogspot.com/2006/02/its-not-only-my-code.html' title='It&apos;s not only my code!'/><author><name>Mark Mc Mahon</name><uri>http://www.blogger.com/profile/13173865151939176401</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22247650.post-113958100164130015</id><published>2006-02-10T22:06:00.000+08:00</published><updated>2006-02-10T22:29:22.353+08:00</updated><title type='text'>Packages, smackages!</title><content type='html'>I had never created a package before working on pywinauto. I just made scripts and if they required other python files that I wrote then I just stuck them in the same directory and imported them from there&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;import myotherscipt&lt;/span&gt;&lt;/blockquote&gt;Then I decided for pywinauto to try and move things around and be better organized - so I created some packages pywinauto.controls and pywinauto.tests.&lt;br /&gt;&lt;br /&gt;What feels strange to me is that these packages are not self contained, I don't mind having to rely on class capabilities defined in other packages (e.g. when testing - that the controls passed in have a &lt;span style="font-family:courier new;"&gt;Rectangle()&lt;/span&gt; method) but I don't like having to &lt;span style="font-family:courier new;"&gt;import pywinauto.win32defines&lt;/span&gt; or other modules from pywinauto. It seems to me that packages should be more self contained then that?&lt;br /&gt;&lt;br /&gt;Should I just do away with these packages and have everything as a flat structure? Should I re-structure so that the parts of pywinauto that I do have to import are in a package of their own (that does not need anything from pywinauto)?&lt;br /&gt;&lt;br /&gt;Well it looks like &lt;span style="font-family:courier new;"&gt;__path__ &lt;/span&gt;is what I need. I guess my &lt;span style="font-family:courier new;"&gt;pywinauto.controls&lt;/span&gt; is not really a package - and I want a directory just for organization. I think &lt;span style="font-family:courier new;"&gt;pywinauto.tests &lt;/span&gt;is a package - as I need to initialize it, and I expect it to always be imported by using &lt;span style="font-family:courier new;"&gt;import tests&lt;/span&gt; (or &lt;span style="font-family:courier new;"&gt;import pywinauto.tests&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;hmm - a little more analysis needed I guess to resolve those dependencies.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22247650-113958100164130015?l=pywinauto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pywinauto.blogspot.com/feeds/113958100164130015/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pywinauto.blogspot.com/2006/02/packages-smackages.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/113958100164130015'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/113958100164130015'/><link rel='alternate' type='text/html' href='http://pywinauto.blogspot.com/2006/02/packages-smackages.html' title='Packages, smackages!'/><author><name>Mark Mc Mahon</name><uri>http://www.blogger.com/profile/13173865151939176401</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22247650.post-113957796399940162</id><published>2006-02-10T21:24:00.000+08:00</published><updated>2006-02-10T21:39:01.846+08:00</updated><title type='text'>New blog - marketing for pywinauto</title><content type='html'>Never thought I would start writing a blog - but it seems to be an important marketing medium for open source projects - so I guess it can't hurt too much :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22247650-113957796399940162?l=pywinauto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pywinauto.blogspot.com/feeds/113957796399940162/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pywinauto.blogspot.com/2006/02/new-blog-marketing-for-pywinauto.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/113957796399940162'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22247650/posts/default/113957796399940162'/><link rel='alternate' type='text/html' href='http://pywinauto.blogspot.com/2006/02/new-blog-marketing-for-pywinauto.html' title='New blog - marketing for pywinauto'/><author><name>Mark Mc Mahon</name><uri>http://www.blogger.com/profile/13173865151939176401</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
