Starting an existing Mainframe job with FTP and C# - 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;
}

Related

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

Calling website through Windows Service

Looking at creating a windows service that will run on an IIS Server. Said service will access an url (mysite.com/mailflow.ashx) every 5 minutes. This is done to get the mailflow going, which is done by accessing the mailflow.ashx file.
Is: https://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.aspx
what I'm looking for in my scenario or is there another class that will do the job?
Coming from a non-coding background but I want to do this on my own as a learning experience.
Small hints are more than enough.
Cheers!
Unless you really want to learn coding, I'd recommend simply creating a scheduled task in windows. Make it call the following js script (called wget in my case)
var WinHttpReq = new ActiveXObject("WinHttp.WinHttpRequest.5.1");
WinHttpReq.Open("GET", WScript.Arguments(0), /*async=*/false);
WinHttpReq.Send();
WScript.Echo(WinHttpReq.ResponseText);
and set the task to start the following program cscript with the following arguments /nologo C:\Path\To\wget.js http://my.url.com
There are plenty of ways to ping an remote url, so you may decide to use another option (perhaps simply launching then killing a browser) but coding a service really is overkill if this is the only task you need
Yes, the HttpWebRequest class is what you need.

Would like to execute a query once per day in ASP.NET MVC

I would like my ASP.NET MVC app to execute a query once per day. What is the recommended way to do this?
My first thought is to put a timer in Global.asax that goes off every 24 hours, then call my query from the Elapsed handler. Any pitfalls with doing it this way? Is there a better way?
Edit
Let me add a little detail to what I'm trying to do. I'd specifically like the query to execute at midnight every day. If a day is missed (say due to sever maintenance or upgrading the app), that wouldn't be a major issue.
Edit 2
Couple more details:
The query is actually an INSERT, not a SELECT. The purpose is to add a "renewal" record for any member that is due to renew his/her membership at the end of the month.
I'm using SQL Server Compact (it's a very small database).
Does it have to originate in the Web layer? Who'd be there to consume the HTML? Typically, periodic SQL queries are scheduled within the database. In case of MS SQL Server - via the SQL Agent job facility. SQL Server can even send e-mail.
RE: edit2: Should've told so right away. SQL Server Compact is not the same as SQL Server - for one, it does not have SQL Agent IIRC. Still, invoking the Web layer is an overkill. I'd use a Windows Scripting Host file (.js) in conjuction with Windows task scheduler. WSH files can connect to databases via ADO and do whatever they want - inserts, selects, anything.
To detect missed scheduled runs, introduce an extra table with a log of scheduled runs. Then on subsequent runs you can analyse the date of the last run and act accordingly.
Edit2: so no administrative access. You should really tell all those details in the question. In this case, I would go through the Web layer after all, but the scheduling would be on MY end - where I do have control. Have Task Scheduler run on your end and invoke an HTTP URL on the server. To invoke URLs, you can use something like the free CURL utility. Running IE in scheduled manner has the disadvantage of leaving the window open.
IIS is not a scheduling engine.
Edit3 re:comment: sorry, I've misunderstood the nature of your setup. My own experiences have clouded my judgement :) Can you just run a check during every logon operation, and if it's been a while since the last maintenance operation, run it right then and there? How long does the maintenance take? If it's ~1min+, makes sense to run it in a worker thread, so that the logging-on user is not made wait.
Scheduling daily maintenance is a good idea in general, and it is implemented fairly often, but it seems you simply don't have the capability.
I do this very thing in my web apps, but use Asynchronous HTTP Handlers (http://msdn.microsoft.com/en-us/library/ms227433.aspx#Y512); I believe this would be recommended. I just start it off on application start and shut it down on application end (Global.asx).
The thing to remember is that you'll probably have to store the last time the query ran in the database because you'll loose track of that when your application pool recycles.
I'm doing this by putting some fake information in "Cache" and put the time period i want then handel the "_onCacheRemove" event do whatever i wanna do then recreate the "CacheItem" again:
e.g.
I put my tasks in Enum with the time that i wanna to rerun this task in seconds:
public enum ScheduledTasks
{
CleanGameRequests = 120,
CleanUpOnlineUsers = 6
}
then deal with them at "Application_Start" :
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
// Adding the tasks i want at App_Start
// so if the application restarted my task will refreshed.
AddTask(ScheduledTasks.CleanGameRequests);
AddTask(ScheduledTasks.CleanUpOnlineUsers);
}
// event to handel
private static CacheItemRemovedCallback _onCacheRemove;
private void AddTask(ScheduledTasks task)
{
_onCacheRemove = new CacheItemRemovedCallback(CacheItemRemoved);
HttpRuntime.Cache.Insert(task.ToString(), (int)task, null,
DateTime.Now.AddSeconds((int)task), Cache.NoSlidingExpiration,
CacheItemPriority.NotRemovable, _onCacheRemove);
}
public void CacheItemRemoved(string key, object time, CacheItemRemovedReason r)
{
var task = (ScheduledTasks)Enum.Parse(typeof(ScheduledTasks), key);
switch (task)
{
case ScheduledTasks.CleanGameRequests:
// Do the concept that you wanna to do.
GameRequest.CleanUp();
break;
case ScheduledTasks.CleanUpOnlineUsers:
OnlineUsers.CleanUp();
break;
default:
break;
}
// Don't forget to recreate the "CacheItem" again.
AddTask(task);
}
Note: You may make your time management as you want. In my case i
wanna these tasks to run every period
of time regardless of what time it is.
In your case you should check the time
before then recreate the CacheItem
again.
Hope this helped :)
Unless you have very active site chances are that IIS will bring your application down and there will be no process to execute your task.
Alternatives:
just do that during/immediately after request that is close enough by time
have external task that will trigger the operation on your site via GET/POST.
reconfigure IIS to never recycle/stop your app pool. Than your timer has chance to execute.
use some external service on the server to schedule the task ("at" or even SQL tasks).

