Help with automated html to image capture
-
First off, I am a Windows network technician with some coding back ground, mostly in C++ and VB, new to C#, so please bear with me. I am trying to modify the following project by Douglas M. Weems (thanks a bunch Douglas for the code, it's been a GREAT help): http://www.codeproject.com/cs/media/IECapture.asp[^] We have a need to automate the process of capturing web sites of our clients as images. To do this I am modifying Douglas' project to do so. I have made most of the changes we require, but am stuck on one, hopefully last, issue. I added a WebBrowser control, and modified the code to read the site loaded in it rather then from the first available web browser window open. My problem is that when I automatically run the the button_click event which has the image capture code, the WebBrowser control does not load quickly enough, and the code calls properties of this control that are set to "null". If I launch the app, and manually click the button which runs the capture code, it works without an issue, the image captures. This is how I setup the automated process. On the Form Load event I read in a text file with the URL, and the WebBrowser control called axWebCap browses to this site. I then run the capture code in the Form Activated event. I discovered that if I do this, that axWebCap.ReadyState = READYSTATE_LOADING. Now if I run this manually by running the ap and click the capture button the axWebCap.ReadyState = READYSTATE_COMPLETE. I guess my question is, how can I run this code in a function after the Form has completely loaded, and therefore the axWebCap WebBrowser control has completely loaded as well, and it's properties are no longer set to null? BTW, I am using Visual C# 2005 EE, and I would be more then happy to clarify anything I just posted. Any help would be greatly appreciated! Thanks, Justin
-
First off, I am a Windows network technician with some coding back ground, mostly in C++ and VB, new to C#, so please bear with me. I am trying to modify the following project by Douglas M. Weems (thanks a bunch Douglas for the code, it's been a GREAT help): http://www.codeproject.com/cs/media/IECapture.asp[^] We have a need to automate the process of capturing web sites of our clients as images. To do this I am modifying Douglas' project to do so. I have made most of the changes we require, but am stuck on one, hopefully last, issue. I added a WebBrowser control, and modified the code to read the site loaded in it rather then from the first available web browser window open. My problem is that when I automatically run the the button_click event which has the image capture code, the WebBrowser control does not load quickly enough, and the code calls properties of this control that are set to "null". If I launch the app, and manually click the button which runs the capture code, it works without an issue, the image captures. This is how I setup the automated process. On the Form Load event I read in a text file with the URL, and the WebBrowser control called axWebCap browses to this site. I then run the capture code in the Form Activated event. I discovered that if I do this, that axWebCap.ReadyState = READYSTATE_LOADING. Now if I run this manually by running the ap and click the capture button the axWebCap.ReadyState = READYSTATE_COMPLETE. I guess my question is, how can I run this code in a function after the Form has completely loaded, and therefore the axWebCap WebBrowser control has completely loaded as well, and it's properties are no longer set to null? BTW, I am using Visual C# 2005 EE, and I would be more then happy to clarify anything I just posted. Any help would be greatly appreciated! Thanks, Justin
Justin, After you've assigned the URL to navigate to, you need to loop until the ReadyState is READYSTATE_COMPLETE; not actually assign it values. Something like: while (axWebCap.ReadyState != READYSTATE_COMPLETE) { // tells application to process messages ... Application.DoEvents(); } // when you come out of this loop, your page is now loaded and // all the objects (DOM) etc... should exist Hope that helps.
:..::. Douglas H. Troy ::..
Bad Astronomy |VCF|wxWidgets|WTL -
Justin, After you've assigned the URL to navigate to, you need to loop until the ReadyState is READYSTATE_COMPLETE; not actually assign it values. Something like: while (axWebCap.ReadyState != READYSTATE_COMPLETE) { // tells application to process messages ... Application.DoEvents(); } // when you come out of this loop, your page is now loaded and // all the objects (DOM) etc... should exist Hope that helps.
:..::. Douglas H. Troy ::..
Bad Astronomy |VCF|wxWidgets|WTLThanks Douglas for your responce! I actually have tried creating a while loop like this. I just can't figure out what to put for the "Application.DoEvents()" that will cause the WebBrowser control to fully load, or wait for it to fully load. I tried the following:
string WebReady = axWebCap.ReadyState.ToString(); while (WebReady != "READYSTATE_COMPLETE") { WebReady = axWebCap.ReadyState.ToString(); }
But that just causes an infinite loop. I am thinking that is because it is not refreshing the Ready Status. Do I need to refresh the form or something? I thought about putting a timer in, but thought that could cause issues in the future if the page load fell outside the time limit. Thanks again, Justin -
Thanks Douglas for your responce! I actually have tried creating a while loop like this. I just can't figure out what to put for the "Application.DoEvents()" that will cause the WebBrowser control to fully load, or wait for it to fully load. I tried the following:
string WebReady = axWebCap.ReadyState.ToString(); while (WebReady != "READYSTATE_COMPLETE") { WebReady = axWebCap.ReadyState.ToString(); }
But that just causes an infinite loop. I am thinking that is because it is not refreshing the Ready Status. Do I need to refresh the form or something? I thought about putting a timer in, but thought that could cause issues in the future if the page load fell outside the time limit. Thanks again, Justinhere's an example I just slapped together for testing ... grant it, my object names differ, but you'll get the idea ...
private void OnFormLoad(object sender, EventArgs e) { this.webBrowser1.Navigate(@"http://www.cnn.com"); while (this.webBrowser1.ReadyState != WebBrowserReadyState.Complete) { Application.DoEvents(); } MessageBox.Show("DONE loading!"); }
:..::. Douglas H. Troy ::..
Bad Astronomy |VCF|wxWidgets|WTL -
here's an example I just slapped together for testing ... grant it, my object names differ, but you'll get the idea ...
private void OnFormLoad(object sender, EventArgs e) { this.webBrowser1.Navigate(@"http://www.cnn.com"); while (this.webBrowser1.ReadyState != WebBrowserReadyState.Complete) { Application.DoEvents(); } MessageBox.Show("DONE loading!"); }
:..::. Douglas H. Troy ::..
Bad Astronomy |VCF|wxWidgets|WTLThanks again Douglas! I hear what you are saying, I just don't know what process to run that will refresh the WebBroswer.ReadyState until it is completed. What event or process can I keep running that will get me to WebBrowserReadyState.Complete before I run the capture code. Here is some of the code:
private void frmMain_Load(object sender, EventArgs e) { Initialize_Site(null, null); string WebReady = axWebCap.ReadyState.ToString(); while (WebReady != "READYSTATE_COMPLETE") { WebReady = axWebCap.ReadyState.ToString(); } } private void frmMain_Activated(object sender, System.EventArgs e) { button1_Click(null, null); //This runs the capture code } private void Initialize_Site(object sender, EventArgs e) { TextReader WebConfig = new StreamReader(@"c:\\IECapture\config.txt"); int LineCount = 4; string[] ConfigLines = new string[LineCount]; for (int i = 1; i < LineCount; i++) { ConfigLines[i] = WebConfig.ReadLine(); } string Address = ConfigLines[1]; axWebCap.Navigate(Address); }
Thanks, Justin -
Thanks again Douglas! I hear what you are saying, I just don't know what process to run that will refresh the WebBroswer.ReadyState until it is completed. What event or process can I keep running that will get me to WebBrowserReadyState.Complete before I run the capture code. Here is some of the code:
private void frmMain_Load(object sender, EventArgs e) { Initialize_Site(null, null); string WebReady = axWebCap.ReadyState.ToString(); while (WebReady != "READYSTATE_COMPLETE") { WebReady = axWebCap.ReadyState.ToString(); } } private void frmMain_Activated(object sender, System.EventArgs e) { button1_Click(null, null); //This runs the capture code } private void Initialize_Site(object sender, EventArgs e) { TextReader WebConfig = new StreamReader(@"c:\\IECapture\config.txt"); int LineCount = 4; string[] ConfigLines = new string[LineCount]; for (int i = 1; i < LineCount; i++) { ConfigLines[i] = WebConfig.ReadLine(); } string Address = ConfigLines[1]; axWebCap.Navigate(Address); }
Thanks, JustinYou need only add a call to Application.DoEvents(); That will tell your application to pump messages and whatnot while you wait for the ReadyState to change ... so in your code, you would private void frmMain_Load(object sender, EventArgs e) { Initialize_Site(null, null); string WebReady = axWebCap.ReadyState.ToString(); while (WebReady != "READYSTATE_COMPLETE") { // tell application to process pending events Application.DoEvents(); // get the readystate WebReady = axWebCap.ReadyState.ToString(); } //add your capture code here ... } -- modified at 16:19 Tuesday 3rd April, 2007
:..::. Douglas H. Troy ::..
Bad Astronomy |VCF|wxWidgets|WTL -
You need only add a call to Application.DoEvents(); That will tell your application to pump messages and whatnot while you wait for the ReadyState to change ... so in your code, you would private void frmMain_Load(object sender, EventArgs e) { Initialize_Site(null, null); string WebReady = axWebCap.ReadyState.ToString(); while (WebReady != "READYSTATE_COMPLETE") { // tell application to process pending events Application.DoEvents(); // get the readystate WebReady = axWebCap.ReadyState.ToString(); } //add your capture code here ... } -- modified at 16:19 Tuesday 3rd April, 2007
:..::. Douglas H. Troy ::..
Bad Astronomy |VCF|wxWidgets|WTLI think I understand now. Pardon my slowness. So the line: Application.DoEvents(); That is an actual event, huh? This shows my lack of knowledge in programming. I have though when people posted this it meant to run a custome function. I will try this What does the Application.DoEvent() actually do? Thanks a bunch for your help!
-
I think I understand now. Pardon my slowness. So the line: Application.DoEvents(); That is an actual event, huh? This shows my lack of knowledge in programming. I have though when people posted this it meant to run a custome function. I will try this What does the Application.DoEvent() actually do? Thanks a bunch for your help!
Well, without it ... your while loop is just going to 'hang' there, and take all the processing until it's condition is met. This is obviously not what you want to have happen ... You want to your program to 'wait' until the ReadyState is complete. By calling DoEvents, that allows your application to process messages that are sitting in the message queue (essentially, it lets your program 'run' while you wait for that state change to occur). Hope that helps.
:..::. Douglas H. Troy ::..
Bad Astronomy |VCF|wxWidgets|WTL -
I think I understand now. Pardon my slowness. So the line: Application.DoEvents(); That is an actual event, huh? This shows my lack of knowledge in programming. I have though when people posted this it meant to run a custome function. I will try this What does the Application.DoEvent() actually do? Thanks a bunch for your help!
-
I just did what you said and it worked like a charge. Added Application.DoEvents() to my while loop, and it works flawlessly. Thank you SO very much Douglas. It is greatly appreciated, and thanks for putting up with a coding newb!