4

I am using windows 7 X64.

I have installed Adobe Acrobat, so that I have a virtual PDF printer. I have also install the adobe flash player on the system.

I open the SWF file using the flash player, and from the flash player I can print the file to PDF.

I wonder if that is possible to repeat the process for a folder of SWF files.

During the "print" process, the PDF printer asks for a file name, which I want to use the file name from the SWF file. I hope this can be automated as well.

Thanks!

3 Answers3

3

Below is my contribution also using pywinauto.

I used internet explorer as the browser (so set internet explorer as default program for swf files) as i found it to load the swf files fastest (I know... weird right).

I also used adobe acrobat to print with. (it seems the print dialog handle is similar for most programs though so you may not have trouble). Because I used adobe I had to change my handle of the print dialog from

window.OK.click to window.Print.click (on line 61)

Also you may need to change the values for the below line (line 43). As your screen res might be different to mine.

browser_tab.click_input(coords=(1440, 2060))

Apologies if it isn't explained well, also because it is python, please check if the indentation is correct in below code.

    import sys
    import re
    import os
    import warnings
    import webbrowser
    from time import sleep
    import pywinauto as pwa
    from pywinauto.application import Application
    from pywinauto.keyboard import SendKeys

    def sendkey_escape(string):
    """Escape `+ ^ % ~ { } [ ] ( )` by putting them within curly braces.

    Refer to sendkeys' documentation for more info:
     * https://github.com/zvodd/sendkeys-py-si/blob/master/doc/SendKeys.txt
       (Could not open the original site: rutherfurd.net/python/sendkeys/ )
    """
    return re.sub(r'([+^%~{}\[\]()])', r'{\1}', string)

    warnings.filterwarnings(
    'once', message=r'.*64-bit application should.*', category=UserWarning
    )

    filenames = os.listdir(os.getcwd())
    app = Application()
    for filename in filenames:
        #pwa.timings.Timings.Slow()
        if not filename.endswith('.swf'):
            continue
        pdfname = filename[:-3] + 'pdf'
        if pdfname in filenames:
            # Already there!
            continue
        # Assume the default application to open swf files is browser_tab.
        webbrowser.open(filename)
        sleep(2)
        app.connect(title_re='.*Explorer', class_name='IEFrame')

        browser_tab = app.IEFrame
        browser_tab.wait('active')
        browser_tab.set_focus()
        #below to enable activex controls
        browser_tab.click_input(coords=(1440, 2060))
        sleep(2)
        browser_tab.right_click_input(coords=(500, 500))

        # Click "print" from the rightclick menu.
        browser_tab.click_input(coords=(540, 645))

        pwa.timings.wait_until_passes(
            20,
            0.5,
            browser_tab[u'Print'].Exists,
            pwa.findwindows.WindowNotFoundError
        )

        app2 = Application().connect(title=u'Print')
        pwa.timings.Timings.Defaults()
        window = app2.Print
        window.wait('ready')
        button = window.Print
        button.Click()

        pwa.timings.wait_until_passes(
            20,
            0.5,
            browser_tab[u'Save PDF File As'].Exists,
            pwa.findwindows.WindowNotFoundError
        )
        app3 = Application().connect(title=u'Save PDF File As', class_name='#32770')
        window = app3.Dialog
        combobox = window[u'4']

        combobox.set_focus().type_keys(sendkey_escape(os.getcwd() + '\\' + pdfname), with_spaces=True)
        window.Save.Click()

        pwa.timings.wait_until_passes(
            20,
            0.5,
            app[u'Creating Adobe PDF'].Exists,
            pwa.findwindows.WindowNotFoundError
        )

        app4 = app.connect(title=u'Creating Adobe PDF', class_name='#32770')
        window3 = app4.Dialog
        window3.wait_not('active',20,1)
        browser_tab.Close()

I used SWAPY to help get the control identifiers of each window. However SWAPY uses old code (still very useful though), so I updated the code to reflect and support the current version of pywinauto (at least for me anyway). If you look it up the function calls are much the same but are just converted from camelcase to underscore_case.

2

I was looking for the same thing. Well, I couldn't find any specific library to this job either. But at the very least we will be able to automate this process using GUI automation tools.

There are lots of libraries and standalone applications for this job. One that seems promising to me is Autoit.

But as a Python fan I found this amazing library called pywinauto and wrote the following script to convert my swf files:

