如何在C#中监视SQL Server代理作业信息

我需要创建一个应用程序来监视SQL Server 2000代理作业状态和信息,当作业发生时与Windows应用程序事件日志中显示相同。 现在我已经通过连接字符串连接到数据库,但我不知道如何从Job获取状态和信息。

我需要在Textbox上显示状态和信息。

您有什么建议怎么办?

开发者工具 :

  1. MS SQL Sever 2000 SP4
  2. MS Visual Studio 2008(C#)

我是菜鸟程序员。

我已经可以做到了……

我在数据库“msdb”中选择表格“Sysjobserver”,以获取我想要的阅读状态,日期,时间。

使用此代码

public void GetJobsAndStatus() { string sqlJobQuery = "select j.job_id, j.name, j.enabled, jh.run_status," + " js.last_outcome_message, jh.run_date, jh.step_name, jh.run_time" + " from sysjobs j left join sysjobhistory jh on (j.job_id = jh.job_id)" + " left join sysjobservers js on (j.job_id = js.job_id)" + " where jh.run_date = (select Max(run_date) from sysjobhistory)" + " and jh.run_time = (select Max(run_time) from sysjobhistory)"; // create SQL connection and set up SQL Command for query using (SqlConnection _con = new SqlConnection("server=10.15.13.70;database=msdb;user id=sa;pwd=")) using (SqlCommand _cmd = new SqlCommand(sqlJobQuery, _con)) { try { // open connection _con.Open(); SqlConnection.ClearPool(_con); // create SQL Data Reader and grab data using (SqlDataReader rdr = _cmd.ExecuteReader()) { // as long as we get information from the reader while (rdr.Read()) { Guid jobID = rdr.GetGuid(0); // read Job_id string jobName = rdr.GetString(1); // read Job name byte jobEnabled = rdr.GetByte(2); // read Job enabled flag int jobStatus = rdr.GetInt32(3); // read last_run_outcome from sysjobserver string jobMessage = rdr.GetString(4); // read Message from sysjobserver int jobRunDate = rdr.GetInt32(5); // read run_date from sysjobhistory string jobStepName = rdr.GetString(6); // read StepName from sysjobhistory int jobRunTime = rdr.GetInt32(7); // read run_time from sysjobhistory String[] lviData = new String[] // ตัวแปรอะเรย์ชื่อ lviData { jobID.ToString(), jobName.ToString(), jobStepName.ToString(), jobMessage.ToString(), jobStatus.ToString(), jobRunDate.ToString(), jobRunTime.ToString(), //jobEnabled.ToString(), }; newData = lviData; DisplayList(); // for display data on datagridview } rdr.Close(); } } 

谢谢大家的帮助。 😀

查询的SQL存储过程不会为您提供任何系统数据,除非您在msdb系统数据库上具有db_owner权限,至少在SQL Server 2008中。因此,所提到的方法通常不适用于您要显示或管理作业的应用程序。 但是,SMO命名空间为您提供了许多SQL Server管理function的托管代码解决方案,包括SQL Server代理函数,这些函数只需要您通常可以为应用程序用户排序的SQLServerAgent *权限。 这里给出了使用SMO类来处理作业的一个很好的介绍:

http://www.codeproject.com/Tips/367470/Manage-SQL-Server-Agent-Jobs-using-Csharp

我现在正在处理类似的任务,虽然SQL查询让我拒绝访问,使用C#代码和Microsoft.SqlServer.Management.Smo.Agent命名空间我刚刚列出了使用此代码的所有作业:

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.SqlServer.Management.Smo; using Microsoft.SqlServer.Management.Common; using Microsoft.SqlServer.Management.Smo.Agent; namespace SmoTest { class Program { static readonly string SqlServer = @"SQL01\SQL01"; static void Main(string[] args) { ServerConnection conn = new ServerConnection(SqlServer); Server server = new Server(conn); JobCollection jobs = server.JobServer.Jobs; foreach (Job job in jobs) { Console.WriteLine(job.Name); } } } } 

这应该是一个很好的起点,了解如何使用T-SQL查找SQL代理作业:

使用TSQL查看(和禁用)SQL代理作业

该脚本将列出数据库中的所有作业,以及下次运行它们的时间等等。

使用job_name,您还应该能够使用服务器上msdb数据库中的SQL Server代理存储过程找到有关作业的详细信息。

SQL Server 2005及更高版本上 ,您可以使用系统存储过程msdb.dbo.sp_help_job来获取有关SQL Server代理作业的信息,包括状态。 您可以在http://msdn.microsoft.com/en-us/library/ms186722(v=SQL.90).aspx上阅读有关sp_help_job的更多信息。

以下是从C#执行此操作的示例代码。

 private Dictionary ExecutionStatusDictionary = new Dictionary() { {0, "Not idle or suspended"}, {1, "Executing"}, {2, "Waiting for thread"}, {3, "Between retries"}, {4, "Idle"}, {5, "Suspended"}, {7, "Performing completion actions"} }; public string GetStatus() { SqlConnection msdbConnection = new SqlConnection("Data Source=SERVERNAME;Initial Catalog=msdb;Integrated Security=SSPI"); System.Text.StringBuilder resultBuilder = new System.Text.StringBuilder(); try { msdbConnection.Open(); SqlCommand jobStatusCommand = msdbConnection.CreateCommand(); jobStatusCommand.CommandType = CommandType.StoredProcedure; jobStatusCommand.CommandText = "sp_help_job"; SqlParameter jobName = jobStatusCommand.Parameters.Add("@job_name", SqlDbType.VarChar); jobName.Direction = ParameterDirection.Input; jobName.Value = "LoadRegions"; SqlParameter jobAspect = jobStatusCommand.Parameters.Add("@job_aspect", SqlDbType.VarChar); jobAspect.Direction = ParameterDirection.Input; jobAspect.Value = "JOB"; SqlDataReader jobStatusReader = jobStatusCommand.ExecuteReader(); while (jobStatusReader.Read()) { resultBuilder.Append(string.Format("{0} {1}", jobStatusReader["name"].ToString(), ExecutionStatusDictionary[(int)jobStatusReader["current_execution_status"]] )); } jobStatusReader.Close(); } finally { msdbConnection.Close(); } return resultBuilder.ToString(); } 

您可以使用此SELECT获取所有服务器作业的列表:

 SELECT [name] FROM msdb.dbo.sysjobs 

如果您想获得当前正在运行的作业及其信息的列表,我建议您在应用程序调用的SQL中编写存储过程。 这里有一个很好的演示,你可以使用……

http://feodorgeorgiev.com/blog/2010/03/how-to-query-currently-running-sql-server-agent-jobs/

祝好运!

对于我的用例,我特别需要知道作业何时完成运行,以及它是否成功。 这是我的代码:

 using System; using System.Data; using System.Data.SqlClient; namespace LaunchJobAndWaitTillDone { class Program { const string connectionString = "Data Source=YOURSERVERNAMEHERE;Initial Catalog=msdb;Integrated Security=SSPI"; const string jobName = "YOURJOBNAMEHERE"; static readonly TimeSpan waitFor = TimeSpan.FromSeconds(1.0); enum JobExecutionResult { Succeeded, FailedToStart, FailedAfterStart, Unknown } static void Main(string[] args) { var instance = new Program(); JobExecutionResult jobResult = instance.RunJob(jobName); switch (jobResult) { case JobExecutionResult.Succeeded: Console.WriteLine($"SQL Server Agent job, '{jobName}', ran successfully to completion."); break; case JobExecutionResult.FailedToStart: Console.WriteLine($"SQL Server Agent job, '{jobName}', failed to start."); break; case JobExecutionResult.FailedAfterStart: Console.WriteLine($"SQL Server Agent job, '{jobName}', started successfully, but encountered an error."); break; default: Console.WriteLine($"Unknown result from attempting to run SQL Server Agent job, '{jobName}'."); break; } Console.ReadLine(); return; } JobExecutionResult RunJob(string jobName) { int jobResult; using (var jobConnection = new SqlConnection(connectionString)) { SqlCommand jobCommand; SqlParameter jobReturnValue; SqlParameter jobParameter; jobCommand = new SqlCommand("sp_start_job", jobConnection); jobCommand.CommandType = CommandType.StoredProcedure; jobReturnValue = new SqlParameter("@RETURN_VALUE", SqlDbType.Int); jobReturnValue.Direction = ParameterDirection.ReturnValue; jobCommand.Parameters.Add(jobReturnValue); jobParameter = new SqlParameter("@job_name", SqlDbType.VarChar); jobParameter.Direction = ParameterDirection.Input; jobCommand.Parameters.Add(jobParameter); jobParameter.Value = jobName; jobConnection.Open(); try { jobCommand.ExecuteNonQuery(); jobResult = (Int32)jobCommand.Parameters["@RETURN_VALUE"].Value; } catch (SqlException) { jobResult = -1; } } switch (jobResult) { case 0: break; default: return JobExecutionResult.FailedToStart; } while (true) { using (var jobConnection2 = new SqlConnection(connectionString)) { SqlCommand jobCommand2 = new SqlCommand("sp_help_jobactivity", jobConnection2); jobCommand2.CommandType = CommandType.StoredProcedure; SqlParameter jobReturnValue2 = new SqlParameter("@RETURN_VALUE", SqlDbType.Int); jobReturnValue2.Direction = ParameterDirection.ReturnValue; jobCommand2.Parameters.Add(jobReturnValue2); SqlParameter jobParameter2 = new SqlParameter("@job_name", SqlDbType.VarChar); jobParameter2.Direction = ParameterDirection.Input; jobCommand2.Parameters.Add(jobParameter2); jobParameter2.Value = jobName; jobConnection2.Open(); SqlDataReader rdr = jobCommand2.ExecuteReader(); while (rdr.Read()) { object msg = rdr["message"]; object run_status = rdr["run_status"]; if (!DBNull.Value.Equals(msg)) { var message = msg as string; var runStatus = run_status as Int32?; if (message != null && message.StartsWith("The job succeeded") && runStatus.HasValue && runStatus.Value == 1) { return JobExecutionResult.Succeeded; } else if (message != null && message.StartsWith("The job failed")) { return JobExecutionResult.FailedAfterStart; } else if (runStatus.HasValue && runStatus.Value == 1) { return JobExecutionResult.Unknown; } } } } System.Threading.Thread.Sleep(waitFor); } } } } 

请注意,您可能需要数据库/服务器所有者权限或此类代码才能使用此权限。