Member 12406065 Ответов: 3

Нужно вызвать отчет для нескольких клиентов в разное время в день/месяц/год


Мне нужно сгенерировать и отправить отчет клиентам в соответствии с их настройками на портале. У нас почти 30 клиентов, и каждый клиент имеет 20-25 отчетов. Клиенты имеют доступ к порталу и могут настроить время своего отчета на любой день/месяц/год.

Например, если клиент запланировал 5 отчетов:

report a ---> daily @ 10PM
report b ---> monthly once on date 02 @ 10AM
report c ---> yearly once on date 30/june @ 5PM
report d ---> daily @ 12PM
report e ---> monthly once on date 02 @ 10AM


точно так же все клиенты имеют право настраивать свои отчеты соответственно в пользовательском интерфейсе. Мы фиксируем все детали в базах данных.

у нас есть код, написанный с шаблоном, который преобразует datatable в pdf и отправляет pdf в качестве вложения в настроенное электронное письмо, написанное на C#.

Вопрос здесь в том, как я узнаю, в какое время и для какого клиента должен быть сгенерирован отчет. Мне нужен совет/идея, чтобы следовать приведенному выше вопросу, чтобы отправить отчет соответствующему клиенту.

Если один клиент, мы можем написать пакетную консоль и запустить эту консоль по расписанию заданий, но здесь у нас есть более 30 клиентов. Поэтому, пожалуйста, предложите мне некоторые идеи/технологии, которым я могу следовать и завершить эту работу без каких-либо проблем

Что я уже пробовал:

please suggest me some ideas/technology that I can follow and complete this work without any problem

3 Ответов

Рейтинг:
2

Garth J Lancaster

Я бы посмотрел на централизованную службу планирования - возможно, на основе C#, используя Topshelf для фреймворка службы, Quartz для запланированных действий на основе cron, выбрасывающих "сообщение" через RabbitMQ, где "messsage" - это клиент + задание + параметры

Затем несколько машин подписываются на сообщения RabbitMQ - возможно, с помощью клиента(ов) или какой - либо другой техники, позволяющей распространять работу, - и запускают соответствующее задание отчета, используя сведения в сообщении


Рейтинг:
2

RickZeeland

В дополнение к ответу Гарта вы также можете использовать планировщик задач Windows для создания и выполнения задач на удаленных компьютерах, см.: Schtasks.exe - Win32-приложений, Майкрософт документы[^]
Лично я предпочитаю называть планировщик задач Windows процессом.Start() поскольку я нахожу существующие библиотеки слишком сложными, а также думаю, что проблемы могут возникнуть, когда все изменится после обновления Windows.

Вот пример для локального использования:

private void CreateSchedulerTask(string scheduleTime)
{
	var command = Path.Combine(Environment.SystemDirectory, @"SchTasks");
	var args = "/Query";
	var result = Utilities.ProcessRun(command, args, true);

	if (result.Contains("MyTaskName"))
	{
		Debug.Print("MyTaskName already running.");
		return;
	}

	command = Path.Combine(Environment.SystemDirectory, @"SchTasks");
	args = "/Create /SC WEEKLY /D MON /TN \"MyTaskName\" /TR \"" + Application.ExecutablePath + "\" /ST " + scheduleTime;
	Debug.Print(command + "  " + args);
	result = Utilities.ProcessRun(command, args, false);
}

public static string ProcessRun(string fileName, string args, bool redirectStandardOutput, bool waitForExit = true, bool hideWindow = false)
{
	string result = string.Empty;
	const int ErrorCancelled = 1223;

	try
	{
		using (Process process = new Process())
		{
			process.StartInfo = new ProcessStartInfo();
			process.StartInfo.FileName = fileName;

			if (hideWindow)
			{
				process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
			}

			if (!string.IsNullOrEmpty(args))
			{
				process.StartInfo.Arguments = args;
			}

			process.StartInfo.CreateNoWindow = true;

			if (redirectStandardOutput)
			{
				process.StartInfo.RedirectStandardOutput = true;
				process.StartInfo.UseShellExecute = false;
				process.Start();

				using (StreamReader reader = process.StandardOutput)
				{
					string resultOut = reader.ReadToEnd();
					Debug.Print(resultOut);
				}
			}
			else
			{
				process.StartInfo.Verb = "runas";
				process.StartInfo.UseShellExecute = true;
				process.Start();
			}

			if (waitForExit)
			{
				// Timeout 2 minutes
				process.WaitForExit(120000);
			}
		}
	}
	catch (Win32Exception ex)
	{
		if (ex.NativeErrorCode == ErrorCancelled)
		{
			result = "ProcessRun() cancelled";
		}
		else
		{
			result = @"ProcessRun() error: " + ex.Message;
		}
	}
	catch (Exception ex)
	{
		result = @"ProcessRun() error: " + ex.Message;
	}

	return result;
}


Рейтинг:
2

Maciej Los

Для базы данных MS SQL Server:

Вы можете создать хранимую процедуру, как описано здесь: c# - создание заданий агента SQL Server программно - переполнение стека[^]

Всякий раз, когда клиент создает расписание, вы можете использовать такую процедуру для программного создания задания sql server.