Where to define scripts that deletes files older then 7 days - c#

I need to write script that delete files older than 7 days in MVC .Net application. I'm going to use this code
List<string> DeletePath = new List<string>();
DirectoryInfo info = new DirectoryInfo(Server.MapPath("~\\TempFiles"));
FileInfo[] files = info.GetFiles().OrderBy(p => p.CreationTime).ToArray();
foreach (FileInfo file in files)
{
DateTime CreationTime = file.CreationTime;
double days = (DateTime.Now - CreationTime).TotalDays;
if (days > 7)
{
string delFullPath = file.DirectoryName + "\\" + file.Name;
DeletePath.Add(delFullPath);
}
}
foreach (var f in DeletePath)
{
if (File.Exists(F))
{
File.Delete(F);
}
}
But i don't know where to define this and how to call. Do i need to create new Controller or something similar?

wrap your code in a static method and use hangfire
http://docs.hangfire.io/en/latest/background-methods/performing-recurrent-tasks.html
RecurringJob.AddOrUpdate(() => myCleanup.CleanupOldFiles(), Cron.Hourly)

Well you need to create a window service which will run in background on the server. Window services are the normal application which run automatically without any user event. Create a window service, then you can write the same code there wrapped in a timer tick event. There you can set the time when you want to execute this code.
Usually window service once deployed start executing your code every second. So you need to set the clock. With the Timer, you can execute your code as per your requirement, everyday at particular time, once in a week, once in a month or so on so forth.
Read more about window services here...
and let me know if you need code for this.

Mvc is not the job for this. It's like asking how to install tires on a train so that it can drive up a private street.
In order for Mvc or any web application for that matter to do something, a request must come in from a client. If no request comes in, IIS does nothing and just "listens" for incoming connections. To do this the "correct" way, you have two options:
Create a batch file or Powershell script or even a C# console application that deletes the files, then setup that batch file or script or program to run in Windows Task Scheduler.
If you need more logic to determine when the files should be deleted or you need customized schedules, then you should make a Windows Service Application. You can make this in C# and you can pretty much have it do anything you want, so long as it doesn't need a GUI. If you do need a GUI, perhaps to configure the service, then you can make a separate WinForms or WPF application that can configure the service. There are several ways to implement GUI/Service communication. Some of the more popular ones are WCF communication, database configuration or even INI files.
Hope this helps!

Related

Detect is when a windows service has been deleted

Is there a way to detect when a windows service has been deleted? I've checked the event log but it doesn't pick up deleted actions only added.
I believe there may be a way using audit logs but I'm unsure how to do this?
Any help is much appreciated.
Thanks
While there is no trace of service deletion in Event or Audit logs, what you can do is create a small console app that detects if a service exists and attach this app to Windows Task Scheduler such that it is scheduled to execute based on frequency or a Trigger that you can customize to your requirements such that you will receive an alert if a service has been added or removed etc..
The console app is designed such that on the first run, it logs all
the services on the system and on the subsequent runs it will be
tracking changes made on the services via servicesRemoved and
servicesAdded, with this we can decide what action to take when a
service has been modified
Console App: ServiceDetector.exe
static void Main(string[] args)
{
var path = #"C:\AdminLocation\ServicesLog.txt";
var currentServiceCollection = ServiceController.GetServices().Select(s => s.ServiceName).ToList(); //Queries the most current Services from the machine
if (!File.Exists(path)) //Creates a Log file with current services if not present, usually means the first run
{
// Assumption made is that this is the first run
using (var text = File.AppendText(path))
{
currentServiceCollection.ForEach((s) => text.WriteLine(s));
}
return;
}
// Fetches the recorded services from the Log
var existingServiceCollection = File.ReadAllLines(path).ToList();
var servicesRemoved = existingServiceCollection.Except(currentServiceCollection).ToList();
var servicesAdded = currentServiceCollection.Except(existingServiceCollection).ToList();
if (!servicesAdded.Any() && !servicesRemoved.Any())
{ Console.WriteLine("No services have been added or removed"); return; }
//If any services has been added
if (servicesAdded.Any())
{
Console.WriteLine("One or more services has been added");
using (var text = File.AppendText(path))
{
servicesAdded.ForEach((s) => text.WriteLine(s));
}
return;
}
//Service(s) may have been deleted, you can choose to record it or not based on your requirements
Console.WriteLine("One or more services has been removed");
}
Scheduling Task
Windows Start > Task Scheduler > Create Basic Task > Set Trigger > Attach your exe > Finish
You're right that deleting a Windows Service does cause an event to be added to the System Event Log (source: https://superuser.com/questions/1238311/how-can-we-detect-if-a-windows-service-is-deleted-is-there-an-event-log-id-for-i).
AFAIK there's no audit policy to audit the deletion of a service and I think if there were I think it would be listed here: https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/basic-audit-process-tracking
I assume polling ServiceController.GetServices() is out of the question because your program might not be running when the service is uninstalled?
There are lots of ways to build instrumentation, until you learn what constitutes good instrumentation. My how-to is essentially taken directly from the Wikipedia entry https://en.wikipedia.org/wiki/Instrumentation.
Instrumentation How-to
http://www.powersemantics.com/e.html
Non-integrated
Primary data only
Pull not push
Organized by process
Never offline
The solution to the problem of measuring indicators exists, but you're stuck conceptualizing how to also have "push-based" instrumentation signal another system. As my E article explains, instruments should always pull data never push it. Event-driven signalling is a potential point of failure you don't need.
To clear up any indecisiveness or doubts you may have about building a separate application, monitors are normally independent (non-integrated as Wikipedia says) processes. So saying your monitor "might not be running" means you have not chosen to build a real non-integrated monitor, one which is always on. Your consumer system doesn't correctly model instrumentation, because it integrates the check in its own process.
Separate these responsibilities and proceed. Decide how often the instrument should reasonably poll for deleted services and poll the data with a timer. If you use the API call simon-pearson suggested, you can also detect when services have been added. Of course, the monitor needs to locally cache a copy of the service list so that indicators can infer what's been added or removed.

