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

Revision 773, 26.5 KB checked in by lowjoel, 6 years ago (diff)

Eraser now takes two command parameters for GUI mode: --atRestart and --quiet.

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