mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-22 07:37:40 +00:00
Merge pull request #3773 from keymanapp/fix/windows/3562-start-keyman-on-demand-tasks
fix(windows): Start Keyman on Demand - tasks
This commit is contained in:
commit
24fe11e6fe
12 changed files with 3199 additions and 3 deletions
|
|
@ -176,7 +176,9 @@ uses
|
|||
Keyman.System.SettingsManager in '..\..\global\delphi\general\Keyman.System.SettingsManager.pas',
|
||||
Keyman.Configuration.UI.UfrmSettingsManager in 'settings\Keyman.Configuration.UI.UfrmSettingsManager.pas' {frmSettingsManager},
|
||||
Keyman.Configuration.UI.UfrmSettingsAddTSFApp in 'settings\Keyman.Configuration.UI.UfrmSettingsAddTSFApp.pas' {frmSettingsAddTSFApp},
|
||||
Keyman.System.SettingsManagerFile in '..\..\global\delphi\general\Keyman.System.SettingsManagerFile.pas';
|
||||
Keyman.System.SettingsManagerFile in '..\..\global\delphi\general\Keyman.System.SettingsManagerFile.pas',
|
||||
Keyman.System.KeymanStartTask in 'util\Keyman.System.KeymanStartTask.pas',
|
||||
TaskScheduler_TLB in '..\..\global\delphi\winapi\TaskScheduler_TLB.pas';
|
||||
|
||||
{$R VERSION.RES}
|
||||
{$R manifest.res}
|
||||
|
|
|
|||
|
|
@ -336,6 +336,8 @@
|
|||
<FormType>dfm</FormType>
|
||||
</DCCReference>
|
||||
<DCCReference Include="..\..\global\delphi\general\Keyman.System.SettingsManagerFile.pas"/>
|
||||
<DCCReference Include="util\Keyman.System.KeymanStartTask.pas"/>
|
||||
<DCCReference Include="..\..\global\delphi\winapi\TaskScheduler_TLB.pas"/>
|
||||
<None Include="Profiling\AQtimeModule1.aqt"/>
|
||||
<BuildConfiguration Include="Debug">
|
||||
<Key>Cfg_2</Key>
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -113,6 +113,7 @@ uses
|
|||
Keyman.Configuration.System.TIPMaintenance,
|
||||
Keyman.Configuration.System.UImportOlderVersionKeyboards11To13,
|
||||
Keyman.Configuration.UI.UfrmSettingsManager,
|
||||
Keyman.System.KeymanStartTask,
|
||||
KeymanPaths,
|
||||
KLog,
|
||||
kmint,
|
||||
|
|
@ -373,7 +374,9 @@ begin
|
|||
|
||||
FMutex := nil; // I2720
|
||||
|
||||
{ Locate the appropriate product }
|
||||
{ Run app reconfiguration tasks }
|
||||
|
||||
TKeymanStartTask.RecreateTask;
|
||||
|
||||
UILanguages.CreateUILanguages;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,133 @@
|
|||
unit Keyman.System.KeymanStartTask;
|
||||
|
||||
interface
|
||||
|
||||
type
|
||||
/// <summary>Create or recreate the automatic task to start Keyman if a TIP
|
||||
/// is selected based on an event in the Event Log</summary>
|
||||
TKeymanStartTask = class
|
||||
private
|
||||
public
|
||||
class procedure RecreateTask;
|
||||
class procedure DeleteTask;
|
||||
class procedure CreateTask;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
System.Variants,
|
||||
Winapi.ActiveX,
|
||||
Winapi.Windows,
|
||||
|
||||
DebugPaths,
|
||||
KeymanPaths,
|
||||
KeymanVersion,
|
||||
RegistryKeys,
|
||||
TaskScheduler_TLB;
|
||||
|
||||
{ TKeymanStartTask }
|
||||
|
||||
const
|
||||
CTaskName = 'Start On Demand';
|
||||
CTaskDescription = 'Starts Keyman on demand when a Keyman input method is selected';
|
||||
CTaskAuthor = 'SIL International';
|
||||
CTaskFolderName = 'Keyman';
|
||||
CTaskTrigger =
|
||||
'<QueryList>'+
|
||||
'<Query Id="0" Path="Application">'+
|
||||
'<Select Path="Application">*[System[Provider[@Name=''Keyman''] and EventID=256]]</Select>'+
|
||||
'</Query>'+
|
||||
'</QueryList>';
|
||||
CTaskEventTriggerId = 'Keyman_StartOnDemand';
|
||||
|
||||
CKeymanExeStartArguments = '-kmc start';
|
||||
|
||||
class procedure TKeymanStartTask.CreateTask;
|
||||
var
|
||||
pService: ITaskService;
|
||||
pTaskFolder: ITaskFolder;
|
||||
pTask: ITaskDefinition;
|
||||
pRegInfo: IRegistrationInfo;
|
||||
pSettings: ITaskSettings;
|
||||
pEventTrigger: IEventTrigger;
|
||||
pAction: IExecAction;
|
||||
begin
|
||||
pService := CoTaskScheduler_.Create;
|
||||
pService.Connect(EmptyParam, EmptyParam, EmptyParam, EmptyParam);
|
||||
|
||||
// Create or open the Keyman task folder
|
||||
try
|
||||
pTaskFolder := pService.GetFolder('\' + CTaskFolderName);
|
||||
except
|
||||
pTaskFolder := pService.GetFolder('\').CreateFolder(CTaskFolderName, EmptyParam);
|
||||
end;
|
||||
|
||||
// Create a new task
|
||||
pTask := pService.NewTask(0);
|
||||
|
||||
pRegInfo := pTask.RegistrationInfo;
|
||||
pRegInfo.Author := CTaskAuthor;
|
||||
pRegInfo.Description := CTaskDescription;
|
||||
pRegInfo.Version := CKeymanVersionInfo.VersionWithTag;
|
||||
|
||||
pSettings := pTask.Settings;
|
||||
pSettings.DisallowStartIfOnBatteries := False;
|
||||
pSettings.StopIfGoingOnBatteries := False;
|
||||
pSettings.ExecutionTimeLimit := 'PT0S'; // no time limit
|
||||
pSettings.Priority := 4; // https://github.com/microsoft/WinDev/issues/55
|
||||
|
||||
// Start the task when Keyman event 256 is logged
|
||||
pEventTrigger := pTask.Triggers.Create(TASK_TRIGGER_EVENT) as IEventTrigger;
|
||||
pEventTrigger.Id := CTaskEventTriggerId;
|
||||
pEventTrigger.Subscription := CTaskTrigger;
|
||||
|
||||
// Action is to run keyman.exe as login user
|
||||
pAction := pTask.Actions.Create(TASK_ACTION_EXEC) as IExecAction;
|
||||
pAction.Path := TKeymanPaths.KeymanEngineInstallPath(TKeymanPaths.S_KeymanExe);
|
||||
pAction.Arguments := CKeymanExeStartArguments;
|
||||
|
||||
pTaskFolder.RegisterTaskDefinition(CTaskName, pTask, TASK_CREATE_OR_UPDATE or TASK_IGNORE_REGISTRATION_TRIGGERS,
|
||||
EmptyParam, EmptyParam, TASK_LOGON_NONE, EmptyParam);
|
||||
end;
|
||||
|
||||
class procedure TKeymanStartTask.DeleteTask;
|
||||
var
|
||||
pService: ITaskService;
|
||||
pTaskFolder: ITaskFolder;
|
||||
begin
|
||||
pService := CoTaskScheduler_.Create;
|
||||
pService.Connect(EmptyParam, EmptyParam, EmptyParam, EmptyParam);
|
||||
try
|
||||
pTaskFolder := pService.GetFolder('\'+CTaskFolderName);
|
||||
except
|
||||
// Assume that the folder doesn't exist, nothing to do
|
||||
Exit;
|
||||
end;
|
||||
|
||||
try
|
||||
pTaskFolder.DeleteTask(CTaskName, 0);
|
||||
except
|
||||
// We'll assume that the task doesn't exist, and continue
|
||||
end;
|
||||
|
||||
if pTaskFolder.GetTasks(0).Count = 0 then
|
||||
begin
|
||||
pTaskFolder := nil;
|
||||
pService.GetFolder('\').DeleteFolder(CTaskFolderName, 0);
|
||||
end;
|
||||
end;
|
||||
|
||||
class procedure TKeymanStartTask.RecreateTask;
|
||||
begin
|
||||
if not Reg_GetDebugFlag(SRegValue_Flag_UseAutoStartTask, True) then
|
||||
begin
|
||||
DeleteTask;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
CreateTask;
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
|
@ -95,7 +95,7 @@ const
|
|||
ValueType: kstInteger
|
||||
);
|
||||
|
||||
BaseKeymanSettings: array[0..31] of TKeymanSettingBase = (
|
||||
BaseKeymanSettings: array[0..32] of TKeymanSettingBase = (
|
||||
|
||||
// TIKE:UTikeDebugMode.TikeDebugMode
|
||||
(
|
||||
|
|
@ -409,6 +409,20 @@ const
|
|||
ValueType: kstInteger
|
||||
),
|
||||
|
||||
// kmshell:Keyman.System.KeymanStartTask
|
||||
(
|
||||
ID: 'engine.compatibility.use_autostart_task';
|
||||
Name: SRegValue_Flag_UseAutoStartTask;
|
||||
RootKey: HKCU;
|
||||
Key: SRegKey_KeymanEngineDebug_CU;
|
||||
Description: 'Set to 0 to disable the autostart task that starts '+
|
||||
'Keyman when a Keyman TIP is selected. After making this '+
|
||||
'change, you will need to open Keyman Configuration once '+
|
||||
'for it to take effect.';
|
||||
DefaultInt: 1;
|
||||
ValueType: kstInteger
|
||||
),
|
||||
|
||||
//
|
||||
// engine.diagnostics
|
||||
//
|
||||
|
|
|
|||
|
|
@ -447,6 +447,8 @@ const
|
|||
|
||||
SRegValue_Flag_UseRegisterHotkey = 'Flag_UseRegisterHotkey';
|
||||
SRegValue_Flag_ShouldSerializeInput = 'Flag_ShouldSerializeInput';
|
||||
SRegValue_Flag_UseAutoStartTask = 'Flag_UseAutoStartTask';
|
||||
|
||||
// Fixed path names
|
||||
const
|
||||
// PF = CSIDL_PROGRAM_FILES
|
||||
|
|
|
|||
1962
windows/src/global/delphi/winapi/TaskScheduler_TLB.pas
generated
Normal file
1962
windows/src/global/delphi/winapi/TaskScheduler_TLB.pas
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,30 @@
|
|||
unit Keyman.System.Test.KeymanStartTaskTest;
|
||||
|
||||
interface
|
||||
|
||||
procedure Run;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
Winapi.ActiveX,
|
||||
Winapi.Windows,
|
||||
|
||||
Keyman.System.KeymanStartTask;
|
||||
|
||||
procedure Run;
|
||||
begin
|
||||
CoInitializeEx(nil, COINIT_APARTMENTTHREADED);
|
||||
try
|
||||
if ParamStr(1) = '-d' then
|
||||
TKeymanStartTask.DeleteTask
|
||||
else if ParamStr(1) = '-c' then
|
||||
TKeymanStartTask.CreateTask
|
||||
else
|
||||
TKeymanStartTask.Recreate;
|
||||
finally
|
||||
CoUninitialize;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
26
windows/src/test/test-starttask/test_starttask.dpr
Normal file
26
windows/src/test/test-starttask/test_starttask.dpr
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
program test_starttask;
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
{$R *.res}
|
||||
|
||||
uses
|
||||
System.SysUtils,
|
||||
Keyman.System.KeymanStartTask in '..\..\desktop\kmshell\util\Keyman.System.KeymanStartTask.pas',
|
||||
DebugPaths in '..\..\global\delphi\general\DebugPaths.pas',
|
||||
RegistryKeys in '..\..\global\delphi\general\RegistryKeys.pas',
|
||||
TaskScheduler_TLB in '..\..\global\delphi\winapi\TaskScheduler_TLB.pas',
|
||||
ErrorControlledRegistry in '..\..\global\delphi\vcl\ErrorControlledRegistry.pas',
|
||||
KeymanVersion in '..\..\global\delphi\general\KeymanVersion.pas',
|
||||
Keyman.System.Test.KeymanStartTaskTest in 'Keyman.System.Test.KeymanStartTaskTest.pas',
|
||||
KeymanPaths in '..\..\global\delphi\general\KeymanPaths.pas';
|
||||
|
||||
begin
|
||||
try
|
||||
Run;
|
||||
{ TODO -oUser -cConsole Main : Insert code here }
|
||||
except
|
||||
on E: Exception do
|
||||
Writeln(E.ClassName, ': ', E.Message);
|
||||
end;
|
||||
end.
|
||||
1022
windows/src/test/test-starttask/test_starttask.dproj
Normal file
1022
windows/src/test/test-starttask/test_starttask.dproj
Normal file
File diff suppressed because it is too large
Load diff
BIN
windows/src/test/test-starttask/test_starttask.res
Normal file
BIN
windows/src/test/test-starttask/test_starttask.res
Normal file
Binary file not shown.
Loading…
Add table
Reference in a new issue