How to call "Action Result" ASP.NET MVC at specific time (Daily)

I have a system for sending E-mails to users by a specific time .
built in ASP.NET MVC4 and has an action result "function" for checking the time of messages and send it if the day of the message is today .
how can I call this action result (daily) -like a scheduler- in efficient way ?
Thanks.
Whilst a separate service / application would be better, you could use wget.
GNU Wget is a free software package for retrieving files using HTTP,
HTTPS and FTP, the most widely-used Internet protocols. It is a
non-interactive commandline tool, so it may easily be called from
scripts, cron jobs, terminals without X-Windows support, etc.
You would then do something like:
"C:\Program Files (x86)\GnuWin32\bin\wget.exe" --no-check-certificate https://www.exammple.com/YouController/YourAction -O NUL
in a .bat file and set that to run via a windows Scheduled task at the time you require (assuming you don't need to run it less than every 60 seconds - if you do, let me know as I have another way around this using a windows service to call the bat file instead).
Omitting the -O NUL part would also save the output so you could see if everything ran successfully by doing:
public ActionResult YourAction()
{
//Do your code, get some stats that show it ran properly.
return Content("Return your stats here.");
}
from your controller action.
More efficient will be when you create new application as Windows Service. There u can easy set code to start at specific time. in this solution you will have more flexibility and independent. You can start hire : Windows Service to run a function at specified time
You could create a small console application that just calls the API do send out the emails. You can then schedule the console app to run at a specific time using the Windows Scheduler; you can even have it run without showing the console window. See here or here for details on how to schedule a task.
Use Azure Functions, that's exactly what it was built for. It's really good.
https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview

Starting an existing Mainframe job with FTP and C#

We have a lot of jobs(jcl) running on the mainframe.
I was asked to try and start a restore job. I have to do this with a C# application.
What i got now is i am able to connect to the mainframe with an ftp library and I can call raw FTP commands that the mainframe understands.
I kind of know how to submit a .jcl file, which will be processed as a job if I use the command "quote site filetype=jes".
My questions are:
- Is there a way to start an existing job?
- Does it matter what "directory"/partition(?) I have navigated to before submitting a job?
You could submit the below JCL through FTP and it would run the JCL in JOB.LIBRARY(JOB)
//JS010 EXEC PGM=IEBGENER
//SYSUT1 DD DSN=JOB.LIBRARY(JOB),DISP=SHR
//SYSUT2 DD SYSOUT=(,INTRDR)
//SYSPRINT DD SYSOUT=*
//SYSIN DD DUMMY
Expanding on Bills comments, is this a Production, Development, Test, QA etc job.
In production on mainframe's, jobs are normally run using a Scheduler (e.g. Ca7 or Workload Scheduler for z/OS (formerly OPC) + several others). Some sites also use Schedulers in QA / Development as well, but this is rare.
Submitting a job via a scheduler
To submit via a scheduler you MUST talk to the Operations / Production Control / Mainframe Support department. They should know what is possible and have preferred ways of doing something like this. They should also know what access is required !!!
Possible options would include:
Most schedulers have the option of submitting a job / schedule when a Dataset (File for non-mainframer's) is created. If available this will probably be the easiest to implement.
All schedulers provide programs that can submit schedules.
You may be able to run a job that submits the appropriate job
Run a program in the foreground to submit the appropriate job
These days most of the schedulers would have a Web interface, they may also have interfaces on other platform. This option is probably not going to be available though.
Submitting a job
If you are just going submit the job, options include:
Copying the job to the INTRDR as #Deuian has done (either foreground or background).
Running TSO background
Submitting via job (from Deuian's answer):
//JOBNAME JOB ...
//JS010 EXEC PGM=IEBGENER
//SYSUT1 DD DSN=JOB.LIBRARY(JOB),DISP=SHR
//SYSUT2 DD SYSOUT=(,INTRDR)
//SYSPRINT DD SYSOUT=*
//SYSIN DD DUMMY
Finally to do anything on the Mainframe, you will need the appropriate security access !!!
I have tried to provide a background information + a basic guide of the option available. Basically you need to talk to Mainframe-Operation / Mainframe-programmers !!!.
Yes, you can - just execute the RETR 'DATASET.NAME' FTP command. Remember that the quotes here are important - without quotes the command would be interpreted as "read spool files by JOBID". And with quotes it would be interpreted as "submit an existing JCL data set, wait for job to complete and retrieve it's spool". And it doesn't matter what directory you have navigated to before submitting a job.
You can refer to my Java implementation of JES client which works through FTP - https://github.com/vadimshchukin/jesclient. It has code which does exactly what you want:
public JESJob execute(String datasetName) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
retrieveFile(String.format("'%s'", datasetName), outputStream);
JESJob job = new JESJob(this);
job.setSpool(outputStream.toString());
return job;
}

how to start windows service on particular time

i want to start my windows service on every sunday 1.00 A.M.
can anyone help me in this
If it has to run on every sunday 1.00 AM then probably you need a simple program that is run by task scheduler on 1 AM Sunday.
It would be better if you use a timer that fires say every one hour and check what day and time it is. If it is sunday and 1 AM you can disable the timer and carry on with the work you want to do in the service. After the work is done then you should re-enable the timer.
One way could be to use SC command in a batch file which can be scheduled to run from windows standard scheduler.
For more information, see
SC /?
start and stop parameters in particular.
Since the logic should be done once in a week at a particular time use windows task scheduler for your purpose.
If you do not know how to perform this, Create a sample.vbs file, which calls your asp.net page/web service where you perform the logic. Then create a schedule in windows task scheduler to trigger your sample.vbs file.
Please see the steps to create the .vbs file that calls your asp.net page/web service
1.Open notepad and copy the following code in it and save
'Declare variables
Dim objRequest
Dim URL
Set objRequest = CreateObject("Microsoft.XMLHTTP")
'Put together the URL link appending the Variables.
URL = "http://computerName/VirtualDirectoryName/Logic.aspx"
'Open the HTTP request and pass the URL to the objRequest object
objRequest.open "POST", URL , false
'Send the HTML Request
objRequest.Send
'Set the object to nothing
Set objRequest = Nothing
2.Edit the URL="with your virtual directory path to the asp.net page/web service" and save.
3.change the extension from ".txt" to ".vbs" and save.
4.Create a new schedule in windows "Task Scheduler" and point the newly created sample.vbs file which will call the page where your logic is written (http://computerName/VirtualDirectoryName/Logic.aspx) and edit the settings to run once in a week at a particular time.
The way I do it is like this:
First you install your windows service on your Windows Server.
Second, you make a batch file. You just open Notepad, write the line beneath and save it as a .bat.
net start myService
Then you use the Task Scheduler available in Windows Server.
Creating the task is easy, you just need to add a trigger event (every sunday) and an action (starting the batch file you've just created).
I'm not saying it is the best way, but it is a way that will work.

How to implement filesystem watcher?

I am having a situation like:
Suppose there is one folder "D:\Main" which can contain any word file. On adding any file/files to the folder I need to parse the file and based on some keywords I need to transfer the file to some other sub folders as well as some entry to the database also.
I know something about FileSystemWatcher. If there would have been a button like "Check and Move" then I know that on the button click event I can do something but how to do it automatically. I mean if I add file to the folder manually also it should do the same(files may be uploaded via web as well as manually).I am currently working in web application with asp.net and c# and I have a little knowledge about windows application. Can any one suggest me how to proceed with this? Thanks.
You will need to create either a windows app or a windows service app. The FileSystemWatch won't survive on a web application. The reason is because web application functions by following the steps:
the webserver thread loads the application
your application starts the watcher and then finally output the web response.
After some idle time, the thread terminates the application, and thus your watcher.
When you have your windows app, you can add the CanRaiseEvents = true and w.Created += new System.IO.FileSystemEventHandler(w_Created); to your watcher. Do your processing in
void w_Created(object sender, System.IO.FileSystemEventArgs e)
{
// here
}
I just happened to be researching something very similar.
But you answered your own question. FileSystemWatcher is likely what you want.
Lower level Win32 APIs information is here:
Obtaining Directory Change Notifications
and here:
FindFirstChangeNotification

Categories

Resources