Console app scheduled task run two different ways - c#

I have a program for a client that needs to run one set of code every 30 minutes via a scheduled task.
at 1:30 am it needs to run a separate set of code.
Both sets of code will generate a file and place it in a directory.
How do I set it up to be able to run two sets of SQL code?
I could do it getting the current date time and comparing it but that seems bulky to me.
Is there a way a schedule task can run a program which would pass in something to my Main(string[] args)?
Is there a correct way to do it without creating two separate apps?

Make your program accept parameters, then schedule your console app (using Windows scheduler) with the different parameters... something like:
void Main(string[] args)
{
var firstArg = args.FirstOrDefault();
if (firstArg == "option1")
{
// do stuff
}
else if (firstArg == "option2")
{
// do other stuff
}
}
In scheduler do something like:

Write to flat file your param result from the first process, or database and get it from there with the second process.. Or just have your process always running and use stopwatch to perform events every 30 minutes instead of using the task scheduler, then you can keep it in memory. You have a lot of options.

Related

C# monitor external process state

I am making a launcher app in C# on windows. However the process isn't directly started by my C# application but it uses a url to start it e.g "steam://rungameid/xxxxxxx"
I need it to monitor a process by name (say XYZ.exe) in the following fashion:
Receive an event when XYZ.exe starts
Receive an event when XYZ.exe exits
I just want to minimise and restore the my C# application's form when the application is running and not running respectively
thanks
Make a timer (with your preferred timer method) and poll every 'n' milliseconds (find what's best for you... I'd say for minimizing/restoring from a game, 500 milliseconds could be a good start, but experiment), then you can use something like:
bool processRunning = false;
void timerTickMethod()
{
var procIsRunning = Process.GetProcessesByName("xyz.exe").Any();
if(procIsRunning && !processRunning)
ProcessIsStartedEvent(); // or directly minimize your app
else if(!procIsRuning && processRunning)
ProcessIsEndedEvent(); // or directly restore your app
processRunning = procIsRunning;
}
If you want to make sure it's your xyz.exe that is running, you can pass in the full path to GetProcessesByName (so that if there's other xyz.exe in your system, it won't confuse your app)
Update
I was writing from memory, so maybe GetProcessesByName only work for friendly names (with no exe, or path).
If that's the case (I haven't tried), and you need the full path you could do it like:
var procIsRunning = Process.GetProcesses().Any(x => x.MainModule.Filename == #"c:\your\full\path.exe");

execute query using time hour in console application c#

i want to truncate table using console application with parameter hour.
for example, i want to run query truncate at 12.00 AM using time in system.
this is my code in console application using c#.
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string getHour = DateTime.Now.ToString("h:mm:ss tt");
if (getHour == "12:00:00 AM")
{
Console.WriteLine("Do action to run query truncate");
//in this line i will execute query truncate.
}
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
}
And this is not working. please give me solution or sample code to fix my problem.
thanks...
I would suggest few things on your code:
Don't use string comparison, but uses DateTime directly (take a look on TimeOfDay.TotalSeconds). This way, it makes the comparison a lot easier
Use repeated calls instead of just one call (unless you can really be sure that you run your program exactly at 12). This way you make your program work for you more.
To make it more robust, provide some ways to give tolerance to your system. This is how good automation should be.
Example:
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
while (true) { //read 2. assuming this is to be run forever in this example, but gives also some way to break the loop whenever necessary in your app
if (DateTime.Now.TimeOfDay.TotalSeconds <= 1) { //read 1. and 3. this way, you give tolerance of 1 second. Your action will be run on 12:00:00 - 12:00:01
Console.WriteLine("Do action to run query truncate");
// //in this line i will execute query truncate.
break; //break after saving once, for instance, and run again when the time close... This is to prevent possible multiple executions...
}
System.Threading.Thread.Sleep(500); //read 2. and 3. check every 500 millisecond, at least to give chance to check the time twice per second
}
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
}
When you run your program, it looks on the clock quickly, and if it is not exactly midnight immediately exits. (To be more precise it prints some message and waits until keypress). I believe you wish to wait until midnight. If the exact timing is not that important (I mean some seconds early or late is acceptable), the simplest solution is:
static void Main(string[] args)
{
Thread.Sleep(DateTime.Today.AddDays(1) - DateTime.Now);
Console.WriteLine("It's about midnight, I go to sleep");
}
I feel like the issue is with the flow of execution of your code.
You're calling the code once and then it stops. It checks once NOW and get the current time. If the time is 12:00:00 AM, you can pass into the if statement, but you'll need to literally run this at 12:00:00 System time on the dot, which is nearly impossible.
You should consider a Windows Service or using Windows Task Manager: C# Console Application - Keep it running.
As mentioned in the other answers you shouldn't be using your app to schedule the task. It looks like you are doing a database maintenance task so the first thing I would look at is...
1) See if your database can schedule tasks. SQL Server Agent for example can schedule stored procedures (or adhoc SQL) to be run at set times and would accomplish your task if you are using that for your database. More info here.
If your database can't do this or you want to do other things other than truncate the table then...
2) try using Windows Task Scheduler
This can launch an application at set times, is easy to setup and then your application can just do the job it's mean to do (e.g. truncate the table) and not worry about the scheduling.

How does one configure Quartz.net to run a job when another job hasn't run for a period

