Example #1
0
        /// <summary>
        /// 【一键导出】按钮单击时执行的代码
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button_Output_Click(object sender, RoutedEventArgs e)
        {
            ConfigHelper configHelper = new ConfigHelper();
            Lockscreen   lockscreen   = new Lockscreen(configHelper.GetValue("LOCKSCREEN", "ASSETS"), configHelper.GetValue("LOCKSCREEN", "OUTPATH"));

            lockscreen.OutputScreen();
            if (CheckBox_includePhone.IsChecked == false)
            {
                lockscreen.DeleteMoblieLock();
            }
            System.Windows.MessageBox.Show("导出完成!", "必应美图小助手", MessageBoxButton.OK, MessageBoxImage.Asterisk);
        }
Example #2
0
        static void Main(string[] args)
        {
            if (args.Length > 0)
            {
                string action                    = null;
                bool   singleImage               = false;
                bool   maximumRes                = false;
                bool?  portrait                  = false;
                string locale                    = null;
                bool   allLocales                = false;
                string outputDir                 = ".";
                string outputName                = "spotlight";
                bool   integrityCheck            = true;
                bool   downloadMany              = false;
                int    downloadAmount            = int.MaxValue;
                int    cacheSize                 = int.MaxValue;
                bool   metadata                  = false;
                bool   metadataAllowInconsistent = false;
                bool   embedMetadata             = false;
                string fromFile                  = null;
                int    apiTryCount               = 3;
                bool   verbose                   = false;

                switch (args[0].ToLower())
                {
                case "urls":
                case "download":
                case "wallpaper":
                case "lockscreen":
                    action = args[0].ToLower();
                    break;

                default:
                    Console.Error.WriteLine("Unknown action: " + args[0]);
                    Environment.Exit(1);
                    break;
                }

                if (args.Length > 1)
                {
                    for (int i = 1; i < args.Length; i++)
                    {
                        switch (args[i].ToLower())
                        {
                        case "--single":
                            singleImage = true;
                            break;

                        case "--many":
                            downloadMany = true;
                            break;

                        case "--amount":
                            i++;
                            downloadMany = true;
                            if (i >= args.Length)
                            {
                                Console.Error.WriteLine("--amount expects an additional argument.");
                                Environment.Exit(1);
                            }
                            if (!int.TryParse(args[i], out downloadAmount) || downloadAmount < 0)
                            {
                                Console.Error.WriteLine("Download amount must be a valid and positive number.");
                                Environment.Exit(1);
                            }
                            if (downloadAmount == 0)
                            {
                                downloadAmount = int.MaxValue;
                            }
                            break;

                        case "--cache-size":
                            i++;
                            if (i >= args.Length)
                            {
                                Console.Error.WriteLine("--cache-size expects an additional argument.");
                                Environment.Exit(1);
                            }
                            if (!int.TryParse(args[i], out cacheSize) || cacheSize <= 0)
                            {
                                Console.Error.WriteLine("Cache size must be a valid and strictly positive number.");
                                Environment.Exit(1);
                            }
                            break;

                        case "--maxres":
                            maximumRes = true;
                            break;

                        case "--portrait":
                            portrait = true;
                            break;

                        case "--landscape":
                            portrait = false;
                            break;

                        case "--locale":
                            i++;
                            if (i < args.Length)
                            {
                                locale = args[i];
                            }
                            else
                            {
                                Console.Error.WriteLine("--locale expects an additional argument.");
                                Environment.Exit(1);
                            }
                            if (!System.Text.RegularExpressions.Regex.Match(locale, "^[a-z]{2}-[A-Z]{2}$").Success)
                            {
                                Console.Error.WriteLine("--locale expected format is xx-XX, e.g. en-US.");
                                Environment.Exit(1);
                            }
                            break;

                        case "--all-locales":
                            allLocales   = true;
                            downloadMany = true;
                            break;

                        case "--outdir":
                            i++;
                            if (i < args.Length)
                            {
                                outputDir = args[i];
                            }
                            else
                            {
                                Console.Error.WriteLine("--outdir expects an additional argument.");
                                Environment.Exit(1);
                            }
                            if (!Directory.Exists(outputDir))
                            {
                                Console.Error.WriteLine("Output directory '" + outputDir + "' does not exist.");
                                Environment.Exit(1);
                            }
                            break;

                        case "--outname":
                            i++;
                            if (i < args.Length)
                            {
                                outputName = args[i];
                            }
                            else
                            {
                                Console.Error.WriteLine("--outname expects an additional argument.");
                                Environment.Exit(1);
                            }
                            foreach (char invalidChar in Path.GetInvalidFileNameChars())
                            {
                                if (outputName.Contains(invalidChar))
                                {
                                    Console.Error.WriteLine("Invalid character '" + invalidChar + "' in specified output file name.");
                                    Environment.Exit(1);
                                }
                            }
                            break;

                        case "--skip-integrity":
                            integrityCheck = false;
                            break;

                        case "--api-tries":
                            i++;
                            if (i >= args.Length)
                            {
                                Console.Error.WriteLine("--api-tries expects an additional argument.");
                                Environment.Exit(1);
                            }
                            if (!int.TryParse(args[i], out apiTryCount) || apiTryCount <= 0)
                            {
                                Console.Error.WriteLine("API tries must be a valid and strictly positive number.");
                                Environment.Exit(1);
                            }
                            break;

                        case "--metadata":
                            metadata = true;
                            break;

                        case "--inconsistent-metadata":
                            metadata = true;
                            metadataAllowInconsistent = true;
                            break;

                        case "--embed-meta":
                            embedMetadata = true;
                            break;

                        case "--from-file":
                            i++;
                            if (i < args.Length)
                            {
                                fromFile = args[i];
                            }
                            else
                            {
                                Console.Error.WriteLine("--from-file expects an additional argument.");
                                Environment.Exit(1);
                            }
                            if (!File.Exists(fromFile))
                            {
                                Console.Error.WriteLine("Input file '" + fromFile + "' does not exist.");
                                Environment.Exit(1);
                            }
                            break;

                        case "--from-dir":
                            i++;
                            if (i < args.Length)
                            {
                                fromFile = args[i];
                            }
                            else
                            {
                                Console.Error.WriteLine("--from-dir expects an additional argument.");
                                Environment.Exit(1);
                            }
                            if (Directory.Exists(fromFile))
                            {
                                string[] jpegFiles = Directory.EnumerateFiles(fromFile, "*.jpg", SearchOption.AllDirectories).ToArray();
                                if (jpegFiles.Any())
                                {
                                    fromFile = jpegFiles[new Random().Next(0, jpegFiles.Length)];
                                }
                                else
                                {
                                    Console.Error.WriteLine("Input directory '" + fromFile + "' does not contain JPG files.");
                                    Environment.Exit(1);
                                }
                            }
                            else
                            {
                                Console.Error.WriteLine("Input directory '" + fromFile + "' does not exist.");
                                Environment.Exit(1);
                            }
                            break;

                        case "--restore":
                            if (action == "lockscreen")
                            {
                                if (FileSystemAdmin.IsAdmin())
                                {
                                    try
                                    {
                                        Lockscreen.RestoreDefaultGlobalLockscreen();
                                        Environment.Exit(0);
                                    }
                                    catch (Exception e)
                                    {
                                        Console.Error.WriteLine(e.GetType() + ": " + e.Message);
                                        Environment.Exit(4);
                                    }
                                }
                                else
                                {
                                    Console.Error.WriteLine("This program must run as administrator to restore the global lockscreen.");
                                    Environment.Exit(4);
                                }
                            }
                            break;

                        case "--verbose":
                            verbose = true;
                            break;

                        default:
                            Console.Error.WriteLine("Unknown argument: " + args[i]);
                            Environment.Exit(1);
                            break;
                        }
                    }

                    if (downloadMany && cacheSize < downloadAmount)
                    {
                        Console.Error.WriteLine(
                            "Download amount ({0}) is greater than cache size ({1}). Reducing download amount to {1}.",
                            downloadAmount == int.MaxValue ? "MAX" : downloadAmount.ToString(),
                            cacheSize
                            );
                        downloadAmount = cacheSize;
                    }

                    if (downloadMany && metadata && allLocales && !metadataAllowInconsistent)
                    {
                        Console.Error.WriteLine("--metadata combined with --all-locales will produce random metadata languages.");
                        Console.Error.WriteLine("Please relaunch with --inconsistent-metadata if you really intend to do this.");
                        Environment.Exit(1);
                    }
                }

                try
                {
                    Queue <string> remainingLocales = new Queue <string>();

                    if (allLocales)
                    {
                        remainingLocales = new Queue <string>(Locales.AllKnownSpotlightLocales);
                        Console.Error.WriteLine(String.Format("Starting download using {0} locales", remainingLocales.Count));
                        locale = remainingLocales.Dequeue();
                        Console.Error.WriteLine(String.Format("Switching to {0} - {1} locales remaining", locale, remainingLocales.Count + 1));
                    }

                    int downloadCount = 0;
                    int noNewImgCount = 0;

                    do
                    {
                        SpotlightImage[] images = (fromFile != null && (action == "wallpaper" || action == "lockscreen"))
                            ? new[] { new SpotlightImage() } // Skip API request, we'll use a local file
                            : Spotlight.GetImageUrls(maximumRes, portrait, locale, apiTryCount);

                        if (images.Length < 1)
                        {
                            Console.Error.WriteLine(Program.Name + " received an empty image set from Spotlight API.");
                            Environment.Exit(2);
                        }

                        SpotlightImage randomImage = images.OrderBy(p => new Guid()).First();

                        if (action == "urls")
                        {
                            if (singleImage)
                            {
                                Console.WriteLine(randomImage.Uri);
                            }
                            else
                            {
                                foreach (SpotlightImage image in images)
                                {
                                    Console.WriteLine(image.Uri);
                                }
                            }
                            Environment.Exit(0);
                        }

                        try
                        {
                            if (singleImage || action == "wallpaper" || action == "lockscreen")
                            {
                                string imageFile = fromFile ?? randomImage.DownloadToFile(outputDir, integrityCheck, metadata, outputName, apiTryCount);
                                if (embedMetadata)
                                {
                                    imageFile = SpotlightImage.EmbedMetadata(imageFile, outputDir, outputName);
                                }
                                Console.WriteLine(imageFile);
                                if (action == "wallpaper")
                                {
                                    try
                                    {
                                        Desktop.SetWallpaper(imageFile);
                                    }
                                    catch (Exception e)
                                    {
                                        Console.Error.WriteLine(e.GetType() + ": " + e.Message);
                                        Environment.Exit(4);
                                    }
                                }
                                else if (action == "lockscreen")
                                {
                                    if (FileSystemAdmin.IsAdmin())
                                    {
                                        try
                                        {
                                            Lockscreen.SetGlobalLockscreen(imageFile);
                                        }
                                        catch (Exception e)
                                        {
                                            Console.Error.WriteLine(e.GetType() + ": " + e.Message);
                                            Environment.Exit(4);
                                        }
                                    }
                                    else
                                    {
                                        Console.Error.WriteLine("This program must run as administrator to change the global lockscreen.");
                                        Environment.Exit(4);
                                    }
                                }
                                Environment.Exit(0);
                            }

                            downloadCount = 0;

                            foreach (SpotlightImage image in images)
                            {
                                string imagePath = image.GetFilePath(outputDir);
                                if (!File.Exists(imagePath))
                                {
                                    try
                                    {
                                        Console.WriteLine(image.DownloadToFile(outputDir, integrityCheck, metadata, null, apiTryCount));
                                        downloadCount++;
                                        downloadAmount--;
                                        if (downloadAmount <= 0)
                                        {
                                            break;
                                        }
                                    }
                                    catch (InvalidDataException)
                                    {
                                        Console.Error.WriteLine("Skipping invalid image: " + image.Uri);
                                    }
                                }
                            }

                            if (verbose)
                            {
                                Console.Error.WriteLine("Successfully downloaded: " + downloadCount + " images.");
                                Console.Error.WriteLine("Already downloaded: " + (images.Length - downloadCount) + " images.");
                            }

                            if (downloadCount == 0)
                            {
                                noNewImgCount++;
                            }
                            else
                            {
                                noNewImgCount = 0;
                            }
                        }
                        catch (Exception e)
                        {
                            Console.Error.WriteLine(e.GetType() + ": " + e.Message);
                            Environment.Exit(3);
                        }

                        if (allLocales && noNewImgCount >= 50 && remainingLocales.Count > 0)
                        {
                            noNewImgCount = 0;
                            locale        = remainingLocales.Dequeue();
                            Console.Error.WriteLine(String.Format("Switching to {0} - {1} locales remaining", locale, remainingLocales.Count + 1));
                        }
                    } while (downloadMany && (downloadCount > 0 || noNewImgCount < 50) && downloadAmount > 0);

                    if (cacheSize < int.MaxValue && cacheSize > 0)
                    {
                        foreach (FileInfo imgToDelete in
                                 Directory.GetFiles(outputDir, "*.jpg", SearchOption.TopDirectoryOnly)
                                 .Select(filePath => new FileInfo(filePath))
                                 .OrderByDescending(fileInfo => fileInfo.CreationTime)
                                 .Skip(cacheSize))
                        {
                            string metadataFile = SpotlightImage.GetMetaLocation(imgToDelete.FullName);
                            if (File.Exists(metadataFile))
                            {
                                File.Delete(metadataFile);
                            }
                            imgToDelete.Delete();
                        }
                    }

                    Environment.Exit(0);
                }
                catch (Exception e)
                {
                    Console.Error.WriteLine(e.GetType() + ": " + e.Message);
                    Environment.Exit(2);
                }
            }

            foreach (string str in new[] {
                " ==== " + Program.Name + " v" + Program.Version + " - By ORelio - Microzoom.fr ====",
                "",
                "Retrieve Windows Spotlight images by requesting the Microsoft Spotlight API.",
                Program.Name + " can also define images as wallpaper and system-wide lockscreen image.",
                "",
                "Usage:",
                "  " + Program.Name + ".exe <action> [arguments]",
                "  Only one action must be provided, as first argument",
                "  Then, provide any number of arguments from the list below.",
                "",
                "Actions:",
                "  urls               Query Spotlight API and print image URLs to standard output",
                "  download           Download all images and print file path to standard output",
                "  wallpaper          Download one random image and define it as wallpaper",
                "  lockscreen         Download one random image and define it as global lockscreen",
                "",
                "Arguments:",
                "  --single           Print only one random url or download only one image as spotlight.jpg",
                "  --many             Try downloading as much images as possible by calling API many times",
                "  --amount <n>       Stop downloading after <n> images successfully downloaded, implies --many",
                "  --cache-size <n>   Only keep <n> most recent images in the output directory, delete others",
                "  --maxres           Force maximum image resolution instead of tailoring to current screen res",
                "  --portrait         Force portrait image instead of autodetecting from current screen res",
                "  --landscape        Force landscape image instead of autodetecting from current screen res",
                "  --locale <xx-XX>   Force specified locale, e.g. en-US, instead of autodetecting from system",
                "  --all-locales      Attempt to download images for all known Spotlight locales, implies --many",
                "  --outdir <dir>     Set output directory instead of defaulting to working directory",
                "  --outname <name>   Set output file name as <name>.ext for --single or --embed-meta",
                "  --skip-integrity   Skip integrity check of downloaded files: file size and sha256 hash",
                "  --api-tries <n>    Amount of unsuccessful API calls before giving up. Default is 3.",
                "  --metadata         Also save image metadata such as title & copyright as <image-name>.txt",
                "  --embed-meta       When available, embed metadata into wallpaper or lockscreen image",
                "  --from-file        Set the specified file as wallpaper/lockscreen instead of downloading",
                "  --from-dir         Set a random image from the specified directory as wallpaper/lockscreen",
                "  --restore          Restore the default lockscreen image, has no effect with other actions",
                "  --verbose          Display additional status messages while downloading images from API",
                "",
                "Exit codes:",
                "  0                  Success",
                "  1                  Invalid arguments",
                "  2                  Spotlight API request failure",
                "  3                  Image download failure or Failed to write image to disk",
                "  4                  Failed to define image as wallpaper or lock screen image"
            })
            {
                Console.Error.WriteLine(str);
            }
            Environment.Exit(1);
        }
