Introduction
I have a script which runs many sub programs, each sub program fetches a web page, filters its contents and outputs frequently (the output are placed in stdout
). It usually works fine, although sometimes it hangs. It is not good because one sub program hangs, the whole script hangs. When it hangs, I always start the Process Explorer to kill this sub program, then the script keeps running. I wanted the script to kill the dead sub program after 30 seconds automatically, so I wrote this program.
Sorry my English is bad.
Background
None.
Using the Code
This is a console application. This program's command line format is:
exec4.exe seconds commandline arguments
For example, the following command will run "dir /s c:\
", wait for 10 seconds and kill.
exec4.exe 10 cmd.exe /c dir /s c:\
You can get exec4.exe. Please download and extract Exec4.zip, and compile:
csc exec4.cs
The source code is listed below:
using System;
using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Collections.Generic;
class Exec4
{
[DllImport("kernel32.dll")]
public static extern int WinExec(string exeName, int operType);
public static void Main(string []args)
{
if (args.Length<1)
{
Console.WriteLine("Usage:");
Console.WriteLine("\tExec4.exe Seconds Commandline");
return;
}
else
{
int Expires;
try
{
Expires = Convert.ToInt32(args[0]);
}
catch
{
Expires = -1;
}
if (Expires<=0)
{
Console.Error.Write("Seconds argument error: ");
Console.Error.WriteLine(args[0]);
return;
}
string cmdLine=args[1];
for (int i=2; i<args.Length; i++) cmdLine+=" "+args[i];
string AppName=args[1];
if (AppName.ToLower().EndsWith(".exe")) AppName=
AppName.Substring(0, AppName.Length-4);
List<int> ProcessIds=new List<int>();
foreach (Process aProcess in Process.GetProcessesByName
(AppName))
ProcessIds.Add(aProcess.Id);
int hr=WinExec(cmdLine,0);
if (hr<=31)
{
Console.Error.Write("SubProgram executes abnormally: ");
Console.Error.WriteLine(cmdLine);
return;
}
DateTime dtStart=DateTime.Now;
int SubProgramProcessId=-1;
foreach (Process aProcess in Process.GetProcessesByName
(AppName))
if (-1==ProcessIds.IndexOf(aProcess.Id))
{
SubProgramProcessId=aProcess.Id;
break;
}
if (-1==SubProgramProcessId)
{
Console.Error.WriteLine("Cannot stop SubProgram!");
return;
}
while ((DateTime.Now - dtStart).TotalSeconds<Expires)
{
Thread.Sleep(100);
int found=0;
foreach (Process aProcess in Process.GetProcessesByName
(AppName))
if (SubProgramProcessId==aProcess.Id)
{
found=1;
break;
}
if (0==found) return;
}
foreach (Process ExpiredProcess in Process.GetProcessesByName
(AppName))
if (SubProgramProcessId==ExpiredProcess.Id)
ExpiredProcess.Kill();
Console.Error.WriteLine("Expire!");
Environment.Exit(-1);
}
}
}
Points of Interest
This program uses WinExec
Windows API to launch the sub program. It uses Process.GetProcessesByName()
function to get related programs and kill the pending sub program as necessary.
Summary
This article describes an approach to start a sub program and stop it automatically. It doesn't kill the sub program's process tree. It introduces a method to kill the pending sub program without any warrant. I hope it is useful to you. Happy Labor's Day!
History
- 30.04.09 - Original version