Assume I have two Quartz.net jobs that
downloads a CSV file with a delta of changes for a period (e.g. 24h) and then imports the data (called IncrementalImportJob)
downloads a CSV file with a all the records and then imports the data (called FullImportJob)
The requirement is that IncrementalImportJob at a minimum once for the period (e.g. 24h). If that window is missed, or the job didn't complete successfully, then FullImportJob should run instead. The reason is that changes for that (missed) day would not be imported. This condition is rather exceptional.
The FullImportJob requires resources (time, CPU, database, memory) to import all the data, which may impact other systems. Further, the delta of changes are often minimal or non-existent. So the goal is to favour running the IncrementalImportJob when possible.
How does one configure quartz.net to run FullImportJob if IncrementalImportJob hasn't completed successfully in a specific time period (say 24h)?
Searching the web for "quartz.net recovery" and "quartz.net misfire" doesn't reveal whether its supported or whether its even possible.
There is native misfire handling in quartz.net, however it only goes as far as specifying whether the job should fire immediately again, or after a period of time or a number of times after misfiring.
I think one option is to handle this internally from IncrementalImportJob.
try
{
//download data
//import data
}
catch (Exception e) //something went wrong
{
//log the error
UpdateFullImportJobTrigger(sched);
}
//Reschedule FullImportJob to run at a time of your choosing.
public void UpdateFullImportJobTrigger(IScheduler sched)
{
Trigger oldTrigger = sched.getTrigger(triggerKey("oldTrigger", "group1");
TriggerBuilder tb = oldTrigger.getTriggerBuilder();
//if you want it to run based on a schedule use this:
Trigger newTrigger = tb.withSchedule(simpleSchedule()
.withIntervalInSeconds(10)
.withRepeatCount(10)
.build();
sched.rescheduleJob(oldTrigger.getKey(), newTrigger);
//or use simple trigger if you want it to run immediately and only once so that
//it runs again on schedule the next time.
}
This is one way of doing it. Another would be abstracting this logic to a maintenance job that checks the logs every so often and if it finds a failure message from IncrementalImportJob, it fires FullImportJob. However, this depends to some extent on your logging system (most people use NLog or log4net).
If on the other hand, your concern is that the job never ran in the first place because, for instance, the app/database/server was down, you could schedule FullImportJob to fire a few hours later and check if IncrementalImportJob has fired as follows:
//this is done from FullImportJob
//how you retrieve triggerKey will depend on whether
//you are using RAMJobStore or ADO.NET JobStore
public void Execute(IJobExecutionContext context)
{
ITrigger incImportJobTrigger = context.Scheduler.GetTrigger(triggerKey);
//if the job has been rescheduled with a new time quartz will set this to null
if (!incImportJobTrigger.GetPreviousFireTimeUtc().HasValue) return;
DateTimeOffset utcTime = incImportJobTrigger.GetPreviousFireTimeUtc().Value;
DateTime previousTireTime = utcTime.LocalDateTime;
if (previousTireTime.Day == DateTime.Now.Day) return;
//IncrementalImportJob has not ran today, let's run FullImportJob
}
Hope this helps.

How can a Windows Service create a process?

I want to create program that run all the time (not a Windows Service exactly). I want it to have no view to the user.
I would like it to be a process, the reason I don't want it to be service is because I want to create to process and I want one service to start them.
I don't know how to create the program without any UI as if I create console application the CMD open when I run the program.
I'm taking a guess as to what you're trying to do, but here's a really simple console application that runs until you hit the ENTER key. It will print out a line to the console every second.
class Program
{
static void Main(string[] args)
{
using (System.Threading.Timer processTimer = new System.Threading.Timer(DoSomething, "fun", 0, 1000))
{
Console.ReadLine();
}
}
static void DoSomething(object data)
{
Console.WriteLine("doing something {0}...", data.ToString());
}
}
You can replace the contents of DoSomething with what you need your console runner to do.
I hope this helps.

How to make script/program to make it so an application is always running?

I have a simple .exe that needs to be running continuously.
Unfortunately, sometimes it crashes unexpectedly, and there's nothing that can be done for this.
I'm thinking of like a C# program that scans the running application tree on a timer and if the process stops running it re-launches it... ? Not sure how to do that though....
Any other ideas?
It's fairly easy to do that, but the "crashes unexpectedly, and there's nothing that can be done for this" sounds highly suspect to me. Perhaps you mean the program in question is from a third party, and you need to work around problems they can't/won't fix?
In any case, there's quite a bit of sample code to do exactly what you're talking about.
The first solution would be to fix your EXE, so it does not crash. If you can not fix it now, you probably need to add exception handling, so you can catch the exception, and not close the EXE.
Second solution is to write simple guard programm that will start your simple .exe and will monitor specific process handle. It will restart your program when it closes.
easiest way is to have you program see if an instance of itself is running and exit if it is. Set up a scheduled task to run it every couple of minutes.
class Program
{
static void Main(string[] args)
{
if (IsRunning())
{
return;
}
else
{
for (int x = 0; x < 10; x++)
{
//Do Stuff
System.Threading.Thread.Sleep(1000);
}
}
}
private static bool IsRunning()
{
Process[] P = Process.GetProcessesByName( Process.GetCurrentProcess().ProcessName ) ;
return P.Count() > 1;
}
}
One trick occasionally employed by malware in days past was to have two processes that each monitor the currently running processes and restart the other process if it is terminated.
The System.Diagnostics namespace has classes which can help, particularly "Process".
For example
static Process[] Process.GetProcesses()
returns a list of all the currently running processes.
If your other process is not in this list, you just restart it with, for example
Process.Start()
Your program needs to initially start your target process itself (with Process.Start), then simply wait for it to terminate (with WaitForExit on object that is returned by Process.Start()). After that whole procedure is repeated.
This way you'd be sure that you are watching the process you are interested in, and you don't need to poll process list at all.
Process.Start() and WaitForExit() usage example.

Categories

Resources