Sunday, August 31, 2014

Internet Explorer 9 Save Dialog - SendKeys Last Resort

At work we use Internet Explorer 9 on Windows 7 Enterprise.  SharePoint is the favored software for filesharing inside organizational groups.  Our mine planning office is in the States; the mine operation whose data I work is in a remote, poorly connected location of the world.

Recently Sharepoint was updated to a new version at the mine.  The SharePoint server configuration there no longer allows Windows Explorer view or mapping of the site to a Windows drive letter.  I've put in a trouble ticket to regain this functionality, but that may take a while if it's possible.  Without it it is difficult to automate file retrieval or get more than one file at a time.

In the meantime I've been able to get the text based files over using win32com automation in Python to run Internet Explorer and grab the innerHTML object.  innerHTML is essentially the text of the files with tags around it.  I rip out the tags, write the text to a file on my harddrive and I'm good to go.

Binary files proved to be more difficult to download.  Shown below is a screenshot of the Internet Explorer 9 dialog box that goes by the generic name Notification Bar:

 
I googled and could nowhere find how this thing fit into the Internet Explorer 9 Document object hierarchy.  Then I came upon this colorful exchange between Microsoft Certified MVP's from 2012 that made things a little more clear.
 
It turns out you can't access the Notification Bar programatically per se.  What you can do is activate the specific Internet Explorer window and tab you're interested in, then send keystrokes to get where you want to, click, and download your file.
 
I'm not a web programmer nor am I a dedicated Windows programmer (I'm actually a geologist).  IEC is a small module that wraps some useful functionality - in my case identifying and clicking on the link on the SharePoint page by it's text identifier:
 
# C Python 2.7
 
# Internet Explorer module.
import IEC as iec
 
import time
 
ie = iec.IEController()
 
ie.Navigate(<URL of SharePoint page>)
# Give the page time to load (7 seconds).
time.sleep(7)
# I want to download file 11.msr.
ie.ClickLink('11')
# Give 5 seconds for the Notification Bar to show up.
time.sleep(5)
 
I'm fortunate in that our mine planning vendor, MineSight, ships Python 2.7 and associated win32com packages along with their software (their API's are written for Python).  If you don't have win32com and friends installed, they are necessary for this solution.
 
At this point I've just got to deal with that pesky Internet Explorer 9 Notification Bar.  As it turns out, SendKeys makes it doable (although neither elegant nor robust :-(   ):
 
# Activate the SharePoint page.
from win32com.client import Dispatch as dispx
shell = dispx('WScript.Shell')
shell.AppActivate(<name of IE9 tab>)
# Little pause.
time.sleep(0.5)
# Keyboard combination for the Notification Bar selection
# is ALT-N or '%n'
shell.SendKeys('%n', True)
# The Notification Bar goes to "Open" by default.
# You need to tab over to the "Save" button.
shell.SendKeys('{TAB}')
# Another little pause.
time.sleep(0.1)
# Space bar clicks on this control.
shell.SendKeys(' ', True)
 
The key combinations for accessing the Notification Bar are in Microsoft's documentation here
 
One link showing use of SendKeys is a German site (mostly English text) here.
 
And that's pretty much it.  There's another dialog that pops up in Internet Explorer 9 after the file is downloaded.  I've been able to blow that off so far and it hasn't gotten in the way as I move to the next download.  I give these files (about 300 kb) 15 seconds to download over a slow connection.  I may have to adjust that.
 
This solution is an abomination by any coding/architecture/durability standard.  Still, it's the abomination that is getting the job done for the time being.
 
Thanks for stopping by.
 
 

8 comments:

  1. A tour de force. It reminds me of a project I once worked on that was written entirely in 2.4, and one of their vendors updated their API, which was only available in 2.7.

    I ended up using JSON to communicate between a 2.4 and a 2.7 process. Wanted to stick my finger down my throat afterwards. The whole system was a pile of kluges held together by klugey string. Yerch.

    ReplyDelete
    Replies
    1. They are the abominations that put food on our tables. A twitter friend related having to programmatically move the mouse to the location of a button and then click it. IDEK.

      "The Kludge that Fed Me" :-(

      Delete
  2. You might be able to use Python's urllib to download the files. I have also used Selenium (http://www.seleniumhq.org/) to automate a browser and make it do what I want.

    ReplyDelete
  3. @Mike, thanks. I tried that among other things. They yield a "operation not permitted" message or error or text value.

    For whatever reason, the site is locked down to force you to use a mouse and clicks and individually download each file. It's kind of a drag :-(

    ReplyDelete
  4. This makes it sound like there should be absolute URLs returned: http://stackoverflow.com/questions/5380560/python-and-sharepoint-integration. And I found this useful link that might work for you: https://bountify.co/download-sharepoint-folders-and-files-with-python

    ReplyDelete
  5. Mike, thanks again. I could be wrong, but I think they've got this site locked down to force the user to use IE9 and a mouse.

    I've tried IronPython with the Sharepoint.Client dll. The usual response to anything I try to do is along the lines of

    "AttributeError: attribute 'SPSite' of 'namespace#' object is read-only"

    I was working from this site

    http://community.spiceworks.com/how_to/show/2361-automate-sharepoint-tasks-using-ironpython

    trying to get started on using the SharePoint client object model.

    It could be I'm not understanding something or missing something. So far I've hit a lot of dead ends.

    Thanks for the input and for having a look at the blog.

    ReplyDelete
  6. As it turns out, there is access to Explorer View; it's just in a different location in the newer version of SharePoint.

    It's not a Python solution, but I can map the SharePoint site as a network drive letter and copy the files with

    xcopy /*.msr . /z

    I learned a little messing with this (I hate GUI's :-( )

    ReplyDelete
  7. Thanks a lot; a life saver for me; have tried autoit and could not download using it. Issue solved.

    ReplyDelete