Set service dependencies after install

I have an application that runs as a Windows service. It stores various things settings in a database that are looked up when the service starts. I built the service to support various types of databases (SQL Server, Oracle, MySQL, etc). Often times end users choose to configure the software to use SQL Server (they can simply modify a config file with the connection string and restart the service). The problem is that when their machine boots up, often times SQL Server is started after my service so my service errors out on start up because it can't connect to the database. I know that I can specify dependencies for my service to help guide the Windows service manager to start the appropriate services before mine. However, I don't know what services to depend upon at install time (when my service is registered) since the user can change databases later on.
So my question is: is there a way for the user to manually indicate the service dependencies based on the database that they are using? If not, what is the proper design approach that I should be taking? I've thought about trying to do something like wait 30 seconds after my service starts up before connecting to the database but this seems really flaky for various reasons. I've also considered trying to "lazily" connect to the database; the problem is that I need a connection immediately upon start up since the database contains various pieces of vital info that my service needs when it first starts. Any ideas?
Dennis
what your looking for is SC.exe. This is a command line tool that users can use to configure services.
sc [Servername] Command Servicename [Optionname= Optionvalue...]
more specificly you would want to use
sc [ServerName] config ServiceName depend=servicetoDependOn
Here is a link on the commandlike options for SC.EXE
http://msdn.microsoft.com/en-us/library/ms810435.aspx
A possible (far from ideal) code solution:
In you startup method code it as a loop that terminates when you've got a connection. Then in that loop trap any database connection errors and keep retrying as the following pseudo code illustrates:
bool connected = false;
while (!connected)
{
try
{
connected = openDatabase(...);
}
catch (connection error)
{
// It might be worth waiting for some time here
}
}
This means that your program doesn't continue until it has a connection. However, it could also mean that your program never gets out of this loop, so you'd need some way of terminating it - either manually or after a certain number of tries.
As you need your service to start in a reasonable time, this code can't go in the main initialisation. You have to arrange for your program to "start" successfully, but not do any processing until this method had returned connected = true. You might achieve this by putting this code in a thread and then starting your actual application code on the "thread completed" event.
Not a direct answer put some points you can look into
Windows service can be started Automatically with a delay. You can check this question in SO for some information about it.
How to make Windows Service start as “Automatic (Delayed Start)”
Check this post How to: Code Service Dependencies

Schedule a job in hosted web server

Can some one give me a best way to implement a daily job with .NET technology.
I have an asp.net application with the sqlserver database hosted in shared hosting, GODaddy in my instance.
My application is used to add / change the data in the database which is performing quite fairly at this time.
I got a new requirement to send some email alerts daily based on some data criteria that were stored in the database.
Initially I thought to write a windows service, but godaddy is not allowing to access the database other than its hosted applications.
Does someone has any idea to send alerts daily at 1:00AM?
Thanks in advance
See Easy Background Tasks in ASP.NET by Jeff Atwood.
Copy/paste from the link:
private static CacheItemRemovedCallback OnCacheRemove = null;
protected void Application_Start(object sender, EventArgs e)
{
AddTask("DoStuff", 60);
}
private void AddTask(string name, int seconds)
{
OnCacheRemove = new CacheItemRemovedCallback(CacheItemRemoved);
HttpRuntime.Cache.Insert(name, seconds, null,
DateTime.Now.AddSeconds(seconds), Cache.NoSlidingExpiration,
CacheItemPriority.NotRemovable, OnCacheRemove);
}
public void CacheItemRemoved(string k, object v, CacheItemRemovedReason r)
{
// do stuff here if it matches our taskname, like WebRequest
// re-add our task so it recurs
AddTask(k, Convert.ToInt32(v));
}
I haven't used GoDaddy for anything other than domain registration, so I have no experience with what you can or cannot do on their hosting platform. I also don't know what their support or knowledge base is like, but I'd say your best option is to ask GoDaddy what they recommend. Otherwise, you might keep implementing something that's technically feasible, but is blocked by the hosting company.
If it's not something that's a prime-time application, one quick and dirty thing to do is to have some kind of external bot calling a (secure) web page on the server that fires off the notification process. Not a real solution, but if this site is just a hobby of yours, it could get you by until you find something the host will allow.
Might also be a good time to find a new host, if this one is not meeting your requirements. There are lots of good ASP.NET hosts available these days.
You can use windows scheduler from the web server to schedule a stored procedure call that can send mail based on particular criteria.
osql.exe -S servername -d database -U username -P password -Q "EXEC spAlertOnCriteria"
References:
osql
Task Scheduler
Many hosting providers can request a URL for you every X minutes. I don't know if GoDaddy does, but if so, you could create an ASMX page that kicks off the job, and tell them to execute it automatically.
If they don't, one solution might be to fire off the job in a background thread at every page request. If you do that, make sure you put in code that limits it to running every X minutes or more (perhaps using a static variable or a database table) - read this story
If you can expose a service on the website hosting the application and database -- authenticated service, of course -- then you can hit that service remotely from any box with credentials, pull down the data, and send the mail that way.
This could be an automated process written as a Windows service, an application that is run under the Scheduler, or some button you push at 1:00 AM. Your pick.
Just because the app is the only thing that can access the database doesn't mean you can't expose the data in other ways.
Use either System.Timers, System.Threading to create a instance that is run at a predetermined time. Have that thread execute whatever the task is that you want... Make sure the code is thread safe!

Categories

Resources