source: branches/eraser6/Eraser/Program.cs @ 761

Revision 761, 26.1 KB checked in by lowjoel, 6 years ago (diff)

-Make sure CommandMain? always returns a value
-When a Win32Exception is caught, return the error code as the application exit code

  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 * Copyright 2008 The Eraser Project
4 * Original Author: Joel Low <lowjoel@users.sourceforge.net>
5 * Modified By:
6 *
7 * This file is part of Eraser.
8 *
9 * Eraser is free software: you can redistribute it and/or modify it under the
10 * terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option) any later
12 * version.
13 *
14 * Eraser is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 *
18 * A copy of the GNU General Public License can be found at
19 * <http://www.gnu.org/licenses/>.
20 */
21
22using System;
23using System.Collections.Generic;
24using System.Windows.Forms;
25
26using Eraser.Manager;
27using Eraser.Util;
28using Microsoft.Win32;
29using System.IO;
30using System.Runtime.Serialization.Formatters.Binary;
31using System.Globalization;
32using System.Reflection;
33using System.Diagnostics;
34using System.ComponentModel;
35
36namespace Eraser
37{
38    static class Program
39    {
40        /// <summary>
41        /// The main entry point for the application.
42        /// </summary>
43        [STAThread]
44        static int Main(string[] commandLine)
45        {
46            //Trivial case: no command parameters
47            if (commandLine.Length == 0)
48                GUIMain(false);
49
50            //Determine if the sole parameter is --restart; if it is, start the GUI
51            //passing isRestart as true. Otherwise, we're a console application.
52            else if (commandLine.Length == 1)
53            {
54                if (commandLine[0] == "/restart" || commandLine[0] == "--restart")
55                {
56                    GUIMain(true);
57                }
58                else
59                {
60                    return CommandMain(commandLine);
61                }
62            }
63
64            //The other trivial case: definitely a console application.
65            else
66                return CommandMain(commandLine);
67
68            //No error.
69            return 0;
70        }
71
72        /// <summary>
73        /// Runs Eraser as a command-line application.
74        /// </summary>
75        /// <param name="commandLine">The command line parameters passed to Eraser.</param>
76        private static int CommandMain(string[] commandLine)
77        {
78            //True if the user specified a quiet command.
79            bool isQuiet = false;
80
81            try
82            {
83                CommandLineProgram program = new CommandLineProgram(commandLine);
84                isQuiet = program.Arguments.Quiet;
85
86                using (ManagerLibrary library = new ManagerLibrary(new Settings()))
87                    program.Run();
88
89                return 0;
90            }
91            catch (Win32Exception e)
92            {
93                Console.WriteLine(e.Message);
94                return e.ErrorCode;
95            }
96            catch (Exception e)
97            {
98                Console.WriteLine(e.Message);
99                return 1;
100            }
101            finally
102            {
103                //Flush the buffered output to the console
104                Console.Out.Flush();
105
106                //Don't ask for a key to press if the user specified Quiet
107                if (!isQuiet)
108                {
109                    Console.Write("\nPress enter to continue . . . ");
110                    Console.Out.Flush();
111                    Console.ReadLine();
112                }
113
114                KernelAPI.FreeConsole();
115            }
116        }
117
118        /// <summary>
119        /// Runs Eraser as a GUI application.
120        /// </summary>
121        /// <param name="isRestart">True if the program was passed the --restart
122        /// switch.</param>
123        private static void GUIMain(bool isRestart)
124        {
125            Application.EnableVisualStyles();
126            Application.SetCompatibleTextRenderingDefault(false);
127            Application.SafeTopLevelCaptionFormat = S._("Eraser");
128
129            using (ManagerLibrary library = new ManagerLibrary(new Settings()))
130            using (eraserClient = new RemoteExecutorServer())
131            {
132                //Set our UI language
133                EraserSettings settings = new EraserSettings();
134                System.Threading.Thread.CurrentThread.CurrentUICulture =
135                    new CultureInfo(settings.Language);
136
137                //Load the task list
138                if (settings.TaskList != null)
139                    using (MemoryStream stream = new MemoryStream(settings.TaskList))
140                        try
141                        {
142                            eraserClient.LoadTaskList(stream);
143                        }
144                        catch (Exception)
145                        {
146                            settings.TaskList = null;
147                            MessageBox.Show(S._("Could not load task list. All task entries have " +
148                                "been lost."), S._("Eraser"), MessageBoxButtons.OK,
149                                MessageBoxIcon.Error);
150                        }
151
152                //Create the main form
153                MainForm form = new MainForm();
154
155                //Run tasks which are meant to be run on restart
156                if (isRestart)
157                {
158                    eraserClient.QueueRestartTasks();
159                }
160
161                //Run the program
162                eraserClient.Run();
163                Application.Run(form);
164
165                //Save the task list
166                using (MemoryStream stream = new MemoryStream())
167                {
168                    eraserClient.SaveTaskList(stream);
169                    settings.TaskList = stream.ToArray();
170                }
171            }
172        }
173
174        /// <summary>
175        /// The global Executor instance.
176        /// </summary>
177        public static Executor eraserClient;
178
179        /// <summary>
180        /// Handles commands passed to the program
181        /// </summary>
182        /// <param name="arguments">The arguments to the command</param>
183        private delegate void CommandHandler(Dictionary<string, string> arguments);
184    }
185
186    class CommandLineProgram
187    {
188        #region Command Line parsing classes
189        /// <summary>
190        /// Manages a command line.
191        /// </summary>
192        public class CommandLine
193        {
194            /// <summary>
195            /// Constructor.
196            /// </summary>
197            /// <param name="cmdParams">The raw arguments passed to the program.</param>
198            public CommandLine(string[] cmdParams)
199            {
200                //Get the action.
201                if (cmdParams.Length < 1)
202                    throw new ArgumentException("An action must be specified.");
203                Action = cmdParams[0];
204
205                //Iterate over each argument, resolving them ourselves and letting
206                //subclasses resolve them if we don't know how to.
207                for (int i = 1; i != cmdParams.Length; ++i)
208                {
209                    if (IsParam(cmdParams[i], "quiet", "q"))
210                        Quiet = true;
211                    else if (!ResolveParameter(cmdParams[i]))
212                        throw new ArgumentException("Unknown argument: " + cmdParams[i]);
213                }
214            }
215
216            /// <summary>
217            /// Called when a parameter is not used by the current CommandLine object
218            /// for subclasses to handle their parameters.
219            /// </summary>
220            /// <param name="param">The parameter to resolve.</param>
221            /// <returns>Return true if the parameter was resolved and accepted.</returns>
222            virtual protected bool ResolveParameter(string param)
223            {
224                return false;
225            }
226
227            /// <summary>
228            /// Checks if the given <paramref name="parameter"/> refers to the
229            /// <paramref name="expectedParameter"/>, regardless of whether it is specified
230            /// with -, --, or /
231            /// </summary>
232            /// <param name="parameter">The parameter on the command line.</param>
233            /// <param name="expectedParameter">The parameter the program is looking for, without
234            /// the - or / prefix.</param>
235            /// <param name="shortParameter">The short parameter when used with a single hyphen,
236            /// without the - or / prefix.</param>
237            /// <returns>True if the parameter references the given expected parameter.</returns>
238            protected static bool IsParam(string parameter, string expectedParameter,
239                string shortParameter)
240            {
241                //Trivial case
242                if (parameter.Length < 1)
243                    return false;
244
245                //Extract the bits before the equal sign.
246                {
247                    int equalPos = parameter.IndexOf('=');
248                    if (equalPos != -1)
249                        parameter = parameter.Substring(0, equalPos);
250                }
251
252                //Get the first letter.
253                switch (parameter[0])
254                {
255                    case '-':
256                        //Can be a - or a --. Check for the second parameter
257                        if (parameter.Length < 2)
258                            //Nothing specified at the end... it's invalid.
259                            return false;
260
261                        if (parameter[1] == '-')
262                            return parameter.Substring(2) == expectedParameter;
263                        else if (shortParameter == null || shortParameter == string.Empty)
264                            return parameter.Substring(1) == expectedParameter;
265                        else
266                            return parameter.Substring(1) == shortParameter;
267                       
268                    case '/':
269                        //The / can be used with both long and short parameters.
270                        parameter = parameter.Substring(1);
271                        return parameter == expectedParameter || (
272                            shortParameter != null && shortParameter != string.Empty &&
273                            parameter == shortParameter
274                        );
275
276                    default:
277                        return false;
278                }
279            }
280
281            /// <summary>
282            /// Gets the list of subparameters of the parameter. Subparameters are text
283            /// after the first =, separated by commas.
284            /// </summary>
285            /// <param name="param">The subparameter text to parse.</param>
286            /// <returns>The list of subparameters in the parameter.</returns>
287            protected static List<KeyValuePair<string, string>> GetSubParameters(string param)
288            {
289                List<KeyValuePair<string, string>> result =
290                    new List<KeyValuePair<string, string>>();
291                int lastPos = 0;
292                int commaPos = (param += ',').IndexOf(',');
293
294                while (commaPos != -1)
295                {
296                    //Extract the current subparameter, and dissect the subparameter at
297                    //the first =.
298                    string subParam = param.Substring(lastPos, commaPos - lastPos);
299                    int equalPos = subParam.IndexOf('=');
300                    if (equalPos == -1)
301                        result.Add(new KeyValuePair<string, string>(subParam, null));
302                    else
303                        result.Add(new KeyValuePair<string, string>(subParam.Substring(0, equalPos),
304                            subParam.Substring(equalPos + 1)));
305
306                    //Find the next ,
307                    lastPos = ++commaPos;
308                    commaPos = param.IndexOf(',', commaPos);
309                }
310
311                return result;
312            }
313
314            /// <summary>
315            /// The action that the command line specifies.
316            /// </summary>
317            public string Action
318            {
319                get
320                {
321                    return action;
322                }
323                private set
324                {
325                    action = value;
326                }
327            }
328
329            /// <summary>
330            /// True if no console window should be created.
331            /// </summary>
332            public bool Quiet
333            {
334                get
335                {
336                    return quiet;
337                }
338                private set
339                {
340                    quiet = value;
341                }
342            }
343
344            private string action;
345            private bool quiet;
346        }
347
348        /// <summary>
349        /// Manages a command line for adding tasks to the global DirectExecutor
350        /// </summary>
351        class AddTaskCommandLine : CommandLine
352        {
353            /// <summary>
354            /// Constructor.
355            /// </summary>
356            /// <param name="cmdParams">The raw command line arguments passed to the program.</param>
357            public AddTaskCommandLine(string[] cmdParams)
358                : base(cmdParams)
359            {
360            }
361
362            protected override bool ResolveParameter(string param)
363            {
364                int equalPos = param.IndexOf('=');
365                if (IsParam(param, "method", "m"))
366                {
367                    if (equalPos == -1)
368                        throw new ArgumentException("--method must be specified with an Erasure " +
369                            "method GUID.");
370
371                    List<KeyValuePair<string, string>> subParams =
372                        GetSubParameters(param.Substring(equalPos + 1));
373                    ErasureMethod = new Guid(subParams[0].Key);
374                }
375                else if (IsParam(param, "schedule", "s"))
376                {
377                    if (equalPos == -1)
378                        throw new ArgumentException("--schedule must be specified with a Schedule " +
379                            "type.");
380
381                    List<KeyValuePair<string, string>> subParams =
382                        GetSubParameters(param.Substring(equalPos + 1));
383                    switch (subParams[0].Key)
384                    {
385                        case "now":
386                            Schedule = Schedule.RunNow;
387                            break;
388                        case "restart":
389                            schedule = Schedule.RunOnRestart;
390                            break;
391                        default:
392                            throw new ArgumentException("Unknown schedule type: " + subParams[0].Key);
393                    }
394                }
395                else if (IsParam(param, "recycled", "r"))
396                {
397                    targets.Add(new Task.RecycleBin());
398                }
399                else if (IsParam(param, "unused", "u"))
400                {
401                    if (equalPos == -1)
402                        throw new ArgumentException("--unused must be specified with the Volume " +
403                            "to erase.");
404
405                    //Create the UnusedSpace target for inclusion into the task.
406                    Task.UnusedSpace target = new Task.UnusedSpace();
407
408                    //Determine if cluster tips should be erased.
409                    target.EraseClusterTips = false;
410                    List<KeyValuePair<string, string>> subParams =
411                        GetSubParameters(param.Substring(equalPos + 1));
412                    foreach (KeyValuePair<string, string> kvp in subParams)
413                        if (kvp.Value == null && target.Drive == null)
414                            target.Drive = Path.GetFullPath(kvp.Key);
415                        else if (kvp.Key == "clusterTips")
416                            target.EraseClusterTips = true;
417                        else
418                            throw new ArgumentException("Unknown subparameter: " + kvp.Key);
419                    targets.Add(target);
420                }
421                else if (IsParam(param, "dir", "d") || IsParam(param, "directory", null))
422                {
423                    if (equalPos == -1)
424                        throw new ArgumentException("--directory must be specified with the " +
425                            "directory to erase.");
426
427                    //Create the base target
428                    Task.Folder target = new Task.Folder();
429
430                    //Parse the subparameters.
431                    List<KeyValuePair<string, string>> subParams =
432                        GetSubParameters(param.Substring(equalPos + 1));
433                    foreach (KeyValuePair<string, string> kvp in subParams)
434                        if (kvp.Value == null && target.Path == null)
435                            target.Path = Path.GetFullPath(kvp.Key);
436                        else if (kvp.Key == "excludeMask")
437                        {
438                            if (kvp.Value == null)
439                                throw new ArgumentException("The exclude mask must be specified " +
440                                    "if the excludeMask subparameter is specified");
441                            target.ExcludeMask = kvp.Value;
442                        }
443                        else if (kvp.Key == "includeMask")
444                        {
445                            if (kvp.Value == null)
446                                throw new ArgumentException("The include mask must be specified " +
447                                    "if the includeMask subparameter is specified");
448                            target.IncludeMask = kvp.Value;
449                        }
450                        else if (kvp.Key == "delete")
451                            target.DeleteIfEmpty = true;
452                        else
453                            throw new ArgumentException("Unknown subparameter: " + kvp.Key);
454
455                    //Add the target to the list of targets
456                    targets.Add(target);
457                }
458                else
459                {
460                    //It's just a file!
461                    Task.File target = new Task.File();
462                    target.Path = Path.GetFullPath(param);
463                    targets.Add(target);
464                }
465
466                return true;
467            }
468
469            /// <summary>
470            /// The erasure method which the user specified on the command line.
471            /// </summary>
472            public Guid ErasureMethod
473            {
474                get
475                {
476                    return erasureMethod;
477                }
478                private set
479                {
480                    erasureMethod = value;
481                }
482            }
483
484            /// <summary>
485            /// The schedule for the current set of targets.
486            /// </summary>
487            public Schedule Schedule
488            {
489                get
490                {
491                    return schedule;
492                }
493                set
494                {
495                    schedule = value;
496                }
497            }
498
499            /// <summary>
500            /// The list of targets which was specified on the command line.
501            /// </summary>
502            public List<Task.ErasureTarget> Targets
503            {
504                get
505                {
506                    return new List<Task.ErasureTarget>(targets.ToArray());
507                }
508                set
509                {
510                    targets = value;
511                }
512            }
513
514            private Guid erasureMethod;
515            private Schedule schedule = Schedule.RunNow;
516            private List<Task.ErasureTarget> targets = new List<Task.ErasureTarget>();
517        }
518        #endregion
519
520        /// <summary>
521        /// Constructor.
522        /// </summary>
523        /// <param name="cmdParams">The raw command line arguments passed to the program.</param>
524        public CommandLineProgram(string[] cmdParams)
525        {
526            try
527            {
528                //Parse the command line arguments.
529                if (cmdParams.Length < 1)
530                    throw new ArgumentException("An action must be specified.");
531
532                switch (cmdParams[0])
533                {
534                    case "addtask":
535                        Arguments = new AddTaskCommandLine(cmdParams);
536                        break;
537                    case "querymethods":
538                    case "help":
539                    default:
540                        Arguments = new CommandLine(cmdParams);
541                        break;
542                }
543
544                //If the user did not specify the quiet command line, then create the console.
545                if (!Arguments.Quiet)
546                    CreateConsole();
547
548                //Map actions to their handlers
549                actionHandlers.Add("addtask", AddTask);
550                actionHandlers.Add("querymethods", QueryMethods);
551                actionHandlers.Add("help", Help);
552            }
553            finally
554            {
555                if (Arguments == null || !Arguments.Quiet)
556                    CreateConsole();
557            }
558        }
559
560        /// <summary>
561        /// Runs the program, analogous to System.Windows.Forms.Application.Run.
562        /// </summary>
563        public void Run()
564        {
565            //Call the function handling the current command line.
566            actionHandlers[Arguments.Action]();
567        }
568
569        /// <summary>
570        /// Creates a console for our application, setting the input/output streams to the
571        /// defaults.
572        /// </summary>
573        private void CreateConsole()
574        {
575            if (KernelAPI.AllocConsole())
576            {
577                Console.SetOut(new StreamWriter(Console.OpenStandardOutput()));
578                Console.SetIn(new StreamReader(Console.OpenStandardInput()));
579            }
580        }
581
582        /// <summary>
583        /// Prints the command line help for Eraser.
584        /// </summary>
585        private static void CommandUsage()
586        {
587            Console.WriteLine(@"usage: Eraser <action> <arguments>
588where action is
589    help                    Show this help message.
590    addtask                 Adds tasks to the current task list.
591    querymethods            Lists all registered Erasure methods.
592
593global parameters:
594    --quiet, -q             Do not create a Console window to display progress.
595
596parameters for help:
597    eraser help
598
599    no parameters to set.
600
601parameters for addtask:
602    eraser addtask [--method=<methodGUID>] [--schedule=(now|restart)] (--recycled " +
603@"| --unused=<volume> | --dir=<directory> | [file1 [file2 [...]]])
604
605    --method, -m            The Erasure method to use.
606    --schedule, -s          The schedule the task will follow. The value must
607                            be one of:
608            now             The task will be queued for immediate execution.
609            restart         The task will be queued for execution when the
610                            computer is next restarted.
611    --recycled, -r          Erases files and folders in the recycle bin
612    --unused, -u            Erases unused space in the volume.
613        optional arguments: --unused=<drive>[,clusterTips]
614            clusterTips     If specified, the drive's files will have their
615                            cluster tips erased.
616    --dir, --directory, -d  Erases files and folders in the directory
617        optional arguments: --dir=<directory>[,e=excludeMask][,i=includeMask][,delete]
618            excludeMask     A wildcard expression for files and folders to
619                            exclude.
620            includeMask     A wildcard expression for files and folders to
621                            include.
622                            The include mask is applied before the exclude
623                            mask.
624            delete          Deletes the folder at the end of the erasure if
625                            specified.
626    file1 ... fileN         The list of files to erase.
627
628parameters for querymethods:
629    eraser querymethods
630
631    no parameters to set.
632
633All arguments are case sensitive.");
634            Console.Out.Flush();
635        }
636
637        #region Action Handlers
638        /// <summary>
639        /// The command line arguments passed to the program.
640        /// </summary>
641        public CommandLine Arguments
642        {
643            get
644            {
645                return arguments;
646            }
647            private set
648            {
649                arguments = value;
650            }
651        }
652
653        /// <summary>
654        /// Prints the help text for Eraser (with copyright)
655        /// </summary>
656        private void Help()
657        {
658            Console.WriteLine(@"Eraser {0}
659(c) 2008 The Eraser Project
660Eraser is Open-Source Software: see http://eraser.heidi.ie/ for details.
661", Assembly.GetExecutingAssembly().GetName().Version);
662
663            Console.Out.Flush();
664            CommandUsage();
665        }
666
667        /// <summary>
668        /// Lists all registered erasure methods.
669        /// </summary>
670        /// <param name="commandLine">The command line parameters passed to the program.</param>
671        private void QueryMethods()
672        {
673            //Output the header
674            const string methodFormat = "{0,-2} {1,-39} {2}";
675            Console.WriteLine(methodFormat, "", "Method", "GUID");
676            Console.WriteLine(new string('-', 79));
677
678            //Refresh the list of erasure methods
679            Dictionary<Guid, ErasureMethod> methods = ErasureMethodManager.GetAll();
680            foreach (ErasureMethod method in methods.Values)
681            {
682                Console.WriteLine(methodFormat, (method is UnusedSpaceErasureMethod) ?
683                    "U" : "", method.Name, method.GUID.ToString());
684            }
685        }
686
687        /// <summary>
688        /// Parses the command line for tasks and adds them using the
689        /// <see cref="RemoteExecutor"/> class.
690        /// </summary>
691        /// <param name="commandLine">The command line parameters passed to the program.</param>
692        private void AddTask()
693        {
694            AddTaskCommandLine arguments = (AddTaskCommandLine)Arguments;
695           
696            //Create the task, and set the method to use.
697            Task task = new Task();
698            ErasureMethod method = arguments.ErasureMethod == Guid.Empty ? 
699                ErasureMethodManager.Default :
700                ErasureMethodManager.GetInstance(arguments.ErasureMethod);
701            foreach (Task.ErasureTarget target in arguments.Targets)
702            {
703                target.Method = method;
704                task.Targets.Add(target);
705            }
706
707            //Check the number of tasks in the task.
708            if (task.Targets.Count == 0)
709                throw new ArgumentException("Tasks must contain at least one erasure target.");
710
711            //Set the schedule for the task.
712            task.Schedule = arguments.Schedule;
713
714            //Send the task out.
715            using (Program.eraserClient = new RemoteExecutorClient())
716            {
717                if (!((RemoteExecutorClient)Program.eraserClient).Connect())
718                {
719                    //The client cannot connect to the server. This probably means
720                    //that the server process isn't running. Start an instance.
721                    Process eraserInstance = Process.Start(
722                        Assembly.GetExecutingAssembly().Location);
723                    eraserInstance.WaitForInputIdle();
724
725                    if (!((RemoteExecutorClient)Program.eraserClient).Connect())
726                        throw new Exception("Eraser cannot connect to the running " +
727                            "instance for erasures.");
728                }
729
730                Program.eraserClient.Run();
731                Program.eraserClient.AddTask(ref task);
732            }
733        }
734        #endregion
735
736        /// <see cref="Arguments"/>
737        private CommandLine arguments;
738
739        /// <summary>
740        /// The prototype of an action handler in the class which executes an
741        /// action as specified in the command line.
742        /// </summary>
743        private delegate void ActionHandler();
744
745        /// <summary>
746        /// Matches an action handler to a function in the class.
747        /// </summary>
748        private Dictionary<string, ActionHandler> actionHandlers =
749            new Dictionary<string, ActionHandler>();
750    }
751
752    internal class Settings : Manager.SettingsManager
753    {
754        /// <summary>
755        /// Registry-based storage backing for the Settings class.
756        /// </summary>
757        private class RegistrySettings : Manager.Settings
758        {
759            /// <summary>
760            /// Constructor.
761            /// </summary>
762            /// <param name="key">The registry key to look for the settings in.</param>
763            public RegistrySettings(Guid pluginID, RegistryKey key)
764            {
765                this.key = key;
766            }
767
768            public override object this[string setting]
769            {
770                get
771                {
772                    byte[] currentSetting = (byte[])key.GetValue(setting, null);
773                    if (currentSetting != null && currentSetting.Length != 0)
774                        using (MemoryStream stream = new MemoryStream(currentSetting))
775                            try
776                            {
777                                return new BinaryFormatter().Deserialize(stream);
778                            }
779                            catch (Exception)
780                            {
781                                key.DeleteValue(setting);
782                                MessageBox.Show(S._("Could not load the setting {0} for plugin {1}. " +
783                                    "The setting has been lost.", key, pluginID.ToString()),
784                                    S._("Eraser"), MessageBoxButtons.OK, MessageBoxIcon.Error);
785                            }
786
787                    return null;
788                }
789                set
790                {
791                    if (value == null)
792                    {
793                        key.DeleteValue(setting);
794                    }
795                    else
796                    {
797                        using (MemoryStream stream = new MemoryStream())
798                        {
799                            new BinaryFormatter().Serialize(stream, value);
800                            key.SetValue(setting, stream.ToArray(), RegistryValueKind.Binary);
801                        }
802                    }
803                }
804            }
805
806            /// <summary>
807            /// The GUID of the plugin whose settings this object is storing.
808            /// </summary>
809            private Guid pluginID;
810
811            /// <summary>
812            /// The registry key where the data is stored.
813            /// </summary>
814            private RegistryKey key;
815        }
816
817        public override void Save()
818        {
819        }
820
821        protected override Manager.Settings GetSettings(Guid guid)
822        {
823            //Open the registry key containing the settings
824            const string eraserKeyPath = @"SOFTWARE\Eraser\Eraser 6";
825            RegistryKey eraserKey = Registry.CurrentUser.OpenSubKey(eraserKeyPath, true);
826            if (eraserKey == null)
827                eraserKey = Registry.CurrentUser.CreateSubKey(eraserKeyPath);
828
829            RegistryKey pluginsKey = eraserKey.OpenSubKey(guid.ToString(), true);
830            if (pluginsKey == null)
831                pluginsKey = eraserKey.CreateSubKey(guid.ToString());
832
833            //Return the Settings object.
834            return new RegistrySettings(guid, pluginsKey);
835        }
836    }
837
838    internal class EraserSettings
839    {
840        public EraserSettings()
841        {
842            settings = Manager.ManagerLibrary.Instance.SettingsManager.ModuleSettings;
843        }
844
845        /// <summary>
846        /// Gets or sets the task list, serialised in binary form by the Manager assembly.
847        /// </summary>
848        public byte[] TaskList
849        {
850            get
851            {
852                return (byte[])settings["TaskList"];
853            }
854            set
855            {
856                settings["TaskList"] = value;
857            }
858        }
859
860        /// <summary>
861        /// Gets or sets the LCID of the language which the UI should be displayed in.
862        /// </summary>
863        public string Language
864        {
865            get
866            {
867                return settings["Language"] == null ? 
868                    GetCurrentCulture().Name :
869                    (string)settings["Language"];
870            }
871            set
872            {
873                settings["Language"] = value;
874            }
875        }
876
877        /// <summary>
878        /// Gets or sets whether the Shell Extension should be loaded into Explorer.
879        /// </summary>
880        public bool IntegrateWithShell
881        {
882            get
883            {
884                return settings["IntegrateWithShell"] == null ?
885                    true : (bool)settings["IntegrateWithShell"];
886            }
887            set
888            {
889                settings["IntegrateWithShell"] = value;
890            }
891        }
892
893        /// <summary>
894        /// Gets or sets a value on whether the main frame should be minimised to the
895        /// system notification area.
896        /// </summary>
897        public bool HideWhenMinimised
898        {
899            get
900            {
901                return settings["HideWhenMinimised"] == null ?
902                    true : (bool)settings["HideWhenMinimised"];
903            }
904            set
905            {
906                settings["HideWhenMinimised"] = value;
907            }
908        }
909
910        /// <summary>
911        /// Gets the current UI culture, correct to the top-level culture (i.e., English
912        /// instead of English (United Kingdom))
913        /// </summary>
914        /// <returns>The CultureInfo of the current UI culture, correct to the top level.</returns>
915        private static CultureInfo GetCurrentCulture()
916        {
917            CultureInfo culture = CultureInfo.CurrentUICulture;
918            while (culture.Parent != CultureInfo.InvariantCulture)
919                culture = culture.Parent;
920
921            return culture;
922        }
923
924        private Manager.Settings settings;
925    }
926}
Note: See TracBrowser for help on using the repository browser.