|
Using the following code I can run a process and trap when it has exited.
private void RunProc()
{
Process p = new Process();
p.StartInfo.FileName = "calc.exe";
p.EnableRaisingEvents = true;
p.Exited += new EventHandler(p_Exited);
p.Start();
}
private void p_Exited(object sender, EventArgs e)
{
MessageBox.Show( "Exited" );
}
What I would like to ask is, can I in some way determine if the process has crashed, been killed, or exited in some abnormal fashion?
I can use the ExitCode property to find out what the exit code of the process was, but some processes don't return meaningful exit codes, and the exit code seems to be zero if the process crashes or is killed.
Searching the web without Google is like straining sewage with your teeth. Userfriendly, 2003/06/07
|
|
|
|
|
Look up Try...Catch blocks.
E.G.,
private void RunProc()
{
Process p = new Process();
p.StartInfo.FileName = "calc.exe";
p.EnableRaisingEvents = true;
try
{
p.Start();
}
catch (Exception exc)
{
MessageBox.Show
(
OwningForm,
"Inner Exception: " + exc.InnerException.ToString() +
" Message: " + exc.Message.ToString() +
" Source: " + exc.Source.ToString()
);
}
}
|
|
|
|
|
I tried that first, didn't think it'd work, and it doesn't, unfortunately.
Maybe if I attach to the process as a debugger...
Searching the web without Google is like straining sewage with your teeth. Userfriendly, 2003/06/07
|
|
|
|
|
A separate program crashing would not throw an exception in the executing AppDomain .
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
If you don't need to process any further until the application quits, use Process.WaitForExit . This will block till normal or abnormal termination.
Since a terminated process does not signal its wait handles, watching for it won't work because thew ait handle is never signaled (and your Exited event is never fired). You could probably P/Invoke the GetExitCodeProcess and pass the process's handle (from Process.Handle after starting it) to get the exit code returned either from normal or abnormal termination. Knowing when to use it is the trick, though.
Finally, you could always start the application in a separate thread and use Process.WaitForExit . This would allow your thread to continue execution. In the class that you'll thread, create your own event (or use a callback) that you'll invoke when WaitForExit returns.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I am trying to control an edit box of a combo in another app.
The apps class name is OtsDJ, and the combo class is "edit".
It is my desire to select the current data in the edit, and replace it with a generated string.
I am having trouble grasping the findwindowex method.
I would like to send a text string to the edit using sendkeys, but would use copy paste method if necessary.
The main issue is grabbing the control on the other app.
Can anyone point me in the right direction?
Jeff
|
|
|
|
|
You can P/Invoke the FindWindowEx API to first find the application and then to find the edit box. Once you get the HWND back (it'll be an IntPtr in managed code), you could also P/Invoke SendMessage to send WM_SETTEXT to it with the lParam parameter set to a string reference:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class Test
{
static void Main(string[] args)
{
if (args.Length < 1) return;
string s = args.Length > 1 ? args[1] : "Hello, world!";
IntPtr ptr = FindWindowEx(IntPtr.Zero, IntPtr.Zero,
null, args[0]);
if (ptr != IntPtr.Zero)
{
ptr = FindWindowEx(ptr, IntPtr.Zero, "Edit", null);
if (ptr != IntPtr.Zero)
SendMessage(ptr, WM_SETTEXT, IntPtr.Zero, s);
}
}
private const int WM_SETTEXT = 0x000c;
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern IntPtr FindWindowEx(
IntPtr hWndParent,
IntPtr hWndChildAfter,
[MarshalAs(UnmanagedType.LPTStr)] string lpszClass,
[MarshalAs(UnmanagedType.LPTStr)] string lpszWindow);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern int SendMessage(
IntPtr hWnd,
[MarshalAs(UnmanagedType.U4)] int msg,
IntPtr wParam,
[MarshalAs(UnmanagedType.LPTStr)] string text);
} The one thing you will have to keep in mind is that many times a control is nested. For example, the code above worked on "Calculator" (calc.exe) but not on "Microsoft Internet Explorer" (iexplore.exe) because the first "Edit" control is nested in a "ComboBox" which is nested in a "ReBarWindow32". You could easily modify the code to traverse the children, though. See the doucmentation for the FindWindowEx function for more information.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thanks!
I'll give this a try.
I should also comment that I can aquire this edit box with a macro program called girder, and send information to it, so I should be able to do the same in my project. Just need the know how!
Jeff
|
|
|
|
|
What's the advantage of typed Datasets?
What's diff between typed and untyped Dataset?
TIA
Promise only what you can do. And then deliver more than what you promised. This signature was created by "Code Project Quoter".
|
|
|
|
|
A typed DataSet is a class that is derived from DataSet that is "pre-configured" with your database schema. Other typed classes deriving from DataTable and other supporting classes are also defined as well.
Typed DataSet s are very handy when using the designer in VS.NET for data-bound controls like the DataGrid because the designer can discover all your table and column names so you can bind to them easily. Simply open the toolbox, select the Data catagory, then drag a "DataSet" in. When it asks, choose to create a typed DataSet from the list (if it's defined in your project) or click "Referenced Projects..." to find typed DataSet s in projects that the current project references.
Why are they better? Well, first you don't have to define all your tables and columns programmatically; they're already defined in your new class. Second, they're much faster depending on how you access data. Commonly, people will use code like this:
string s = (string)dataSet1.Tables["MyTable"].Rows[0]["ID"]; That is a very expensive call. First, the tables must be enumerated to find the one named "MyTable" (which includes expensive, case-insensitive string searches). Then the first row is obtained and the column with the name "ID" is found in a simiar fashion, except that columns are first enumerated and then the N'th row's data is retrieved.
When you use a typed DataSet and use code like the following, the lookups are not necessary because the tables and references columns are references to the tables and columns already instantiated - no lookups are required:
string s = myDataSet1.MyTable.Rows[0].ID; Also notice I didn't have to cast to a string? While casting is done internally in the typed DataSet class, you don't have to worry about cast exceptions in your code, which is good encapsulation.
Finally, when you use the designer to generate a derivative DataAdapter , all the table and column mappings are done for you automatically.
While the benefits are great when using the VS.NET designers, the runtime benefits are good, too. Few to no lookups are required and it's easier to discover type information at runtime for abstract implementations.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hi guys..
I've a project and I want to put my principal web page in cache, and the server should refresh the information each 5 or 10 minutes.
I wait for yours ideas !!!
Thanks..
.............................
|
|
|
|
|
Here's an idea: try google[^]. COUNTLESS projects have been written that already do this and the source for many - in about every language, framework, and platform you can think of - is available. This is a trivial thing to implement. In .NET, for instance, you could simply use an HttpWebRequest (preferrably using async operations) on a timer.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hi...
Really now I don't know who I can print only 1 or 2 or three decimal digits of a float number in C#. 1.234566 --result--> 1.23 (two decimals places)
How I can do that ??
Thanks...
.............................
|
|
|
|
|
ToString has overloaded methods that allow you to provide a format specifier.
Christian
I have drunk the cool-aid and found it wan and bitter. - Chris Maunder
|
|
|
|
|
A great site for formatting numbers:
http://authors.aspalliance.com/aspxtreme/aspnet/types/numericformatstrings.aspx
|
|
|
|
|
Hi ppl!
In my program I need to catch the axWebBrowser1 'DocumentComplete' event. But I find out that this event happens more than 1 times !!!?? At some pages it even happens 7 or 8 times !! Why is this ??? And how I can tell if this is very last chance when it happens (document completly loaded) or there's will be more 'DocumentComplete' events ???
Please help - this is extremly important to me
"I have not failed.
I've just found 10,000 ways that won't work."
- Thomas Alva Edison (1847-1931)
|
|
|
|
|
Hi.
I believe that this link[^] adequately addresses your issue. (Unless you can't figure out how to do the pDisp comparison in C#.)
John
"You said a whole sentence with no words in it, and I understood you!" -- my wife as she cries about slowly becoming a geek.
|
|
|
|
|
Hi man !!
Thanks for the answer - very helpfull. But you see - I'm still having problems with determinate when exactly web page is loaded
I'm trying to receive IHTMLCollection from axWebBrowser.Document from some news web site (the url is http://www.lenta.ru) For the very bad luck I choosed this site to test my collection with and I still receive a weird result Sometimes the size of collection is 2069 elements and sometimes (I just hit refresh button I receive collection of 2065 (!) elements and so on... I don't know what to do Seems to me I can't really lock on the page and some elements are missing (?) sometimes ???
Any sugestions ???
"I have not failed.
I've just found 10,000 ways that won't work."
- Thomas Alva Edison (1847-1931)
|
|
|
|
|
I'm having trouble understanding what your code is really doing. Where did this collection with 2056 elements come from?
The axWebBrowser.Document itself shouldn't be changing, but its content will be.
John
"You said a whole sentence with no words in it, and I understood you!" -- my wife as she cries about slowly becoming a geek.
|
|
|
|
|
Here you go the full (almost) source code
<br />
this.webBrowser.AddressBar = false;<br />
this.webBrowser.Dock = DockStyle.Fill;<br />
this.webBrowser.FullScreen = true;<br />
this.webBrowser.MenuBar = false;<br />
this.webBrowser.Offline = false;<br />
this.webBrowser.RegisterAsBrowser = true;<br />
this.webBrowser.RegisterAsDropTarget = false;<br />
this.webBrowser.Silent = true;<br />
this.webBrowser.StatusBar = false;<br />
this.webBrowser.TheaterMode = true;<br />
.<br />
.<br />
.<br />
<br />
<br />
<br />
private void webBrowser_DocumentComplete (object sender,AxSHDocVw.DWebBrowserEvents2_DocumentCompleteEvent e)<br />
{<br />
++this.tempCounter;<br />
<br />
if ( sender.Equals((object)this.webBrowser) && this.webBrowser.ReadyState.Equals(SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE))<br />
{<br />
MessageBox.Show ("Done loading\n\nLoaded " + this.tempCounter.ToString() +" times", "Document loaded");<br />
<br />
htmlDocGlobal = (mshtml.IHTMLDocument2) webBrowser.Document;<br />
<br />
if (clickEvent == null)<br />
{<br />
clickEvent = (mshtml.HTMLDocumentEvents2_Event) htmlDocGlobal;<br />
clickEvent.onclick += new mshtml.HTMLDocumentEvents2_onclickEventHandler (On_MouseClick);<br />
}<br />
}<br />
}<br />
<br />
<br />
private bool On_MouseClick (mshtml.IHTMLEventObj e)<br />
{<br />
if (e.button.Equals (0))<br />
{<br />
<br />
ArrayList m_PathToElement = new ArrayList();<br />
IHTMLElement m_Parent = null;<br />
IHTMLElement m_Child = null;<br />
IHTMLElementCollection m_ParentCol = null;<br />
IEnumerator colEnum = null;<br />
<br />
m_Child = e.srcElement;<br />
m_Parent = m_Child.parentElement;<br />
<br />
while (m_Child.parentElement != null)
{ {<br />
m_ParentCol = (IHTMLElementCollection) m_Parent.all;<br />
<br />
System.Windows.Forms.Application.DoEvents ();
colEnum = m_ParentCol.GetEnumerator ();<br />
colEnum.MoveNext ();
.<br />
.<br />
.<br />
.<br />
.<br />
Then I go throught collection and search for ckicked element till the root element.<br />
}<br />
}<br />
}<br />
I make some checks for received htmlDocGlobal and the size is different all the time
If you need the full source code please contact me by eMail
"I have not failed.
I've just found 10,000 ways that won't work."
- Thomas Alva Edison (1847-1931)
|
|
|
|
|
It looks like you have 2 separate problems. First, test only the part that determines whether the page has finished loading. Once that is ready, then work on those other portions. The simpler you make each test, the easier it is to determine where the problem lies.
If you need the complete page and all of its elements to finish loading before you do anything, then you'll need to track each sub-document and note when that has finished as well. Then, when they are all completely loaded, you can do your work.
John
"You said a whole sentence with no words in it, and I understood you!" -- my wife as she cries about slowly becoming a geek.
|
|
|
|
|
Yeah I thought about - checking all elements in the page for .ReadyState but I don't know how to do it Can you show me some code ???
(I check my prog on www.lenta.ru and this web page have 6 frames and 1 pop-up window)
"I have not failed.
I've just found 10,000 ways that won't work."
- Thomas Alva Edison (1847-1931)
|
|
|
|
|
One way to do that would be to add each new document element to a collection when the document state changes. (If your ArrayList doesn't Contain() the document element, then Add() it.) Later, when the state of all those documents is complete, then test to see if you have the information you should have.
John
"You said a whole sentence with no words in it, and I understood you!" -- my wife as she cries about slowly becoming a geek.
|
|
|
|
|
Heres the deal:
I was looking at a control this guy made, its a menu control but behaves in a way I have never seen.
- You place his menuProvider control on a form (in design mode).
- You place the standard .NET mainMenu control on the form as well.
Now, You can add menuEntries to the .NET mainMenu control -- but in the properties panel it has a new property that ties it to the menuProvider. This standard non-subclassed .NET mainMenu has a new custom property?
How?
Did I miss a huge chunk about programming windows controls where you can modify properties of standard delivered objects?
Matthew Hazlett
Windows 2000/2003 MCSE
Never got an MCSD, go figure...
|
|
|
|
|
It sounds like he used the IExtenderProvider interface, which is implemented by the ToolTip and HelpProvider controls that you may have used already. Take a look at the docs here[^].
John
"You said a whole sentence with no words in it, and I understood you!" -- my wife as she cries about slowly becoming a geek.
|
|
|
|