1- // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
2- // If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
3- // Copyright (C) OpenHardwareMonitor and Contributors.
4- // Partial Copyright (C) Michael Möller <mmoeller@openhardwaremonitor.org> and Contributors.
5- // All Rights Reserved.
6-
7- using System ;
1+ using System ;
82using System . IO ;
9- using System . Linq ;
3+ using System . Runtime . InteropServices ;
104using System . Security ;
115using System . Security . Principal ;
126using System . Windows . Forms ;
137using Microsoft . Win32 ;
14- using Microsoft . Win32 . TaskScheduler ;
15- using Action = Microsoft . Win32 . TaskScheduler . Action ;
16-
17- namespace OpenHardwareMonitor . UI ;
188
19- public class StartupManager
9+ namespace OpenHardwareMonitor . UI
2010{
21- private const string RegistryPath = @"Software\Microsoft\Windows\CurrentVersion\Run" ;
22- private bool _startup ;
23-
24- public StartupManager ( )
11+ public class StartupManager
2512 {
26- if ( Environment . OSVersion . Platform >= PlatformID . Unix )
27- {
28- IsAvailable = false ;
29- return ;
30- }
3113
32- if ( IsAdministrator ( ) && TaskService . Instance . Connected )
33- {
34- IsAvailable = true ;
14+ private readonly TaskSchedulerClass _scheduler ;
15+ private bool _startup ;
16+ private const string REGISTRY_RUN = @"Software\Microsoft\Windows\CurrentVersion\Run" ;
3517
36- Task task = GetTask ( ) ;
37- if ( task != null )
38- {
39- foreach ( Action action in task . Definition . Actions )
40- {
41- if ( action . ActionType == TaskActionType . Execute && action is ExecAction execAction )
42- {
43- if ( execAction . Path . Equals ( Application . ExecutablePath , StringComparison . OrdinalIgnoreCase ) )
44- _startup = true ;
45- }
46- }
47- }
48- }
49- else
18+ private bool IsAdministrator ( )
5019 {
5120 try
5221 {
53- using ( RegistryKey registryKey = Registry . CurrentUser . OpenSubKey ( RegistryPath ) )
54- {
55- string value = ( string ) registryKey ? . GetValue ( nameof ( OpenHardwareMonitor ) ) ;
56-
57- if ( value != null )
58- _startup = value == Application . ExecutablePath ;
59- }
60-
61- IsAvailable = true ;
22+ WindowsIdentity identity = WindowsIdentity . GetCurrent ( ) ;
23+ WindowsPrincipal principal = new ( identity ) ;
24+ return principal . IsInRole ( WindowsBuiltInRole . Administrator ) ;
6225 }
63- catch ( SecurityException )
26+ catch
6427 {
65- IsAvailable = false ;
28+ return false ;
6629 }
6730 }
68- }
69-
70- public bool IsAvailable { get ; }
7131
72- public bool Startup
73- {
74- get { return _startup ; }
75- set
32+ public StartupManager ( )
7633 {
77- if ( _startup != value )
34+ if ( Software . OperatingSystem . IsUnix )
7835 {
79- if ( IsAvailable )
36+ _scheduler = null ;
37+ IsAvailable = false ;
38+ return ;
39+ }
40+
41+ if ( IsAdministrator ( ) )
42+ {
43+ try
8044 {
81- if ( TaskService . Instance . Connected )
82- {
83- if ( value )
84- CreateTask ( ) ;
85- else
86- DeleteTask ( ) ;
45+ _scheduler = new TaskSchedulerClass ( ) ;
46+ _scheduler . Connect ( null , null , null , null ) ;
47+ }
48+ catch
49+ {
50+ _scheduler = null ;
51+ }
8752
88- _startup = value ;
89- }
90- else
53+ if ( _scheduler != null )
54+ {
55+ try
9156 {
9257 try
9358 {
94- if ( value )
95- CreateRegistryKey ( ) ;
96- else
97- DeleteRegistryKey ( ) ;
98-
99- _startup = value ;
59+ // check if the taskscheduler is running
60+ IRunningTaskCollection collection = _scheduler . GetRunningTasks ( 0 ) ;
10061 }
101- catch ( UnauthorizedAccessException )
62+ catch ( ArgumentException ) { }
63+
64+ ITaskFolder folder = _scheduler . GetFolder ( "\\ Open Hardware Monitor" ) ;
65+ IRegisteredTask task = folder . GetTask ( "Startup" ) ;
66+ _startup = ( task != null ) &&
67+ ( task . Definition . Triggers . Count > 0 ) &&
68+ ( task . Definition . Triggers [ 1 ] . Type ==
69+ TASK_TRIGGER_TYPE2 . TASK_TRIGGER_LOGON ) &&
70+ ( task . Definition . Actions . Count > 0 ) &&
71+ ( task . Definition . Actions [ 1 ] . Type ==
72+ TASK_ACTION_TYPE . TASK_ACTION_EXEC ) &&
73+ ( task . Definition . Actions [ 1 ] as IExecAction != null ) &&
74+ ( ( task . Definition . Actions [ 1 ] as IExecAction ) . Path ==
75+ Application . ExecutablePath ) ;
76+
77+ }
78+ catch ( IOException )
79+ {
80+ _startup = false ;
81+ }
82+ catch ( UnauthorizedAccessException )
83+ {
84+ _scheduler = null ;
85+ }
86+ catch ( COMException )
87+ {
88+ _scheduler = null ;
89+ }
90+ catch ( NotImplementedException )
91+ {
92+ _scheduler = null ;
93+ }
94+ }
95+ }
96+ else
97+ {
98+ _scheduler = null ;
99+ }
100+
101+ if ( _scheduler == null )
102+ {
103+ try
104+ {
105+ using ( RegistryKey key =
106+ Registry . CurrentUser . OpenSubKey ( REGISTRY_RUN ) )
107+ {
108+ _startup = false ;
109+ if ( key != null )
102110 {
103- throw new InvalidOperationException ( ) ;
111+ string value = ( string ) key . GetValue ( "OpenHardwareMonitor" ) ;
112+ if ( value != null )
113+ _startup = value == Application . ExecutablePath ;
104114 }
105115 }
116+ IsAvailable = true ;
106117 }
107- else
118+ catch ( SecurityException )
108119 {
109- throw new InvalidOperationException ( ) ;
120+ IsAvailable = false ;
110121 }
111122 }
123+ else
124+ {
125+ IsAvailable = true ;
126+ }
112127 }
113- }
114128
115- private static bool IsAdministrator ( )
116- {
117- try
129+ private void CreateSchedulerTask ( )
118130 {
119- WindowsIdentity identity = WindowsIdentity . GetCurrent ( ) ;
120- WindowsPrincipal principal = new WindowsPrincipal ( identity ) ;
121-
122- return principal . IsInRole ( WindowsBuiltInRole . Administrator ) ;
131+ ITaskDefinition definition = _scheduler . NewTask ( 0 ) ;
132+ definition . RegistrationInfo . Description =
133+ "This task starts the Open Hardware Monitor on Windows startup." ;
134+ definition . Principal . RunLevel =
135+ TASK_RUNLEVEL . TASK_RUNLEVEL_HIGHEST ;
136+ definition . Settings . DisallowStartIfOnBatteries = false ;
137+ definition . Settings . StopIfGoingOnBatteries = false ;
138+ definition . Settings . ExecutionTimeLimit = "PT0S" ;
139+ _ = ( ILogonTrigger ) definition . Triggers . Create ( TASK_TRIGGER_TYPE2 . TASK_TRIGGER_LOGON ) ;
140+ IExecAction action = ( IExecAction ) definition . Actions . Create ( TASK_ACTION_TYPE . TASK_ACTION_EXEC ) ;
141+ action . Path = Application . ExecutablePath ;
142+ action . WorkingDirectory =
143+ Path . GetDirectoryName ( Application . ExecutablePath ) ;
144+
145+ ITaskFolder root = _scheduler . GetFolder ( "\\ " ) ;
146+ ITaskFolder folder ;
147+ try
148+ {
149+ folder = root . GetFolder ( "Open Hardware Monitor" ) ;
150+ }
151+ catch ( IOException )
152+ {
153+ folder = root . CreateFolder ( "Open Hardware Monitor" , "" ) ;
154+ }
155+ folder . RegisterTaskDefinition ( "Startup" , definition ,
156+ ( int ) TASK_CREATION . TASK_CREATE_OR_UPDATE , null , null ,
157+ TASK_LOGON_TYPE . TASK_LOGON_INTERACTIVE_TOKEN , "" ) ;
123158 }
124- catch
159+
160+ private void DeleteSchedulerTask ( )
125161 {
126- return false ;
162+ ITaskFolder root = _scheduler . GetFolder ( "\\ " ) ;
163+ try
164+ {
165+ ITaskFolder folder = root . GetFolder ( "Open Hardware Monitor" ) ;
166+ folder . DeleteTask ( "Startup" , 0 ) ;
167+ }
168+ catch ( IOException ) { }
169+ try
170+ {
171+ root . DeleteFolder ( "Open Hardware Monitor" , 0 ) ;
172+ }
173+ catch ( IOException ) { }
127174 }
128- }
129175
130- private static Task GetTask ( )
131- {
132- try
176+ private void CreateRegistryRun ( )
133177 {
134- return TaskService . Instance . AllTasks . FirstOrDefault ( x => x . Name . Equals ( nameof ( OpenHardwareMonitor ) , StringComparison . OrdinalIgnoreCase ) ) ;
178+ RegistryKey key = Registry . CurrentUser . CreateSubKey ( REGISTRY_RUN ) ;
179+ key . SetValue ( "OpenHardwareMonitor" , Application . ExecutablePath ) ;
135180 }
136- catch
181+
182+ private void DeleteRegistryRun ( )
137183 {
138- return null ;
184+ RegistryKey key = Registry . CurrentUser . CreateSubKey ( REGISTRY_RUN ) ;
185+ key . DeleteValue ( "OpenHardwareMonitor" ) ;
139186 }
140- }
141-
142- private void CreateTask ( )
143- {
144- TaskDefinition taskDefinition = TaskService . Instance . NewTask ( ) ;
145- taskDefinition . RegistrationInfo . Description = "Starts OpenHardwareMonitor on Windows startup." ;
146-
147- taskDefinition . Triggers . Add ( new LogonTrigger ( ) ) ;
148-
149- taskDefinition . Settings . StartWhenAvailable = true ;
150- taskDefinition . Settings . DisallowStartIfOnBatteries = false ;
151- taskDefinition . Settings . StopIfGoingOnBatteries = false ;
152- taskDefinition . Settings . ExecutionTimeLimit = TimeSpan . Zero ;
153- taskDefinition . Settings . AllowHardTerminate = false ;
154-
155- taskDefinition . Principal . RunLevel = TaskRunLevel . Highest ;
156- taskDefinition . Principal . LogonType = TaskLogonType . InteractiveToken ;
157-
158- taskDefinition . Actions . Add ( new ExecAction ( Application . ExecutablePath , "" , Path . GetDirectoryName ( Application . ExecutablePath ) ) ) ;
159-
160- TaskService . Instance . RootFolder . RegisterTaskDefinition ( nameof ( OpenHardwareMonitor ) , taskDefinition ) ;
161- }
162187
163- private static void DeleteTask ( )
164- {
165- Task task = GetTask ( ) ;
166- task ? . Folder . DeleteTask ( task . Name , false ) ;
167- }
188+ public bool IsAvailable { get ; }
168189
169- private static void CreateRegistryKey ( )
170- {
171- RegistryKey registryKey = Registry . CurrentUser . CreateSubKey ( RegistryPath ) ;
172- registryKey ? . SetValue ( nameof ( OpenHardwareMonitor ) , Application . ExecutablePath ) ;
173- }
174-
175- private static void DeleteRegistryKey ( )
176- {
177- RegistryKey registryKey = Registry . CurrentUser . CreateSubKey ( RegistryPath ) ;
178- registryKey ? . DeleteValue ( nameof ( OpenHardwareMonitor ) ) ;
190+ public bool Startup
191+ {
192+ get
193+ {
194+ return _startup ;
195+ }
196+ set
197+ {
198+ if ( _startup != value )
199+ {
200+ if ( IsAvailable )
201+ {
202+ if ( _scheduler != null )
203+ {
204+ if ( value )
205+ CreateSchedulerTask ( ) ;
206+ else
207+ DeleteSchedulerTask ( ) ;
208+ _startup = value ;
209+ }
210+ else
211+ {
212+ try
213+ {
214+ if ( value )
215+ CreateRegistryRun ( ) ;
216+ else
217+ DeleteRegistryRun ( ) ;
218+ _startup = value ;
219+ }
220+ catch ( UnauthorizedAccessException )
221+ {
222+ throw new InvalidOperationException ( ) ;
223+ }
224+ }
225+ }
226+ else
227+ {
228+ throw new InvalidOperationException ( ) ;
229+ }
230+ }
231+ }
232+ }
179233 }
180- }
234+ }
0 commit comments