"""Convert all swf files in this directory to a pdf file using Firefox.

Note that some parameters in this script need to be adjusted according to
user's printer setup, screen resolution, etc.

Documentation of pywinauto:
 * https://pywinauto.github.io/docs/contents.html
An example script using pywinauto:
 * https://github.com/vsajip/pywinauto/blob/master/examples/SaveFromFirefox.py
"""


import re
import os
import warnings
import webbrowser
from time import sleep
from functools import partial

import pywinauto as pwa
from pywinauto.application import Application


def sendkey_escape(string):
    """Escape `+ ^ % ~ { } [ ] ( )` by putting them within curly braces.

    Refer to sendkeys' documentation for more info:
         * https://github.com/zvodd/sendkeys-py-si/blob/master/doc/SendKeys.txt
           (Could not open the original site: rutherfurd.net/python/sendkeys/ )
    """
    return re.sub(r'([+^%~{}\[\]()])', r'{\1}', string)


# Using 32-bit python on 64-bit machine? Will get the following warning a lot:
# "UserWarning: 64-bit application should be automated using 64-bit Python
# (you use 32-bit Python)"
# Limit this warnings to only show once.
# The following line does not work as expected. See
# github.com/pywinauto/pywinauto/issues/125
warnings.filterwarnings(
    'once', message=r'.*64-bit application should.*', category=UserWarning
)
# Assume Firefox is already open.
app = Application().connect(title_re=".*Firefox")
firefox = app.MozillaFireFox.GeckoFPSandboxChildWindow
filenames = os.listdir()
for filename in filenames:
    if not filename.endswith('.swf'):
        continue
    pdfname = filename[:-3] + 'pdf'
    if pdfname in filenames:
        # Already there!
        continue
    # Assume the default application to open swf files is Firefox.
    webbrowser.open(filename)
    firefox.SetFocus()
    firefox.Wait('exists ready', timeout=5)
    firefox.RightClickInput(coords=(200, 200))
    firefox.Wait('ready', timeout=10)
    # Click "print" from the rightclick menu.
    firefox.ClickInput(coords=(210, 320))
    pwa.timings.WaitUntilPasses(
        timeout=10,
        retry_interval=1,
        func=partial(app.Connect, title='Print'),
        exceptions=pwa.findwindows.WindowNotFoundError,
    )
    app.Print.Wait('ready active', 5)
    # The printing process depends on the default printer being used.
    app.Print.OK.Click()
    app.Print.WaitNot('exists', timeout=5)
    pwa.timings.WaitUntilPasses(
        timeout=10,
        retry_interval=1,
        func=partial(app.Connect, title='Save As'),
        exceptions=pwa.findwindows.WindowNotFoundError,
    )
    # Be wary that some characters such as "%" don't work correctly in Save As
    # dialogs. This code does not handle such awkwardness of MS Windows.
    app.SaveAS.ComboBox.SetFocus().TypeKeys(
        sendkey_escape(os.getcwd() + '\\' + pdfname), with_spaces=True
    )
    app.SaveAS.Save.Click()
    firefox.Wait('exists ready', timeout=5)
    # Focuse is lost to flash (bugzilla: 78414). Use mouse to close the tab.
    firefox.ClickInput(coords=(418, 16), absolute=True)
    firefox.WaitNot("exists", timeout=5)

This method has its own limitations. For example you won't be able to use your computer during the conversion process as mouse and keyboard are controlled by the script. The script needs adjustments for individual computers. Also the GUI controlling process is supposed to be a lot slower than a CLI application designed to do the same job. However this is still far easier and faster than converting them manually.

P.S. I can't help but to mention Sikuli. Another amazing python library for GUI automation.

Update

The above method produces vector graphics, but if anyone is interested in rasterized .png files (which can be easily converted to pdf using freely available tools), they may want to try swfrender from swftools package. Currently, the latest stable binary version available for Windows is 0.9.0 (2009-07-21). But I recommend trying the development snapshot swftools-2013-04-09-1007.exe which offers some more options including the option -r which is used to adjust the resolution of the output file.

AXO
  • 1,126
-2

I found an alternative way to do this:

  1. Use "Xilisoft convertor" to convert swf to jpg (batch conversion is possible)
  2. Use Online convertors to combine all jpg to pdf
DavidPostill
  • 162,382