Sunday, 15 June 2025

automating money

Most of my backup process is automated: I have a python script for finding changed files, zipping them up, transferring them to the server, and other bits and pieces.  (Yes, I know there are other ways to do this.  For example, my Google Drive is self-backing-up -- I hope.  But for certain material, I want to be sure what's being backed up, and to where.)

One part of the process that has needed a manual component is backing up my AceMoney data.  Manual until now, that is.

Here's the (part of) the process I have been doing manually.

  • Launch the application
  • Enter my password into the text box, and click OK. 

  • Select File > SaveAs... in the main application

  • Enter the new file name in the Save As dialogue, and click Save

  • Exit the application

It doesn't take long at all to do this, but it is a (very minor) nuisance to have to do this each time (and to remember what to do).  So, how to do all this from python?

Enter the pywinauto library.  (I note it hasn't been updated in a while -- but it seems to work okay, at least for the level of complexity I need.)  After a bit of reading the documentation, getting baffled, watching a short YouTube videoskimming a longer YouTube video, reading a nice tutorial (reading is my preferred input medium for this sort of information), re-reading the documentation (which now made a lot more sense), then writing and testing some code (with quite a lot of muttering when I wanted to do something a little different from the tutorials), I ended up with:
from pywinauto.application import Application

def backup_ace_money(pwd,file_name):

    # Launch the application
    app = Application().start(r'C:\Program Files (x86)\AceMoney\AceMoney.exe', timeout=10)

    # Enter password, click OK
    pwd_dlg = app.window(title='Enter password')
    pwd_dlg.Edit.type_keys(pwd)
    pwd_dlg.OKButton.click()

    # Select File > SaveAs in main window
    main_dlg = app.top_window()
    main_dlg.menu_select('File -> Save As...')

    # Enter the file name in the Save menu, and click Save
    save_dlg = app.window(title='Save As')
    save_dlg.SaveAsComboBox1.type_keys(file_name)
    save_dlg.SaveButton.click()

    # Exit AceMoney
    main_dlg.close()

The only (hah!) difficult bit was discovering the name of the box to type the file name into.  (I confess that discovering the mere existence of the menu_select() function took me more time, and extreme muttering, than it should have.)  The print_control_identifiers() function was indispensable for finding the name of the relevant control, but the great advantage is you can access by (relatively robust) name, not (incredibly fragile) screen position.  

So, a couple of hours and 10 lines of code later, this task has now been automated.

And now I'm thinking about what to automate next.



Tuesday, 10 June 2025

Why does it cry and resist before it is hurt?

I came across this recently: 

Unjust laws exist: shall we be content to obey them, or shall we endeavor to amend them, and obey them until we have succeeded, or shall we transgress them at once? Men generally, under such a government as this, think that they ought to wait until they have persuaded the majority to alter them. They think that, if they should resist, the remedy would be worse than the evil. But it is the fault of the government itself that the remedy is worse than the evil. It makes it worse. Why is it not more apt to anticipate and provide for reform? Why does it not cherish its wise minority? Why does it cry and resist before it is hurt? Why does it not encourage its citizens to be on the alert to point out its faults, and do better than it would have them? Why does it always crucify Christ, and excommunicate Copernicus and Luther, and pronounce Washington and Franklin rebels?   

— Henry David Thoreau (1849) Civil Disobedience, p367


 

Monday, 9 June 2025

scanners upgrade not in vain


A few months ago, I had an issue with a Windows upgrade bricking my Canon scanner.  At the time, I reverted to an earlier version of Windows to "solve" the problem.  The update reminders were becoming more aggressive, and eventually, it updated itself again, without asking.

Coincidentally, my other half has just got himself a new machine.  Cue several days of his muttering and more, trying to restore his life from his previous machine, which mostly required finding new versions of software, and recompiling a lot of C code.  I reminded him of my scanner woes, as I guessed he was about to encounter them, too.

Clearly, his Google-fu is better than mine, and he directed me to a site I hadn't previously found.  There is a work-around, and a new version of the CaptureOnTouch software.  (Note that the date of the new release is prior to my previous post.  Sigh.)  So, I downloaded it, unzipped it, and double-clicked the exe.  It got partway through the Wizard before bailing.  So I uninstalled the previous version, and tried installing again.  It worked!

So, I now have both Windows 42H2 and Canon scanning ability.  Success!

But it really shouldn't be this difficult.



Saturday, 7 June 2025