Task Scheduler using C# (To Schedule .bat(batch) file) - c#

I want to create one Task Scheduler using C# same as Windows Task Scheduler, to run my .bat (batch) file on particular time.
I found this useful link (http://www.codeproject.com/Articles/38553/TaskScheduler)
in this they schedule trigger, and i want to Schedule my .bat file
I mean while i am trying to give my batch file path in tags textbox, its just fired trigger, not run my batch file
so, i modify that code little bit, and now I am able to run my batch file also,
but, when i close my application triggering also stop,
so, is there any way i can triggering or run my batch file even if i close my application liks window task scheduler???
kindly Help me .
Note: its desktop application using C#

you can place the path of your batch file in tags textbox .Checkbox the Active in one time only box ,set the time and at that time the trigger is fired.
Note: It justs fire's the trigger.What you are loking is to run the batch file.In that case you need to modify the code. you can start from
private void buttonCreateTrigger_Click(object sender, EventArgs e)
{
CreateSchedulerItem();
}
in Demo.cs page
In order to run your batch file or exe in TaskScheduler.cs find and replace this code
void _triggerTimer_Tick(object sender, EventArgs e)
{
_triggerTimer.Stop();
foreach (TriggerItem item in TriggerItems)
if (item.Enabled)
while (item.TriggerTime <= DateTime.Now)
item.RunCheck(DateTime.Now);
System.Diagnostics.Process.Start("Your Path");
_triggerTimer.Start();
}
Now you can save this path in some knid of common class and make it access to both.

So, what's the problem? After downloading you can check the Demo.cs, where you can find the method private void CreateSchedulerItem() and the event triggerItem_OnTrigger. You can change this event to run the batch file that you need.

Something like this. I hope that you can change Console.WriteLine on System.Diagnostics.
static void Main(string[] args) {
AutoResetEvent autoResetEvent = new AutoResetEvent(false);
Timer timer = new Timer(PrintHello, autoResetEvent, 0, 5000);
autoResetEvent.WaitOne();
}
private static void PrintHello(Object state) {
Console.WriteLine("Hello");
}

Related

Pass String from python script to C# UI [duplicate]

I'm making a program that controls a game server. One of the functions I'm making, is a live server logfile monitor.
There is a logfile (a simple textfile) that gets updated by the server as it runs.
How do I continuously check the logfile and output it's content in a RichTextBox?
I did this simple function just try and get the content of the log. It will of course just get the text row by row and output it to my textbox. Also it will lock the program for as long as the loop runs, so I know it's useless.
public void ReadLog()
{
using (StreamReader reader = new StreamReader("server.log"))
{
String line;
// Read and display lines from the file until the end of the file is reached.
while ((line = reader.ReadLine()) != null)
{
monitorTextBox.AppendText(line + "\n");
CursorDown();
}
}
}
But how would you go about solving the live monitoring as simple as possible?
*** EDIT ***
I'm using Prescots solution. great stuff.
At the moment I'm using a sstreamreader to put the text from the file to my textbox. I ran into the problem is that, whenever I tried to access any of the gui controls in my event handler the program just stopped with no error or warnings.
I found out that it has to do with threading. I solved that like this:
private void OnChanged(object source, FileSystemEventArgs e)
{
if (monitorTextField.InvokeRequired)
{
monitorTextField.Invoke((MethodInvoker)delegate { OnChanged(source, e); });
}
else
{
StreamReader reader = new StreamReader("file.txt");
monitorTextField.Text = "";
monitorTextField.Text = reader.ReadToEnd();
reader.Close();
CursorDown();
}
}
Now my only problem is that the file.txt is used by the server so I can't access it, since it's "being used by another process". I can't control that process, so maybe I'm out of luck.
But the file can be opened in notepad while the server is running, so somehow it must be possible. Perhaps I can do a temp copy of the file when it updates and read the copy. I don't know.
Check out the System.IO.FileSystemWatcher class:
public static Watch()
{
var watch = new FileSystemWatcher();
watch.Path = #"D:\tmp";
watch.Filter = "file.txt";
watch.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite; //more options
watch.Changed += new FileSystemEventHandler(OnChanged);
watch.EnableRaisingEvents = true;
}
/// Functions:
private static void OnChanged(object source, FileSystemEventArgs e)
{
if(e.FullPath == #"D:\tmp\file.txt")
{
// do stuff
}
}
Edit: if you know some details about the file, you could handle the most efficent way to get the last line. For example, maybe when you read the file, you can wipe out what you've read, so next time it's updated, you just grab whatever is there and output. Perhaps you know one line is added at a time, then your code can immediately jump to the last line of the file. Etc.
Although the FileSystemWatcher is the most simple solution I have found it to be unreliable in reality.. often a file can be updated with new contents but the FileSystemWatcher does not fire an event until seconds later and often never.
The only reliable way I have found to approach this is to check for changes to the file on a regular basis using a System.Timers.Timer object and checking the file size.
I have written a small class that demonstrates this available here:
https://gist.github.com/ant-fx/989dd86a1ace38a9ac58
Example Usage
var monitor = new LogFileMonitor("c:\temp\app.log", "\r\n");
monitor.OnLine += (s, e) =>
{
// WARNING.. this will be a different thread...
Console.WriteLine(e.Line);
};
monitor.Start();
The only real disadvantage here (apart from a slight performance delay caused by file size checking) is that because it uses a System.Timers.Timer the callback comes from a different thread.
If you are using a Windows Forms or WPF app you could easily modify the class to accept a SynchronizingObject which would ensure the event handler events are called from the same thread.
As #Prescott suggested, use a FileSystemWatcher. And make sure, you open the file with the appropriate FileShare mode (FileShare.ReadWrite seems to be appropriate), since the file might still be opened by the server. If you try to open the file exclusively while it is still used by another process, the open operation will fail.
Also in order to gain a bit of performance, you could remember the last position up to which you already have read the file and only read the new parts.
Use this answer on another post c# continuously read file.
This one is quite efficient, and it checks once per second if the file size has changed.
You can either run it on another thread (or convert to async code), but in any case you would need to marshall the text back to the main thread to append to the textbox.
Try adding a Timer and have the Timer.Tick set to an Interval of 1 second. On Timer.Tick you run the function.
private void myTimer_Tick(object sender, EventArgs e)
{
ReadLog();
}

Pause and resume a download WPF

Hello I am working on a WPF platform targeting .NET framework 4.5.2. I am writing a downloader for my application. Here is the code:
private void Download(Dictionary<int, FileAndLinkClass> MyLinks)
{
ApplicationDownloadThread = new Thread(() =>
{
foreach (KeyValuePair<int, FileAndLinkClass> item in MyLinks)
{
fileNo++;
WebClient myWebClient = new WebClient();
myWebClient.DownloadProgressChanged += MyWebClient_DownloadProgressChanged;
myWebClient.DownloadFileCompleted += MyWebClient_DownloadFileCompleted;
// Download the Web resource and save it into the current filesystem folder.
string downloadedFileAdress = System.IO.Path.Combine(fileLocation, $"{item.Value.FileName}");
myWebClient.DownloadFileAsync(new Uri(item.Value.Link), downloadedFileAdress);
while (myWebClient.IsBusy)
{
}
}
});
ApplicationDownloadThread.IsBackground = false;
ApplicationDownloadThread.Start();
//UnZipAndCreateUpdatePackage(MyLinks);
}
Now I want at button click the download must be paused and at another button click the download must be resumed. I tried working with .set() property of an AutoReset event and .Reset() property of the same but it didn't work.
I need help. My button click code are:
private AutoResetEvent waitHandle = new AutoResetEvent(true);
private void StartDownloadBtn_Click(object sender, RoutedEventArgs e)
{
waitHandle.Set();
}
private void StopDownloadBtn_Click(object sender, RoutedEventArgs e)
{
waitHandle.Reset();
}
I have also tried this link How to pause/suspend a thread then continue it?. nothing happens
I've also gone through Adding pause and continue ability in my downloader but I failed to incorporate the solution in my above code as I am also updating the download progress on the UI.
Well I did some more digging, apparently if for you Adding pause and continue ability in my downloader wasn't clear as the it uses byte stream data in the class. Maybe you could check out the link below, it also provides a VS solution on WPF for the downloading .zip file extensions with pause/resume/stop capabilities. Please let me know if you need some more help.
Link to CodeProject article:
C# .NET Background File Downloader

How to reopen a file immediately after it closes via my C# application

I ran out of ideas and couldn't find any reference about it so here I go...
I need to keep a secondary application wich is not related to my c# project always running in background. So if this secondary application crashes or someone else close it manually it will automatically re launch again via my c# app.
I have no clue of how to accomplish this one, I mean checking if this application closes by something external to my c# app.
Any help would be greatly appreciated.
Thanks in advance.
The below code is in C# and it is inside a WinForm.
private void Form1_Load(object sender, EventArgs e)
{
Process p = Process.GetProcessesByName("Notepad")[0];
p.EnableRaisingEvents = true;
p.Exited += new EventHandler(p_Exited);
}
void p_Exited(object sender, EventArgs e)
{
MessageBox.Show("Exit");
}
It looks for a Process with Name Notepad & retrieved the first instance of it. It sets EnableRaisingEvents to true on it and hooks to the Exited event. Whenever notepad is closed it would display an alert.
Based on this logic, you can build your app.
As a solution you can use Windows service which invokes your always running application .
You can make that service catch error return codes from the app and restart it depending on errors.
you can keep checking for a process if it is running or not using process class in vb.net
For Each p As Process In Process.GetProcessesByName("communicator")
ShowWindow(p.MainWindowHandle, SHOW_WINDOW.SW_NORMAL)
Next p
if the process you want not inthe list you may launch it again.
Ashish kumar
Simplest way is to run a timer and in the tick event, use-
if (Process.GetProcessesByName("communicator").Count() == 0)
{
Process.Start("communicator.exe");
}
You can use FileSystemWatcher to keep a watch of the file modified by other application.
FileSystemWatcher has events like Changed, Created,Renamed, Deleted, which can be subscribed to keep track of a file changes.

How do I limit my Windows application to spawning a single instance of a process?

I am working on a Windows application. I have created a help file (.chm) using a third party tool and I call it from the Windows application. The help file is invoked successfully when I click on Help menu item or press F1 for the application.
The problem I am facing is that if I click on the menu item again or press F1 (while the application is open and I have not closed the previous help file) it opens another instance of the help file.
Let me be clear by giving an example: I want it to be just like the "Solitaire" game. No matter how many times you press F1 or the Contents menu item it shows only one help window.
I want to do same thing like "Solitaire". I don't want multiple instances to be created.
I hope you understood my problem. Please let me know if my query is wrong.
I have posted my code below.
ProcessStartInfo info;
Process exeprocess;
The below code is in Help menuitem click event.
private void mnuContents_Click(object sender, EventArgs e)
{
string ApplicationPath=ConfigurationSettings.AppSettings["HelpFile"].ToString();
info = new ProcessStartInfo(ApplicationPath);
//Process.Start(info);
exeprocess = Process.Start(info);
}
One solution is:
Have your application create a system-wide resource (the example below uses a Win32 mutex)
Check the resource before you spawn the .chm (I imagine you're probably using ShellExec or some variant to spawn the help file.
Here's example code (in C++/Win32 code):
http://support.microsoft.com/kb/243953
Another, different approach is to see if any currently running processes match the one you would spawn. Here's example code for this approach:
http://www.dotnetperls.com/single-instance-windows-form
You have a Process object, so you should probably store it somewhere and check if it is still active the next time the help command is invoked. You could use Process.HasExited for that purpose. If it has exited, clean up the Process object by calling Dispose() and then launch a new instance, storing it away again. Repeat as needed.
Ok this is your block of code to start the CHM viewer:
private void mnuContents_Click(object sender, EventArgs e)
{
string ApplicationPath=ConfigurationSettings.AppSettings["HelpFile"].ToString();
info = new ProcessStartInfo(ApplicationPath);
//Process.Start(info);
exeprocess = Process.Start(info);
}
in exeprocess there is a property called Id. You need to keep track of that Id for the next time the user presses F1 or the menu key.
You need to do a check like
private void mnuContents_Click(object sender, EventArgs e)
{
if (Process.GetProcessById(self.previousId) != null) {
string ApplicationPath=ConfigurationSettings.AppSettings["HelpFile"].ToString();
info = new ProcessStartInfo(ApplicationPath);
//Process.Start(info);
exeprocess = Process.Start(info);
self.previousId = exeprocess.Id;
}
}
Something like that would work. If you want to get fancy, you can bring the already-running process to the foreground as well.

C#/.NET: Closing another process outside the main window

I just wanna ask your opinion/suggestion on how to 'terminate' a running application/process is C#
Right now, I do have the following codes:
Process myProcess;
private void btnOpen_Click(object sender, RoutedEventArgs e)
{
DirectoryInfo di = new DirectoryInfo(System.Environment.GetFolderPath(Environment.SpecialFolder.Programs));
myProcess = Process.Start(di + #"\Wosk\Wosk.appref-ms"); // opening a file coming for Startup Menu
}
private void btnClose_Click(object sender, RoutedEventArgs e)
{
myProcess.Kill(); // not working - Cannot process request because the process has exited
}
I also tried myProcess.Close(); but nothing's happening.
You should have a look at
Process.HasExited Property
A process can terminate independently
of your code. If you started the
process using this component, the
system updates the value of HasExited
automatically, even if the associated
process exits independently.
Based on your comment it looks like the Process instance has already exited when you hit the close button. This can happen at any time and it's something you need to guard against. The easiest way is to simply catch the exception that results from calling Kill on an already exited process.
try {
myProcess.Kill();
} catch ( InvalidOperationException ) {
// Process is already finished so nothing to do
}
You are starting a program that was installed with ClickOnce. The .appref-ms is executed by a helper program, rundll32.exe, that starts the process and quickly exits. To terminate the started process, you'll need to find the actual running .exe with Process.GetProcessesByName() and use the Kill method.
We can't tell you what the process name is, that's contained in the .appref-ms file. But it is easy for you to see with TaskMgr.exe.
Process[] islemler = Process.GetProcessesByName("osk");
foreach (Process islem in islemler)
islem.Kill();
First please replace:
di + #"\Wosk\Wosk.appref-ms"
with:
Path.Combine(di.FullName, #"Wosk\Wosk.appref-ms")
Now to the point: I don't know what Wosk.appref-ms is or how this process is started. If this is a file it will be opened with the default program associated with this file extension. The problem could be related to the fact that the process you start only starts another process and terminates immediately. That's why when you try to kill it it says that it has already exited, but the actual process it spawned is still running. In this case you will have to enumerate through the running processes with Process.GetProcesses(), find the process and stop it.

Categories

Resources