Мое приложение имеет несколько задач, которые нужно запускать в фоновом режиме. Я использую планировщик задач, чтобы запустить приложение, когда задача требуется, и приложение само закрывается, когда задача завершена. Пока все хорошо.
Задания могут занять некоторое время, поэтому я отправляю уведомления в центр действий в начале и в конце задания. Для первого у меня нет проблем, но во втором уведомлении я хочу открыть файл журнала, когда пользователь щелкает по нему.
Центр действий показывает оба уведомления, но файл журнала не открывается при нажатии на уведомление. Я думаю, это потому, что приложение уже закрыто.
Пока я пробовал следующее.
uses
System.SysUtils, System.Classes, System.Notification,
System.Generics.Collections;
type
TActionCenter = class(TDataModule)
NotificationCenter: TNotificationCenter;
procedure NotificationCenterReceiveLocalNotification(Sender: TObject;
ANotification: TNotification);
strict private
FNotifications: TDictionary<string, TOnReceiveLocalNotification>;
public
class procedure AppRegister(const ACompanyName: string);
procedure AfterConstruction; override;
procedure BeforeDestruction; override;
procedure SendNotification(const ATitle, AMessage: string); overload;
procedure SendNotification(const ATitle, AMessage: string; AOnClick: TOnReceiveLocalNotification); overload;
end;
var
_ActionCenter: TActionCenter;
...
uses
System.Hash, System.Win.Registry, Winapi.Windows;
procedure TActionCenter.AfterConstruction;
begin
inherited;
FNotifications := TDictionary<string, TOnReceiveLocalNotification>.Create;
end;
class procedure TActionCenter.AppRegister(const ACompanyName: string);
const
ActionCenterKey = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Notifications\Settings\';
var
ApplicationKey: string;
Registry: TRegistry;
begin
ApplicationKey := ACompanyName + '.DesktopToasts.' + THashBobJenkins.GetHashString(ParamStr(0));
Registry := TRegistry.Create;
try
Registry.RootKey := HKEY_CURRENT_USER;
if not Registry.KeyExists(ActionCenterKey + ApplicationKey) then
begin
Registry.Access := KEY_WRITE;
if Registry.OpenKey(ActionCenterKey + ApplicationKey, True) then
Registry.WriteInteger('ShowInActionCenter', 1);
end;
finally
Registry.Free;
end;
end;
procedure TActionCenter.BeforeDestruction;
begin
inherited;
FNotifications.Free;
end;
procedure TActionCenter.NotificationCenterReceiveLocalNotification(
Sender: TObject; ANotification: TNotification);
var
Pair: TPair<string, TOnReceiveLocalNotification>;
begin
Pair := FNotifications.ExtractPair(ANotification.Name);
if Assigned(Pair.Value) then
Pair.Value(Sender, ANotification);
end;
procedure TActionCenter.SendNotification(const ATitle, AMessage: string);
begin
SendNotification(ATitle, AMessage, nil);
end;
procedure TActionCenter.SendNotification(const ATitle, AMessage: string;
AOnClick: TOnReceiveLocalNotification);
var
Notification: TNotification;
begin
Notification := NotificationCenter.CreateNotification;
try
Notification.Name := TGUID.NewGuid.ToString;
Notification.Title := ATitle;
Notification.AlertBody := AMessage;
FNotifications.Add(Notification.Name, AOnClick);
NotificationCenter.PresentNotification(Notification);
finally
Notification.Free;
end;
end;
initialization
TActionCenter.AppRegister('MyCompanyName');
_ActionCenter := TActionCenter.Create(nil);
finalization
_ActionCenter.Free;
...
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
Vcl.StdCtrls, ActionCenter.Classes;
type
TMain = class(TForm)
Send: TButton;
procedure SendClick(Sender: TObject);
strict private
procedure NotificationClick1(ASender: TObject; ANotification: TNotification);
procedure NotificationClick2(ASender: TObject; ANotification: TNotification);
procedure NotificationClick3(ASender: TObject; ANotification: TNotification);
procedure OpenLog(FileName: TFileName);
end;
....
uses
Winapi.ShellAPI;
procedure TMain.NotificationClick1(ASender: TObject; ANotification: TNotification);
begin
OpenLog('C:\First.txt');
end;
procedure TMain.NotificationClick2(ASender: TObject; ANotification: TNotification);
begin
OpenLog('C:\Second.txt');
end;
procedure TMain.NotificationClick3(ASender: TObject; ANotification: TNotification);
begin
OpenLog('C:\Third.txt');
end;
procedure TMain.OpenLog(FileName: TFileName);
var
Handle: THandle;
begin
Handle := GetStdHandle(STD_INPUT_HANDLE);
ShellExecute(Handle, nil, PChar(FileName), nil, nil, SW_SHOWNORMAL);
end;
Есть ли способ сделать это? Есть ли событие OnReceiveLocalNotification, которое работает даже после закрытия приложения?