Example #3
0
        internal static void AddContextMenus()
        {
            // Add main contextmenu
            cm = new ContextMenu();
            var scbf = (SolidColorBrush)Application.Current.Resources["MainColorFadedBrush"];

            ///////////////////////////
            ///////////////////////////
            ///     Open           \\\\
            ///////////////////////////
            ///////////////////////////
            var opencm = new MenuItem
            {
                Header           = Application.Current.Resources["Open"] as string,
                InputGestureText = $"{Application.Current.Resources["Ctrl"] as string} + O"
            };
            var opencmIcon = new System.Windows.Shapes.Path
            {
                Data    = Geometry.Parse(SVGiconFile),
                Stretch = Stretch.Fill
            };

            opencmIcon.Width = opencmIcon.Height = 12;
            opencmIcon.Fill  = scbf;
            opencm.Icon      = opencmIcon;
            opencm.Click    += (s, x) => Open();
            cm.Items.Add(opencm);

            ///////////////////////////
            ///////////////////////////
            ///     Save           \\\\
            ///////////////////////////
            ///////////////////////////
            var savecm = new MenuItem()
            {
                Header           = Application.Current.Resources["Save"] as string,
                InputGestureText = $"{Application.Current.Resources["Ctrl"] as string} + S"
            };
            var savecmIcon = new System.Windows.Shapes.Path
            {
                Data    = Geometry.Parse(SVGiconSave),
                Stretch = Stretch.Fill
            };

            savecmIcon.Width = savecmIcon.Height = 12;
            savecmIcon.Fill  = scbf;
            savecm.Icon      = savecmIcon;
            savecm.Click    += (s, x) => SaveFiles();
            cm.Items.Add(savecm);

            ///////////////////////////
            ///////////////////////////
            ///     Print          \\\\
            ///////////////////////////
            ///////////////////////////
            var printcm = new MenuItem
            {
                Header           = Application.Current.Resources["Print"] as string,
                InputGestureText = $"{Application.Current.Resources["Ctrl"] as string} + P"
            };
            var printcmIcon = new System.Windows.Shapes.Path
            {
                Data    = Geometry.Parse(SVGiconPrint),
                Stretch = Stretch.Fill
            };

            printcmIcon.Width = printcmIcon.Height = 12;
            printcmIcon.Fill  = scbf;
            printcm.Icon      = printcmIcon;
            printcm.Click    += (s, x) => Print(Pics[FolderIndex]);
            cm.Items.Add(printcm);

            ///////////////////////////
            ///////////////////////////
            ///     Open With      \\\\
            ///////////////////////////
            ///////////////////////////
            var openwcm = new MenuItem
            {
                Header           = Application.Current.Resources["OpenWith"] as string,
                InputGestureText = "E"
            };
            var openwIcon = new System.Windows.Shapes.Path
            {
                Data    = Geometry.Parse(SVGiconSend),
                Stretch = Stretch.Fill
            };

            openwIcon.Width = openwIcon.Height = 12;
            openwIcon.Fill  = scbf;
            openwcm.Icon    = openwIcon;
            openwcm.Click  += (s, x) => OpenWith(Pics[FolderIndex]);
            cm.Items.Add(openwcm);

            ///////////////////////////
            ///////////////////////////
            ///     Recent Files   \\\\
            ///////////////////////////
            ///////////////////////////
            cm.Items.Add(new Separator());
            var recentcm = new MenuItem
            {
                Header = Application.Current.Resources["RecentFiles"] as string,
            };
            var recentcmIcon = new System.Windows.Shapes.Path
            {
                Data    = Geometry.Parse(SVGiconPaper),
                Stretch = Stretch.Fill
            };

            recentcmIcon.Width = recentcmIcon.Height = 12;
            recentcmIcon.Fill  = scbf;
            recentcm.Icon      = recentcmIcon;
            cm.Items.Add(recentcm);

            ///////////////////////////
            ///////////////////////////
            ///     Sort Files     \\\\
            ///////////////////////////
            ///////////////////////////
            var sortcm = new MenuItem
            {
                Header = Application.Current.Resources["SortFilesBy"] as string,
            };
            var sortcmIcon = new System.Windows.Shapes.Path
            {
                Data    = Geometry.Parse(SVGiconSort),
                Stretch = Stretch.Fill
            };

            sortcmIcon.Width = sortcmIcon.Height = 12;
            sortcmIcon.Fill  = scbf;
            sortcm.Icon      = sortcmIcon;

            ///////////////////////////
            ///   File Name        \\\\
            ///////////////////////////
            var sortcmChild0       = new MenuItem();
            var sortcmChild0Header = new RadioButton
            {
                Content         = Application.Current.Resources["FileName"] as string,
                BorderThickness = new Thickness(0, 0, 0, 0),
                MinWidth        = 125,
                IsChecked       = Properties.Settings.Default.SortPreference == 0
            };

            sortcmChild0Header.Click += delegate { ConfigureSettings.UpdateUIValues.ChangeSorting(0); cm.IsOpen = false; };
            sortcmChild0.Click       += delegate { ConfigureSettings.UpdateUIValues.ChangeSorting(0); cm.IsOpen = false; };
            sortcmChild0.Header       = sortcmChild0Header;
            sortcm.Items.Add(sortcmChild0);

            ///////////////////////////
            ///   File Size        \\\\
            ///////////////////////////
            var sortcmChild1       = new MenuItem();
            var sortcmChild1Header = new RadioButton
            {
                Content         = Application.Current.Resources["FileSize"] as string,
                BorderThickness = new Thickness(0, 0, 0, 0),
                MinWidth        = 125,
                IsChecked       = Properties.Settings.Default.SortPreference == 1
            };

            sortcmChild1Header.Click += delegate { ConfigureSettings.UpdateUIValues.ChangeSorting(1); cm.IsOpen = false; };
            sortcmChild1.Click       += delegate { ConfigureSettings.UpdateUIValues.ChangeSorting(1); cm.IsOpen = false; };
            sortcmChild1.Header       = sortcmChild1Header;
            sortcm.Items.Add(sortcmChild1);

            ///////////////////////////
            ///   Creation Time     \\\\
            ///////////////////////////
            var sortcmChild2       = new MenuItem();
            var sortcmChild2Header = new RadioButton
            {
                Content         = Application.Current.Resources["CreationTime"] as string,
                BorderThickness = new Thickness(0, 0, 0, 0),
                MinWidth        = 125,
                IsChecked       = Properties.Settings.Default.SortPreference == 2
            };

            sortcmChild2Header.Click += delegate { ConfigureSettings.UpdateUIValues.ChangeSorting(2); cm.IsOpen = false; };
            sortcmChild2.Click       += delegate { ConfigureSettings.UpdateUIValues.ChangeSorting(2); cm.IsOpen = false; };
            sortcmChild2.Header       = sortcmChild2Header;
            sortcm.Items.Add(sortcmChild2);

            ///////////////////////////
            ///   File extension   \\\\
            ///////////////////////////
            var sortcmChild3       = new MenuItem();
            var sortcmChild3Header = new RadioButton
            {
                Content         = Application.Current.Resources["FileExtension"] as string,
                BorderThickness = new Thickness(0, 0, 0, 0),
                MinWidth        = 125,
                IsChecked       = Properties.Settings.Default.SortPreference == 3
            };

            sortcmChild3Header.Click += delegate { ConfigureSettings.UpdateUIValues.ChangeSorting(3); cm.IsOpen = false; };
            sortcmChild3.Click       += delegate { ConfigureSettings.UpdateUIValues.ChangeSorting(3); cm.IsOpen = false; };
            sortcmChild3.Header       = sortcmChild3Header;
            sortcm.Items.Add(sortcmChild3);

            ///////////////////////////
            ///   Last Access Time \\\\
            ///////////////////////////
            var sortcmChild4       = new MenuItem();
            var sortcmChild4Header = new RadioButton
            {
                Content         = Application.Current.Resources["LastAccessTime"] as string,
                BorderThickness = new Thickness(0, 0, 0, 0),
                MinWidth        = 125,
                IsChecked       = Properties.Settings.Default.SortPreference == 4
            };

            sortcmChild4Header.Click += delegate { ConfigureSettings.UpdateUIValues.ChangeSorting(4); cm.IsOpen = false; };
            sortcmChild4.Click       += delegate { ConfigureSettings.UpdateUIValues.ChangeSorting(4); cm.IsOpen = false; };
            sortcmChild4.Header       = sortcmChild4Header;
            sortcm.Items.Add(sortcmChild4);

            ///////////////////////////
            ///   Last Write Time  \\\\
            ///////////////////////////
            var sortcmChild5       = new MenuItem();
            var sortcmChild5Header = new RadioButton
            {
                Content         = Application.Current.Resources["LastWriteTime"] as string,
                BorderThickness = new Thickness(0, 0, 0, 0),
                MinWidth        = 125,
                IsChecked       = Properties.Settings.Default.SortPreference == 5
            };

            sortcmChild5Header.Click += delegate { ConfigureSettings.UpdateUIValues.ChangeSorting(5); cm.IsOpen = false; };
            sortcmChild5.Click       += delegate { ConfigureSettings.UpdateUIValues.ChangeSorting(5); cm.IsOpen = false; };
            sortcmChild5.Header       = sortcmChild5Header;
            sortcm.Items.Add(sortcmChild5);

            ///////////////////////////
            ///   Random        \\\\
            ///////////////////////////
            var sortcmChild6       = new MenuItem();
            var sortcmChild6Header = new RadioButton
            {
                Content         = Application.Current.Resources["Random"] as string,
                BorderThickness = new Thickness(0, 0, 0, 0),
                MinWidth        = 125,
                IsChecked       = Properties.Settings.Default.SortPreference == 6
            };

            sortcmChild6Header.Click += delegate { ConfigureSettings.UpdateUIValues.ChangeSorting(6); cm.IsOpen = false; };
            sortcmChild6.Click       += delegate { ConfigureSettings.UpdateUIValues.ChangeSorting(6); cm.IsOpen = false; };
            sortcmChild6.Header       = sortcmChild6Header;
            sortcm.Items.Add(sortcmChild6);
            cm.Items.Add(sortcm);

            ///////////////////////////
            ///////////////////////////
            ///     Settings       \\\\
            ///////////////////////////
            ///////////////////////////
            var settingscm = new MenuItem
            {
                Header = Application.Current.Resources["Settings"] as string,
            };
            var settingscmIcon = new System.Windows.Shapes.Path
            {
                Data    = Geometry.Parse(SVGiconWrench),
                Stretch = Stretch.Fill
            };

            settingscmIcon.Width = settingscmIcon.Height = 12;
            settingscmIcon.Fill  = scbf;
            settingscm.Icon      = settingscmIcon;
            cm.Items.Add(settingscm);

            ///////////////////////////
            ///   Looping          \\\\
            ///////////////////////////
            var settingscmLoop = new MenuItem
            {
                InputGestureText = "L"
            };
            var settingscmLoopHeader = new CheckBox
            {
                IsChecked           = Properties.Settings.Default.Looping,
                Content             = Application.Current.Resources["Looping"] as string,
                FontSize            = 13,
                MinWidth            = 125,
                HorizontalAlignment = HorizontalAlignment.Left,
                Width  = double.NaN,
                Height = double.NaN
            };

            settingscmLoop.Header       = settingscmLoopHeader;
            settingscmLoop.Click       += (s, x) => { ConfigureSettings.UpdateUIValues.SetLooping(s, x); };
            settingscmLoopHeader.Click += (s, x) => { ConfigureSettings.UpdateUIValues.SetLooping(s, x); };
            settingscm.Items.Add(settingscmLoop);

            ///////////////////////////
            ///   Scroll         \\\\
            ///////////////////////////
            var settingscmScroll = new MenuItem
            {
                InputGestureText = "X"
            };
            var settingscmScrollHeader = new CheckBox
            {
                IsChecked           = Properties.Settings.Default.ScrollEnabled,
                Content             = Application.Current.Resources["Scrolling"] as string,
                FontSize            = 13,
                MinWidth            = 125,
                HorizontalAlignment = HorizontalAlignment.Left,
                Width  = double.NaN,
                Height = double.NaN
            };

            settingscmScrollHeader.Click += ConfigureSettings.UpdateUIValues.SetScrolling;
            settingscmScroll.Header       = settingscmScrollHeader;
            settingscmScroll.Click       += (s, x) => { ConfigureSettings.UpdateUIValues.SetScrolling(s, x); settingscmScrollHeader.IsChecked = (bool)settingscmScrollHeader.IsChecked ? false : true; };
            settingscm.Items.Add(settingscmScroll);

            ///////////////////////////
            ///   Alt interface    \\\\
            ///////////////////////////
            var altcm = new MenuItem
            {
                InputGestureText = "Alt + Z"
            };
            var altcmHeader = new CheckBox
            {
                Content             = Application.Current.Resources["ShowHideUI"] as string,
                IsChecked           = Properties.Settings.Default.ShowInterface,
                FontSize            = 13,
                MinWidth            = 125,
                HorizontalAlignment = HorizontalAlignment.Left,
                Width  = double.NaN,
                Height = double.NaN
            };

            altcmHeader.Click += delegate
            {
                if (GalleryFunctions.IsOpen)
                {
                    altcmHeader.IsChecked = Properties.Settings.Default.ShowInterface;
                    return;
                }
                HideInterfaceLogic.ToggleInterface();
            };
            altcm.Header = altcmHeader;
            altcm.Click += delegate { HideInterfaceLogic.ToggleInterface(); };
            settingscm.Items.Add(altcm);

            ///////////////////////////
            ///   Transparent bg   \\\\
            ///////////////////////////
            var transcm = new MenuItem
            {
                InputGestureText = "T"
            };
            var transcmHeader = new Button
            {
                Content             = Application.Current.Resources["ChangeBg"] as string,
                ToolTip             = Application.Current.Resources["ChangeBgTooltip"] as string,
                FontSize            = 13,
                Width               = double.NaN,
                Height              = double.NaN,
                HorizontalAlignment = HorizontalAlignment.Left
            };

            transcmHeader.Click += ConfigureSettings.ConfigColors.ChangeBackground;
            transcm.Header       = transcmHeader;
            transcm.Click       += ConfigureSettings.ConfigColors.ChangeBackground;
            settingscm.Items.Add(transcm);

            cm.Items.Add(new Separator());

            ///////////////////////////
            ///////////////////////////
            ///  Set as            \\\\
            ///////////////////////////
            ///////////////////////////

            var setAsCm = new MenuItem
            {
                Header = Application.Current.Resources["SetAs"] as string,
            };

            var setAsCmIcon = new System.Windows.Shapes.Path
            {
                Data    = Geometry.Parse(SVGiconCamera),
                Stretch = Stretch.Fill
            };

            setAsCmIcon.Width = setAsCmIcon.Height = 12;
            setAsCmIcon.Fill  = scbf;
            setAsCm.Icon      = setAsCmIcon;

            var wallcm = new MenuItem
            {
                Header = Application.Current.Resources["SetAsWallpaper"] as string,
            };

            wallcm.Click += (s, x) => SetWallpaper(WallpaperStyle.Fill);
            var wallcmIcon = new System.Windows.Shapes.Path
            {
                Data    = Geometry.Parse(SVGiconCamera),
                Stretch = Stretch.Fill
            };

            wallcmIcon.Width = wallcmIcon.Height = 12;
            wallcmIcon.Fill  = scbf;
            wallcm.Icon      = wallcmIcon;
            setAsCm.Items.Add(wallcm);

            var lockCm = new MenuItem
            {
                Header = Application.Current.Resources["SetAsLockScreenImage"] as string,
            };

            lockCm.Click += async delegate { await Lockscreen.ChangeLockScreenBackground(Pics[FolderIndex]).ConfigureAwait(false); };
            var lockCmIcon = new System.Windows.Shapes.Path
            {
                Data    = Geometry.Parse(SVGiconCamera),
                Stretch = Stretch.Fill
            };

            lockCmIcon.Width = lockCmIcon.Height = 12;
            lockCmIcon.Fill  = scbf;
            lockCm.Icon      = lockCmIcon;
            setAsCm.Items.Add(lockCm);

            cm.Items.Add(setAsCm);

            ///////////////////////////
            ///////////////////////////
            ///   Locate on disk   \\\\
            ///////////////////////////
            ///////////////////////////
            var lcdcm = new MenuItem
            {
                Header           = Application.Current.Resources["ShowInFolder"] as string,
                InputGestureText = "F3"
            };
            var lcdcmIcon = new System.Windows.Shapes.Path
            {
                Data    = Geometry.Parse(SVGiconSearch),
                Stretch = Stretch.Fill
            };

            lcdcmIcon.Width = lcdcmIcon.Height = 12;
            lcdcmIcon.Fill  = scbf;
            lcdcm.Icon      = lcdcmIcon;
            lcdcm.Click    += (s, x) => Open_In_Explorer();
            cm.Items.Add(lcdcm);

            ///////////////////////////
            ///////////////////////////
            ///   Image Info       \\\\
            ///////////////////////////
            ///////////////////////////
            var fildecm = new MenuItem
            {
                Header = Application.Current.Resources["ImageInfo"] as string,
            };
            var fildecmIcon = new System.Windows.Shapes.Path
            {
                Data    = Geometry.Parse(SVGiconPaperDetails),
                Stretch = Stretch.Fill
            };

            fildecmIcon.Width = fildecmIcon.Height = 12;
            fildecmIcon.Fill  = scbf;
            fildecm.Icon      = fildecmIcon;
            fildecm.Click    += (_, _) => LoadWindows.ImageInfoWindow();
            cm.Items.Add(fildecm);
            cm.Items.Add(new Separator());

            ///////////////////////////
            ///////////////////////////
            ///   Copy             \\\\
            ///////////////////////////
            ///////////////////////////
            var cpm = new MenuItem
            {
                Header = Application.Current.Resources["Copy"] as string,
            };

            var cpmIcon = new System.Windows.Shapes.Path
            {
                Data    = Geometry.Parse(SVGiconCopy),
                Stretch = Stretch.Fill
            };

            cpmIcon.Width = cpmIcon.Height = 12;
            cpmIcon.Fill  = scbf;
            cpm.Icon      = cpmIcon;

            ///////////////////////////
            ///   Copy file        \\\\
            ///////////////////////////
            var cppcm = new MenuItem
            {
                Header  = Application.Current.Resources["CopyFile"] as string,
                ToolTip = Application.Current.Resources["CopyFile"] as string
                          + $" [{Application.Current.Resources["Ctrl"] as string}] + C]",
            };

            cppcm.Click += (s, x) => Copyfile();
            cpm.Items.Add(cppcm);

            ///////////////////////////
            ///   Copy base64      \\\\
            ///////////////////////////
            var cpxcm = new MenuItem
            {
                Header  = Application.Current.Resources["Copy"] as string + " base64",
                ToolTip = Application.Current.Resources["Copy"] as string + " base64"
                          + $" [{Application.Current.Resources["Ctrl"] as string} + " +
                          $"{Application.Current.Resources["Shift"] as string}  + C]",
            };

            cpxcm.Click += async delegate { await Base64.SendToClipboard().ConfigureAwait(false); };
            cpm.Items.Add(cpxcm);

            ///////////////////////////
            ///   Copy bitmap      \\\\
            ///////////////////////////
            var cpxbm = new MenuItem
            {
                Header  = Application.Current.Resources["CopyImage"] as string,
                ToolTip = Application.Current.Resources["CopyImageTooltip"] as string
                          + $" [{Application.Current.Resources["Ctrl"] as string} + " +
                          $"{Application.Current.Resources["Alt"] as string}  + C]",
            };

            cpxbm.Click += (s, x) => CopyBitmap();
            cpm.Items.Add(cpxbm);

            ///////////////////////////
            ///   Copy file path   \\\\
            ///////////////////////////
            var cppfm = new MenuItem
            {
                Header = Application.Current.Resources["FileCopyPath"] as string,
            };

            cppfm.Click += (s, x) => CopyText();
            cpm.Items.Add(cppfm);

            cm.Items.Add(cpm);

            ///////////////////////////
            ///////////////////////////
            ///   Cut File         \\\\
            ///////////////////////////
            ///////////////////////////
            var cpccm = new MenuItem
            {
                Header           = Application.Current.Resources["FileCut"] as string,
                InputGestureText = $"{Application.Current.Resources["Ctrl"] as string} + X"
            };
            var cpccmIcon = new System.Windows.Shapes.Path
            {
                Data    = Geometry.Parse(SVGiconScissor),
                Stretch = Stretch.Fill
            };

            cpccmIcon.Width = cpccmIcon.Height = 12;
            cpccmIcon.Fill  = scbf;
            cpccm.Icon      = cpccmIcon;
            cpccm.Click    += (s, x) => Cut(Pics[FolderIndex]);
            cm.Items.Add(cpccm);

            ///////////////////////////
            ///////////////////////////
            ///   Paste File       \\\\
            ///////////////////////////
            ///////////////////////////
            var pastecm = new MenuItem
            {
                Header           = Application.Current.Resources["FilePaste"] as string,
                InputGestureText = $"{Application.Current.Resources["Ctrl"] as string} + V"
            };
            var pastecmIcon = new System.Windows.Shapes.Path
            {
                Data    = Geometry.Parse(SVGiconPaste),
                Stretch = Stretch.Fill,
                Width   = 12,
                Height  = 12,
                Fill    = scbf
            };

            pastecm.Icon   = pastecmIcon;
            pastecm.Click += (s, x) => Paste();
            cm.Items.Add(pastecm);

            ///////////////////////////
            ///////////////////////////
            ///   Delete File      \\\\
            ///////////////////////////
            ///////////////////////////
            var MovetoRecycleBin = new MenuItem
            {
                Header           = Application.Current.Resources["DeleteFile"] as string,
                InputGestureText = Application.Current.Resources["Delete"] as string,
            };
            var MovetoRecycleBinIcon = new System.Windows.Shapes.Path
            {
                Data    = Geometry.Parse(SVGiconRecycle),
                Stretch = Stretch.Fill,
                Width   = 12,
                Height  = 12,
                Fill    = scbf
            };

            MovetoRecycleBin.Icon   = MovetoRecycleBinIcon;
            MovetoRecycleBin.Click += delegate { DeleteFile(Pics[FolderIndex], true); };
            cm.Items.Add(MovetoRecycleBin);

            ///////////////////////////
            ///////////////////////////
            ///   Close            \\\\
            ///////////////////////////
            ///////////////////////////
            cm.Items.Add(new Separator());
            var clcm = new MenuItem
            {
                Header           = Application.Current.Resources["Close"] as string,
                InputGestureText = Application.Current.Resources["Esc"] as string,
                StaysOpenOnClick = false
            };
            var mclcmIcon = new System.Windows.Shapes.Path
            {
                Data    = Geometry.Parse(SVGiconClose),
                Stretch = Stretch.Fill,
                Width   = 12,
                Height  = 12,
                Fill    = scbf
            };

            clcm.Icon   = mclcmIcon;
            clcm.Click += (s, x) => { cm.Visibility = Visibility.Collapsed; SystemCommands.CloseWindow(LoadWindows.GetMainWindow); };
            cm.Items.Add(clcm);

            // Add to elements
            LoadWindows.GetMainWindow.MainImage.ContextMenu = LoadWindows.GetMainWindow.ParentContainer.ContextMenu = cm;
            cm.Opened += (tt, yy) => Recentcm_Opened(recentcm);

#if DEBUG
            Trace.WriteLine("Contextmenu loaded");
#endif
        }
        static void Main(string[] args)
        {
            if (args.Length > 0)
            {
                string action         = null;
                bool   singleImage    = false;
                bool   maximumRes     = false;
                bool?  portrait       = false;
                string outputDir      = ".";
                string outputName     = "spotlight";
                bool   integrityCheck = true;
                bool   downloadMany   = false;
                bool   metadata       = false;
                string fromFile       = null;

                switch (args[0].ToLower())
                {
                case "urls":
                case "download":
                case "wallpaper":
                case "lockscreen":
                    action = args[0].ToLower();
                    break;

                default:
                    Console.Error.WriteLine("Unknown action: " + args[0]);
                    Environment.Exit(1);
                    break;
                }

                if (args.Length > 1)
                {
                    for (int i = 1; i < args.Length; i++)
                    {
                        switch (args[i].ToLower())
                        {
                        case "--single":
                            singleImage = true;
                            break;

                        case "--many":
                            downloadMany = true;
                            break;

                        case "--maxres":
                            maximumRes = true;
                            break;

                        case "--portrait":
                            portrait = true;
                            break;

                        case "--landscape":
                            portrait = false;
                            break;

                        case "--outdir":
                            i++;
                            if (i < args.Length)
                            {
                                outputDir = args[i];
                            }
                            else
                            {
                                Console.Error.WriteLine("--outdir expects an additional argument.");
                                Environment.Exit(1);
                            }
                            if (!Directory.Exists(outputDir))
                            {
                                Console.Error.WriteLine("Output directory '" + outputDir + "' does not exist.");
                                Environment.Exit(1);
                            }
                            break;

                        case "--outname":
                            i++;
                            if (i < args.Length)
                            {
                                outputName = args[i];
                            }
                            else
                            {
                                Console.Error.WriteLine("--outname expects an additional argument.");
                                Environment.Exit(1);
                            }
                            foreach (char invalidChar in Path.GetInvalidFileNameChars())
                            {
                                if (outputName.Contains(invalidChar))
                                {
                                    Console.Error.WriteLine("Invalid character '" + invalidChar + "' in specified output file name.");
                                    Environment.Exit(1);
                                }
                            }
                            break;

                        case "--skip-integrity":
                            integrityCheck = false;
                            break;

                        case "--metadata":
                            metadata = true;
                            break;

                        case "--from-file":
                            i++;
                            if (i < args.Length)
                            {
                                fromFile = args[i];
                            }
                            else
                            {
                                Console.Error.WriteLine("--from-file expects an additional argument.");
                                Environment.Exit(1);
                            }
                            if (!File.Exists(fromFile))
                            {
                                Console.Error.WriteLine("Input file '" + fromFile + "' does not exist.");
                                Environment.Exit(1);
                            }
                            break;

                        case "--from-dir":
                            i++;
                            if (i < args.Length)
                            {
                                fromFile = args[i];
                            }
                            else
                            {
                                Console.Error.WriteLine("--from-dir expects an additional argument.");
                                Environment.Exit(1);
                            }
                            if (Directory.Exists(fromFile))
                            {
                                string[] jpegFiles = Directory.EnumerateFiles(fromFile, "*.jpg", SearchOption.AllDirectories).ToArray();
                                if (jpegFiles.Any())
                                {
                                    fromFile = jpegFiles[new Random().Next(0, jpegFiles.Length)];
                                }
                                else
                                {
                                    Console.Error.WriteLine("Input directory '" + fromFile + "' does not contain JPG files.");
                                    Environment.Exit(1);
                                }
                            }
                            else
                            {
                                Console.Error.WriteLine("Input directory '" + fromFile + "' does not exist.");
                                Environment.Exit(1);
                            }
                            break;

                        case "--restore":
                            if (action == "lockscreen")
                            {
                                if (FileSystemAdmin.IsAdmin())
                                {
                                    try
                                    {
                                        Lockscreen.RestoreDefaultGlobalLockscreen();
                                        Environment.Exit(0);
                                    }
                                    catch (Exception e)
                                    {
                                        Console.Error.WriteLine(e.GetType() + ": " + e.Message);
                                        Environment.Exit(4);
                                    }
                                }
                                else
                                {
                                    Console.Error.WriteLine("This program must run as administrator to restore the global lockscreen.");
                                    Environment.Exit(4);
                                }
                            }
                            break;

                        default:
                            Console.Error.WriteLine("Unknown argument: " + args[i]);
                            Environment.Exit(1);
                            break;
                        }
                    }
                }

                try
                {
                    int downloadCount = 0;
                    int noNewImgCount = 0;

                    do
                    {
                        SpotlightImage[] images = (fromFile != null && (action == "wallpaper" || action == "lockscreen"))
                            ? new[] { new SpotlightImage() } // Skip API request, we'll use a local file
                            : Spotlight.GetImageUrls(maximumRes, portrait);

                        if (images.Length < 1)
                        {
                            Console.Error.WriteLine(Program.Name + " received an empty image set from Spotlight API.");
                            Environment.Exit(2);
                        }

                        SpotlightImage randomImage = images.OrderBy(p => new Guid()).First();

                        if (action == "urls")
                        {
                            if (singleImage)
                            {
                                Console.WriteLine(randomImage.Uri);
                            }
                            else
                            {
                                foreach (SpotlightImage image in images)
                                {
                                    Console.WriteLine(image.Uri);
                                }
                            }
                            Environment.Exit(0);
                        }

                        try
                        {
                            if (singleImage || action == "wallpaper" || action == "lockscreen")
                            {
                                string outputFile = fromFile ?? randomImage.DownloadToFile(outputDir, integrityCheck, metadata, outputName);
                                Console.WriteLine(outputFile);
                                if (action == "wallpaper")
                                {
                                    try
                                    {
                                        Desktop.SetWallpaper(fromFile ?? outputFile);
                                    }
                                    catch (Exception e)
                                    {
                                        Console.Error.WriteLine(e.GetType() + ": " + e.Message);
                                        Environment.Exit(4);
                                    }
                                }
                                else if (action == "lockscreen")
                                {
                                    if (FileSystemAdmin.IsAdmin())
                                    {
                                        try
                                        {
                                            Lockscreen.SetGlobalLockscreen(fromFile ?? outputFile);
                                        }
                                        catch (Exception e)
                                        {
                                            Console.Error.WriteLine(e.GetType() + ": " + e.Message);
                                            Environment.Exit(4);
                                        }
                                    }
                                    else
                                    {
                                        Console.Error.WriteLine("This program must run as administrator to change the global lockscreen.");
                                        Environment.Exit(4);
                                    }
                                }
                                Environment.Exit(0);
                            }

                            downloadCount = 0;

                            foreach (SpotlightImage image in images)
                            {
                                string imagePath = image.GetFilePath(outputDir);
                                if (!File.Exists(imagePath))
                                {
                                    Console.WriteLine(image.DownloadToFile(outputDir, integrityCheck, metadata));
                                    downloadCount++;
                                }
                            }

                            Console.Error.WriteLine("Successfully downloaded: " + downloadCount + " images.");
                            Console.Error.WriteLine("Already downloaded: " + (images.Length - downloadCount) + " images.");

                            if (downloadCount == 0)
                            {
                                noNewImgCount++;
                            }
                            else
                            {
                                noNewImgCount = 0;
                            }
                        }
                        catch (Exception e)
                        {
                            Console.Error.WriteLine(e.GetType() + ": " + e.Message);
                            Environment.Exit(3);
                        }

                        Console.WriteLine(noNewImgCount);

                        //} while (downloadMany && (downloadCount > 0 || noNewImgCount < 10));
                    } while (downloadMany && noNewImgCount < 1000);
                    Environment.Exit(0);
                }
                catch (Exception e)
                {
                    Console.Error.WriteLine(e.GetType() + ": " + e.Message);
                    Environment.Exit(2);
                }
            }

            foreach (string str in new[] {
                " ==== " + Program.Name + " v" + Program.Version + " - By ORelio - Microzoom.fr ====",
                "",
                "Retrieve Windows Spotlight images by requesting the Microsoft Spotlight API.",
                Program.Name + " can also define images as wallpaper and system-wide lockscreen image.",
                "",
                "Usage:",
                "  " + Program.Name + ".exe <action> [arguments]",
                "  Only one action must be provided, as first argument",
                "  Then, provide any number of arguments from the list below.",
                "",
                "Actions:",
                "  urls               Query Spotlight API and print image URLs to standard output",
                "  download           Download all images and print file path to standard output",
                "  wallpaper          Download one random image and define it as wallpaper",
                "  lockscreen         Download one random image and define it as global lockscreen",
                "",
                "Arguments:",
                "  --single           Print only one random url or download only one image as spotlight.jpg",
                "  --many             Try downloading as much images as possible by calling API many times",
                "  --maxres           Force maximum image resolution instead of tailoring to current screen res",
                "  --portrait         Force portrait image instead of autodetecting from current screen res",
                "  --landscape        Force landscape image instead of autodetecting from current screen res",
                "  --outdir <dir>     Set output directory instead of defaulting to working directory",
                "  --outname <name>   Set output file name as <name>.jpg in single image mode, ignored otherwise",
                "  --skip-integrity   Skip integrity check of downloaded files: file size and sha256 hash",
                "  --metadata         Also save image metadata such as title & copyright as <image-name>.txt",
                "  --from-file        Set the specified file as wallpaper/lockscreen instead of downloading",
                "  --from-dir         Set a random image from the specified directory as wallpaper/lockscreen",
                "  --restore          Restore the default lockscreen image, has no effect with other actions",
                "",
                "Exit codes:",
                "  0                  Success",
                "  1                  Invalid arguments",
                "  2                  Spotlight API request failure",
                "  3                  Image download failure or Failed to write image to disk",
                "  4                  Failed to define image as wallpaper or lock screen image"
            })
            {
                Console.Error.WriteLine(str);
            }
            Environment.Exit(1);
        }