我需要创建一个应用程序来监视 SQL Server 2000 代理作业状态和作业发生时的信息,与 Windows 应用程序事件日志上的显示相同。现在我已经通过连接字符串连接到数据库,但我不知道如何从 Job 获取状态和信息。
我需要在文本框上显示状态和信息。
你有什么建议怎么做。
开发者工具 :
- MS SQL 服务器 2000 SP4
- 微软视觉工作室 2008 (C#)
我是一个菜鸟程序员。
我需要创建一个应用程序来监视 SQL Server 2000 代理作业状态和作业发生时的信息,与 Windows 应用程序事件日志上的显示相同。现在我已经通过连接字符串连接到数据库,但我不知道如何从 Job 获取状态和信息。
我需要在文本框上显示状态和信息。
你有什么建议怎么做。
开发者工具 :
我是一个菜鸟程序员。
我已经可以做到了……
我在数据库“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();
}
}
非常感谢大家的帮助。:-D
查询的 SQL 存储过程不会为您提供任何系统数据,除非您至少在 SQL Server 2008 中拥有 msdb 系统数据库的 db_owner 权限。因此,上述方法通常不适用于您想要显示或管理作业的应用程序。然而,SMO 命名空间为您提供了许多 SQL Server 管理功能的托管代码解决方案,包括仅需要 SQLServerAgent* 权限的 SQL Server 代理功能,您通常可以为您的应用程序用户进行排序。这里给出了使用 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 代理作业的良好起点:
该脚本将列出您在数据库中的所有作业,以及下一次运行它们的时间等等。
使用 job_name,您还应该能够使用服务器数据库中的SQL Server 代理存储过程msdb
找到有关您的作业的详细信息。
在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<int, string> ExecutionStatusDictionary = new Dictionary<int, string>()
{
{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);
}
}
}
}
请注意,您可能需要数据库/服务器所有者权限或类似的权限才能使此代码正常工作。