My apologies if this has already been sent but I did not receive a post acknowledgement.
|Tim, | |Thanks again. Your assistance has been extremely helpful. | |I've modified the test routine to illustrate the substance of our exchange |and am posting it by way of giving something back to the group and in the |off chance that it may prove useful to others. | |BTW, I'm still a bit concerned about the Python COM related crash on |trailing events but will leave it to others more skilled than me to decide |what if anything should be done. | |By way of explanation for others the output, included below after the code, |illustrates the following: | |At 2.185 when the main sets ie.Visible = 1, the OnVisible event code runs |BEFORE control returns to the main routine at 2.272 and absent a |PumpWaitingMessages. Clearly setting this IE property will cause the On- |event code to run and some events are synchronous with main's interaction |with COM. | |At 2.272 when the main sets ie.StatusBar = 0, both the OnCommandStateChange |and OnStatus bar on event routines run BEFORE control returns to the main |routine at 2.275 and absent a PumpWaitingMessages. While later |OnCommandStateChange events must be pumped, there are some conditions when |a given On-event routine WILL EXECUTE absent a pump but later WILL REQUIRE |a pump. | |At 2.324 when the main initiates a navigation both the OnCommandStateChange |and OnBeforeNavigate2 event routines run BEFORE control returns to the main |at 2.400 and absent a PumpWaitingMessages. Clearly event routines can and |do run when some (but not necessarily all) COM object properties are |changed or methods executed. | |At 2.401 when the main spins in Python for 30 seconds WITHOUT pumping NO |On-event code is run. In an apartment-threaded model absent a bug in the |object's COM interface event code should never be executed unless COM |properties are changed or methods executed. | |At 32.413 when the main does 'one pump' the OnCommandStateChange event |coded is executed 3 times BEFORE control returns to the main at 32.419. |Clearly events can and do occur while the main is off doing whatever and |the COM object is off doing its own whatever. These events will queue and |subsequent pumping or other interactions (not illustrated but true) that |cause the pythoncom message queue to be processed will cause the associated |On-event routines to execute. | |FWIW, if the test is run again the number and of events here will vary |since the processes (the test and IE) are entirely separate. | |At 32.419 when the main spins for 10 seconds NO On-event routines are |executed. This verifies and supports the NO EVENTS UNLESS PROPERTIES OR |METHODS rule. | |At 42.429 when the main does another pump there are no pending events. |FWIW, in other runs of this test occasionally there will be another event |or two reflecting the flow of the separate test and IE processes. | |At 47.460 when the main starts pumping messages for 30 seconds events start |to occur and the IE window begins to display. The IE window does NOT paint |before then even though some 40+ seconds have elapsed. Clearly IE is |'hung' waiting disposition of some events. It should be noted that in the |case of IE some events, for example NewWindow2, expect a return value so |that IE can be expected to (and as far as I know does) wait for the event |to be processed before proceeding. While it is not clear what event this |particular Navigate2 is waiting on, it is clearly waiting since subsequent |to starting to pump messages the page displays in roughly another 17 |seconds. Clearly, in a DispatchWithEvents world when events are caught |they MUST be pumped to allow the correspondent process (IE) to proceed. |Absent pumping the correspondent can 'hang' waiting for the event to be |processed. | |At 97.461 subsequent pumping yields NO events. This page is now stable. |It should be noted that this particular stable behavior is a function of |this particular page and NOT a general characteristic of IE or COM. | |It is entirely possible for HTML pages to go off and do whatever whenever |and cause events. For instance, on this page in particular the right hand |frame paints and a topmost window document complete event occurs (not |illustrated in this example, but an indication that all the bytes from the |original navigation request are now received) before all events have |occurred and the page is completely rendered. On this page, when IE begins |to process the page after the topmost window document complete event occurs |there is a bit of script attached to the pages OnLoad event that runs to |build the left hand frame. This script goes back to the web to get the |left frame contents and generates a stream of events that occur after the |initial navigation is (in some sense) complete. This illustrates that a |page CAN go off and generate events without interaction from the main |automation routine. While on this page the script is triggered by the |pages OnLoad event, it is entirely possible that on page script will wait |around a bit or be attached to some other page feature and then start to do |things that generate events. A slight modification of this test that stops |pumping after the topmost window document complete event will leave the |left frame NOT displayed until messages are once again pumped. | | | |--- Begin Code --- |import win32com.client |import pythoncom |import time | |class events(): | def OnVisible(self, vis): | self.eventMsg( 'OnVisible is %s'%(vis)) | def OnBeforeNavigate2(self,pDisp,url,flags, | targetFrameName,postData, | headers,cancel): | self.eventMsg( "OnBeforeNavigate2 on url [%s] on frame [%s]"% | (url, targetFrameName)) | def OnCommandStateChange(self, | Command, | Enable): | self.eventMsg( 'OnCommandStateChange: %s %s'%(Command,Enable)) | def OnProgressChange(self, nProgress, nProgressMax): | msg = 'OnProgressChange progress %d max %d' % ( | nProgress, nProgressMax) | self.eventMsg( msg ) | def OnStatusBar(self, | status): | self.eventMsg('OnStatusBar') | def eventMsg( self, msg ): | print 'At %6.3f Event tag [%s] %s'%(time.clock(), tag, msg) | |tag = 'No tag' |def mainMsg( t, msg = ''): | global tag | tag = t | print 'At %6.3f Main tag [%s] %s'%(time.clock(), t, msg) | return | |def spin( t, msg ): | mainMsg( 'Spin for %s seconds, no pump'%t, msg) | t0 = time.clock() | while time.clock()-t0 < t: pass | |def spinPump( t, msg ): | mainMsg( 'Pump %s seconds'%t, msg) | t0 = time.clock() | while time.clock()-t0 < t: pythoncom.PumpWaitingMessages() | |time.clock() # just get clock running |mainMsg( 'Begin test' ) |mainMsg( 'win32com.client.DispatchWithEvents' ) |ie = win32com.client.DispatchWithEvents( | 'InternetExplorer.Application', | events) |# NO PUMP MESSAGE |mainMsg( 'Set ie.Visible', 'On-event routines run') |ie.Visible = 1 |mainMsg( 'Set ie.StatusBar false', 'On-event routines run' ) |ie.StatusBar = 0 |mainMsg( 'Set ie.StatusBar true', 'On-event routines run' ) |ie.StatusBar = 1 |mainMsg( 'Navigate to ... aa752574.aspx', | 'OnBeforeNavigate2 event routine runs' ) |url = 'http://msdn2.microsoft.com/en-us/library/aa752574.aspx' |ie.Navigate(url) |mainMsg( 'Back from Navigate', 'The page should NOT be displayed') |spin(30, 'The page should not display and there should be no events' ) |mainMsg( 'One pump', | 'The page should still NOT be displayed, ' + \ | 'but we should see a few messages and ' + \ | 'IE is hung waiting for events to be processed' ) |pythoncom.PumpWaitingMessages() |spin( 10, 'The page should still NOT be displayed, ' + \ | 'there should be no events and ' | 'IE is hung waiting for events to be processed' ) |mainMsg( 'Another pump', | 'The page should still NOT be displayed, ' + \ | 'but we may see a few more messages and ' + \ | 'IE is still hung waiting for events to be processed' ) |pythoncom.PumpWaitingMessages() |spin( 5, 'The page should still NOT be displayed, ' + \ | 'there should be no events and ' | 'IE is hung waiting for events to be processed' ) |spinPump( 30, 'The page should NOW start displaying') |spinPump( 20, 'The page should be stable and there should be no trailing |events' ) |mainMsg( 'End test' ) |--- End Code --- | |--- Begin Output --- |At 0.000 Main tag [Begin test] |At 0.000 Main tag [win32com.client.DispatchWithEvents] |At 2.185 Main tag [Set ie.Visible] On-event routines run |At 2.189 Event tag [Set ie.Visible] OnCommandStateChange: 2 False |At 2.272 Event tag [Set ie.Visible] OnVisible is True |At 2.272 Main tag [Set ie.StatusBar false] On-event routines run |At 2.275 Event tag [Set ie.StatusBar false] OnCommandStateChange: 1 False |At 2.275 Event tag [Set ie.StatusBar false] OnStatusBar |At 2.275 Main tag [Set ie.StatusBar true] On-event routines run |At 2.321 Event tag [Set ie.StatusBar true] OnStatusBar |At 2.324 Main tag [Navigate to ... aa752574.aspx] OnBeforeNavigate2 event |routine runs |At 2.328 Event tag [Navigate to ... aa752574.aspx] OnCommandStateChange: 2 |False |At 2.353 Event tag [Navigate to ... aa752574.aspx] OnBeforeNavigate2 on |url [http://msdn2.microsoft.com/en-us/library/aa752574.aspx] on frame [] |At 2.400 Main tag [Back from Navigate] The page should NOT be displayed |At 2.401 Main tag [Spin for 30 seconds, no pump] The page should not |display and there should be no events |At 32.413 Main tag [One pump] The page should still NOT be displayed, but |we should see a few messages and IE is hung waiting for events to be |processed |At 32.413 Event tag [One pump] OnCommandStateChange: 1 False |At 32.416 Event tag [One pump] OnCommandStateChange: 2 False |At 32.417 Event tag [One pump] OnCommandStateChange: 1 False |At 32.419 Main tag [Spin for 10 seconds, no pump] The page should still |NOT be displayed, there should be no events and IE is hung waiting for |events to be processed |At 42.429 Main tag [Another pump] The page should still NOT be displayed, |but we may see a few more messages and IE is still hung waiting for events |to be processed |At 42.429 Main tag [Spin for 5 seconds, no pump] The page should still NOT |be displayed, there should be no events and IE is hung waiting for events |to be processed |At 47.460 Main tag [Pump 30 seconds] The page should NOW start displaying |At 47.461 Event tag [Pump 30 seconds] OnProgressChange progress 100 max |10000 |At 47.484 Event tag [Pump 30 seconds] OnProgressChange progress 100 max |10000 |At 47.655 Event tag [Pump 30 seconds] OnProgressChange progress 150 max |10000 |At 47.657 Event tag [Pump 30 seconds] OnProgressChange progress 200 max |10000 |At 47.660 Event tag [Pump 30 seconds] OnProgressChange progress 250 max |10000 |At 47.661 Event tag [Pump 30 seconds] OnProgressChange progress 300 max |10000 |At 47.666 Event tag [Pump 30 seconds] OnProgressChange progress 350 max |10000 |At 47.667 Event tag [Pump 30 seconds] OnProgressChange progress 400 max |10000 |At 47.667 Event tag [Pump 30 seconds] OnProgressChange progress 450 max |10000 |At 47.668 Event tag [Pump 30 seconds] OnProgressChange progress 500 max |10000 |At 47.669 Event tag [Pump 30 seconds] OnProgressChange progress 550 max |10000 |At 47.671 Event tag [Pump 30 seconds] OnProgressChange progress 600 max |10000 |At 47.700 Event tag [Pump 30 seconds] OnProgressChange progress 666800 max |1000000 |At 48.256 Event tag [Pump 30 seconds] OnCommandStateChange: -1 False |At 48.447 Event tag [Pump 30 seconds] OnCommandStateChange: 2 False |At 48.448 Event tag [Pump 30 seconds] OnCommandStateChange: 1 False |At 48.497 Event tag [Pump 30 seconds] OnCommandStateChange: -1 False |At 48.654 Event tag [Pump 30 seconds] OnProgressChange progress 1060000 max |1000000 |At 54.270 Event tag [Pump 30 seconds] OnProgressChange progress 1000000 max |1000000 |At 54.271 Event tag [Pump 30 seconds] OnProgressChange progress -1 max |1000000 |At 54.286 Event tag [Pump 30 seconds] OnProgressChange progress 1000000 max |1000000 |At 54.584 Event tag [Pump 30 seconds] OnBeforeNavigate2 on url |[http://msdn2.microsoft.com/en-us/library/aa752574(d=toc).aspx] on frame [] |At 54.610 Event tag [Pump 30 seconds] OnProgressChange progress 1000000 max |10000 |At 54.616 Event tag [Pump 30 seconds] OnCommandStateChange: -1 False |At 54.769 Event tag [Pump 30 seconds] OnProgressChange progress 0 max 0 |At 56.209 Event tag [Pump 30 seconds] OnCommandStateChange: 2 False |At 56.210 Event tag [Pump 30 seconds] OnCommandStateChange: 1 False |At 57.316 Event tag [Pump 30 seconds] OnProgressChange progress 70800 max |1000000 |At 64.288 Event tag [Pump 30 seconds] OnProgressChange progress 1000000 max |1000000 |At 64.345 Event tag [Pump 30 seconds] OnProgressChange progress -1 max |1000000 |At 64.526 Event tag [Pump 30 seconds] OnCommandStateChange: -1 False |At 64.854 Event tag [Pump 30 seconds] OnProgressChange progress 0 max 0 |At 77.460 Main tag [Pump 20 seconds] The page should be stable and there |should be no trailing events |At 97.461 Main tag [End test] | |--- End Output --- _______________________________________________ Python-win32 mailing list Python-win32@python.org http://mail.python.org/mailman/listinfo/python-win32