コード例 #1
1
ファイル: SUUpdateAlert.cs プロジェクト: klm1/SparkleDotNET
        public SUUpdateAlert(Window window, SUHost host, SUAppcastItem item)
            : base(window)
        {
            Window.TaskbarItemInfo = new System.Windows.Shell.TaskbarItemInfo();
            Window.Closing += WindowShouldClose;
            Window.Icon = host.Icon;
            Window.Topmost = true;

            status = WindowStatus.WaitingForInitialAction;

            mainViewController = new SUUpdateAlertWindowViewController(new SUUpdateAlertWindowView());
            ViewController = mainViewController;

            buttons = new SUUpdateAlertActionButtonsViewController(new SUUpdateAlertActionButtonsView());
            buttons.InstallButton.Click += DownloadButtonClicked;
            buttons.RemindLaterButton.Click += RemindLaterButtonClicked;
            buttons.SkipVersionButton.Click += SkipVersionButtonClicked;

            downloadingViewController = new SUUpdateAlertDownloadProgressViewController(new SUUpdateAlertDownloadProgressView());
            downloadingViewController.CancelButton.Click += CancelDownloadClicked;

            indeterminateViewController = new SUUpdateAlertIndeterminateProgressViewController(new SUUpdateAlertIndeterminateProgressView());
            readyToInstallViewController = new SUUpdateAlertReadyToInstallViewController(new SUUpdateAlertReadyToInstallView());

            readyToInstallViewController.InstallButton.Click += InstallButtonClicked;

            mainViewController.ActionViewController = buttons;
            mainViewController.Host = host;
            mainViewController.Item = item;
        }
コード例 #2
0
        public SUUpdateAlert(Window window, SUHost host, SUAppcastItem item)
            : base(window)
        {
            Window.TaskbarItemInfo = new System.Windows.Shell.TaskbarItemInfo();
            Window.Closing        += WindowShouldClose;
            Window.Icon            = host.Icon;
            Window.Topmost         = true;

            status = WindowStatus.WaitingForInitialAction;

            mainViewController = new SUUpdateAlertWindowViewController(new SUUpdateAlertWindowView());
            ViewController     = mainViewController;

            buttons = new SUUpdateAlertActionButtonsViewController(new SUUpdateAlertActionButtonsView());
            buttons.InstallButton.Click     += DownloadButtonClicked;
            buttons.RemindLaterButton.Click += RemindLaterButtonClicked;
            buttons.SkipVersionButton.Click += SkipVersionButtonClicked;

            downloadingViewController = new SUUpdateAlertDownloadProgressViewController(new SUUpdateAlertDownloadProgressView());
            downloadingViewController.CancelButton.Click += CancelDownloadClicked;

            indeterminateViewController  = new SUUpdateAlertIndeterminateProgressViewController(new SUUpdateAlertIndeterminateProgressView());
            readyToInstallViewController = new SUUpdateAlertReadyToInstallViewController(new SUUpdateAlertReadyToInstallView());

            readyToInstallViewController.InstallButton.Click += InstallButtonClicked;

            mainViewController.ActionViewController = buttons;
            mainViewController.Host = host;
            mainViewController.Item = item;
        }
コード例 #3
0
        public static SUUpdateAlert CreateAlert(SUHost host, SUAppcastItem item)
        {
            SUUpdateAlertWindow window = new SUUpdateAlertWindow();
            SUUpdateAlert       alert  = new SUUpdateAlert(window, host, item);

            return(alert);
        }
コード例 #4
0
        public SUUpdatePermissionPromptViewController(SUHost host)
            : base(new SUUpdatePermissionPromptView())
        {
            Host = host;
                UpdateHeaderDescription.Text = String.Format(SULocalizedStrings.StringForKey("Update Automatically Prompt Header"),
                    Host.Name, SULocalizedStrings.StringForKey("Help"));
                IconView.Source = host.LargeIcon;
                ExtendedInfoContainer.Expanded += ExpandWindow;
                ExtendedInfoContainer.Collapsed += CollapseWindow;
                ExtendedInfoContainer.IsExpanded = false;
                oldHeight = 150;

                string systemInfo = "";

                try {

                    foreach (Dictionary<string, string> item in SUSystemProfiler.SystemProfileForHost(host))
                    {

                        systemInfo = String.Concat(systemInfo, item.ValueForKey(SUConstants.SUProfileItemDisplayKeyKey), ": ",
                            item.ValueForKey(SUConstants.SUProfileItemDisplayValueKey), Environment.NewLine);

                    }

                    InfoBox.Text = systemInfo;

                } catch (Exception e) {

                    if (e is System.Runtime.InteropServices.COMException || e is System.Management.ManagementException)
                        InfoBox.Text = SULocalizedStrings.StringForKey("Profile Generation Error");
                    else
                        throw e;

                }
        }
コード例 #5
0
        public SUUpdatePermissionPromptViewController(SUHost host)
            : base(new SUUpdatePermissionPromptView())
        {
            Host = host;
            UpdateHeaderDescription.Text = String.Format(SULocalizedStrings.StringForKey("Update Automatically Prompt Header"),
                                                         Host.Name, SULocalizedStrings.StringForKey("Help"));
            IconView.Source = host.LargeIcon;
            ExtendedInfoContainer.Expanded  += ExpandWindow;
            ExtendedInfoContainer.Collapsed += CollapseWindow;
            ExtendedInfoContainer.IsExpanded = false;
            oldHeight = 150;

            string systemInfo = "";

            try {
                foreach (Dictionary <string, string> item in SUSystemProfiler.SystemProfileForHost(host))
                {
                    systemInfo = String.Concat(systemInfo, item.ValueForKey(SUConstants.SUProfileItemDisplayKeyKey), ": ",
                                               item.ValueForKey(SUConstants.SUProfileItemDisplayValueKey), Environment.NewLine);
                }

                InfoBox.Text = systemInfo;
            } catch (Exception e) {
                if (e is System.Runtime.InteropServices.COMException || e is System.Management.ManagementException)
                {
                    InfoBox.Text = SULocalizedStrings.StringForKey("Profile Generation Error");
                }
                else
                {
                    throw e;
                }
            }
        }
コード例 #6
0
        public override void CheckForUpdatesAtURLWithHost(string aUrl, SUHost aHost)
        {
            base.CheckForUpdatesAtURLWithHost(aUrl, aHost);

            SUAppcast appcast = new SUAppcast();
            appcast.Delegate = this;
            appcast.UserAgentString = String.Format("{0}/{1} SparkleDotNET", Host.Name, Host.DisplayVersion);
            appcast.FetchAppcastFromURL(new Uri(aUrl));
        }
コード例 #7
0
        public override void CheckForUpdatesAtURLWithHost(string aUrl, SUHost aHost)
        {
            base.CheckForUpdatesAtURLWithHost(aUrl, aHost);

            SUAppcast appcast = new SUAppcast();

            appcast.Delegate        = this;
            appcast.UserAgentString = String.Format("{0}/{1} SparkleDotNET", Host.Name, Host.DisplayVersion);
            appcast.FetchAppcastFromURL(new Uri(aUrl));
        }
        public SUUpdatePermissionPromptWindowController(SUHost host)
            : base(new SUUpdatePermissionPromptWindow())
        {
            Window.Icon = host.Icon;
                Window.Topmost = true;

                viewController = new SUUpdatePermissionPromptViewController(host);
                viewController.CheckAutomaticallyButton.Click += CheckAutomatically;
                viewController.DontCheckButton.Click += DontCheck;

                ViewController = viewController;
                sendDelegateOnWindowClose = true;
        }
コード例 #9
0
        public SUUpdatePermissionPromptWindowController(SUHost host)
            : base(new SUUpdatePermissionPromptWindow())
        {
            Window.Icon    = host.Icon;
            Window.Topmost = true;

            viewController = new SUUpdatePermissionPromptViewController(host);
            viewController.CheckAutomaticallyButton.Click += CheckAutomatically;
            viewController.DontCheckButton.Click          += DontCheck;

            ViewController            = viewController;
            sendDelegateOnWindowClose = true;
        }
コード例 #10
0
        private SUUpdater(KNBundle aBundle)
        {
            KNBundle bundle = KNBundle.BundleWithAssembly(Assembly.GetAssembly(this.GetType()));

            if (aBundle == null)
            {
                aBundle = KNBundle.MainBundle();
            }

            if (sharedUpdaters.ContainsKey(aBundle))
            {
                throw new Exception("Updater for this bundle exists - use SUUpdater.UpdaterForBundle()");
            }

            SUInstaller.AddInstallerForFileType(new SUExecutableInstaller(), ".exe");
            SUInstaller.AddInstallerForFileType(new SUMSIInstaller(), ".msi");

            SUUnarchiver.AddUnarchiverForFileType(new SUZipUnarchiver(), ".zip");
            SUUnarchiver.AddUnarchiverForFileType(new SUExeUnarchiver(), ".exe");
            SUUnarchiver.AddUnarchiverForFileType(new SUExeUnarchiver(), ".msi");

            sharedUpdaters.Add(aBundle, this);
            host = new SUHost(aBundle);

            // Clean out old update files if they exist

            if (host.ObjectForUserDefaultsKey(SUConstants.SUExtractedFilesForCleanupKey) != null)
            {
                string path = (string)host.ObjectForUserDefaultsKey(SUConstants.SUExtractedFilesForCleanupKey);

                try {
                    FileAttributes attr = File.GetAttributes(path);
                    if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
                    {
                        Directory.Delete(path, true);
                    }
                    else
                    {
                        File.Delete(path);
                    }
                } catch {
                } finally {
                    host.SetObjectForUserDefaultsKey(null, SUConstants.SUExtractedFilesForCleanupKey);
                }
            }

            OfferToAutomaticallyUpdateIfAppropriate();
            ScheduleNextUpdateCheck();
        }
コード例 #11
0
        public static ArrayList SystemProfileForHost(SUHost host)
        {
            ArrayList profile = new ArrayList();

            // App name

            profile.Add(DictionaryForProfileItem("appName", SULocalizedStrings.StringForKey("Application Name"), host.Name, host.Name));

            // App version

            profile.Add(DictionaryForProfileItem("appVersion", SULocalizedStrings.StringForKey("Application Version"), host.Version, host.Version));

            // System version

            string version = Environment.OSVersion.ToString();
            profile.Add(DictionaryForProfileItem("osVersion", SULocalizedStrings.StringForKey("OS Version"), version, version));

            //.NET version

            string frameworkVersion = Environment.Version.ToString();
            profile.Add(DictionaryForProfileItem("dotNetVersion", SULocalizedStrings.StringForKey(".NET Version"), frameworkVersion, frameworkVersion));

            // 64-bit?

            if (Environment.Is64BitOperatingSystem) {
                profile.Add(DictionaryForProfileItem("cpu64bit", SULocalizedStrings.StringForKey("CPU is 64-Bit?"), "true", SULocalizedStrings.StringForKey("Yes")));
            } else {
                profile.Add(DictionaryForProfileItem("cpu64bit", SULocalizedStrings.StringForKey("CPU is 64-Bit?"), "false", SULocalizedStrings.StringForKey("No")));
            }

            // CPU Count

            profile.Add(DictionaryForProfileItem("ncpu", SULocalizedStrings.StringForKey("Number of CPUs"), Environment.ProcessorCount.ToString(), Environment.ProcessorCount.ToString()));

            // RAM

            ulong installedMemory = 0;
            MEMORYSTATUSEX memStatus = new MEMORYSTATUSEX();
            if (GlobalMemoryStatusEx(memStatus)) {
                installedMemory = memStatus.ullTotalPhys / 1024 / 1024;
            }

            profile.Add(DictionaryForProfileItem("ramMB", SULocalizedStrings.StringForKey("Memory (MB)"), installedMemory.ToString(), installedMemory.ToString()));

            return profile;
        }
コード例 #12
0
ファイル: SUUpdater.cs プロジェクト: nagyist/SparkleDotNET
        private SUUpdater(KNBundle aBundle)
        {
            KNBundle bundle = KNBundle.BundleWithAssembly(Assembly.GetAssembly(this.GetType()));

            if (aBundle == null) {
                aBundle = KNBundle.MainBundle();
            }

            if (sharedUpdaters.ContainsKey(aBundle)) {
                throw new Exception("Updater for this bundle exists - use SUUpdater.UpdaterForBundle()");
            }

            SUInstaller.AddInstallerForFileType(new SUExecutableInstaller(), ".exe");
            SUInstaller.AddInstallerForFileType(new SUMSIInstaller(), ".msi");

            SUUnarchiver.AddUnarchiverForFileType(new SUZipUnarchiver(), ".zip");
            SUUnarchiver.AddUnarchiverForFileType(new SUExeUnarchiver(), ".exe");
            SUUnarchiver.AddUnarchiverForFileType(new SUExeUnarchiver(), ".msi");

            sharedUpdaters.Add(aBundle, this);
            host = new SUHost(aBundle);

            // Clean out old update files if they exist

            if (host.ObjectForUserDefaultsKey(SUConstants.SUExtractedFilesForCleanupKey) != null) {
                string path = (string)host.ObjectForUserDefaultsKey(SUConstants.SUExtractedFilesForCleanupKey);

                try {

                    FileAttributes attr = File.GetAttributes(path);
                    if ((attr & FileAttributes.Directory) == FileAttributes.Directory) {
                        Directory.Delete(path, true);
                    } else {
                        File.Delete(path);
                    }
                } catch {
                } finally {
                    host.SetObjectForUserDefaultsKey(null, SUConstants.SUExtractedFilesForCleanupKey);
                }
            }

            OfferToAutomaticallyUpdateIfAppropriate();
            ScheduleNextUpdateCheck();
        }
コード例 #13
0
        public SUUpdatePermissionPromptViewController(SUHost host)
            : base(new SUUpdatePermissionPromptView())
        {
            Host = host;
                UpdateHeaderDescription.Text = String.Format(SULocalizedStrings.StringForKey("Update Automatically Prompt Header"),
                    Host.Name, SULocalizedStrings.StringForKey("Help"));
                IconView.Source = host.LargeIcon;
                ExtendedInfoContainer.Expanded += ExpandWindow;
                ExtendedInfoContainer.Collapsed += CollapseWindow;
                ExtendedInfoContainer.IsExpanded = false;
                oldHeight = 150;

                string systemInfo = "";

                foreach (Dictionary<string, string> item in SUSystemProfiler.SystemProfileForHost(Host)) {

                    systemInfo = String.Concat(systemInfo, item.ValueForKey(SUConstants.SUProfileItemDisplayKeyKey), ": ",
                        item.ValueForKey(SUConstants.SUProfileItemDisplayValueKey), Environment.NewLine);

                }

                InfoBox.Text = systemInfo;
        }
コード例 #14
0
 virtual public void CheckForUpdatesAtURLWithHost(string aUrl, SUHost aHost)
 {
     Host       = aHost;
     appcastURL = aUrl;
 }
コード例 #15
0
ファイル: SUUpdateAlert.cs プロジェクト: klm1/SparkleDotNET
 public static SUUpdateAlert CreateAlert(SUHost host, SUAppcastItem item)
 {
     SUUpdateAlertWindow window = new SUUpdateAlertWindow();
     SUUpdateAlert alert = new SUUpdateAlert(window, host, item);
     return alert;
 }
コード例 #16
0
 virtual public void CheckForUpdatesAtURLWithHost(string aUrl, SUHost aHost) {
     Host = aHost;
     appcastURL = aUrl;
 }
コード例 #17
0
        public static List <Dictionary <string, string> > SystemProfileForHost(SUHost host)
        {
            List <Dictionary <string, string> > profile = new List <Dictionary <string, string> >();

            // App name

            profile.Add(DictionaryForProfileItem("appName", SULocalizedStrings.StringForKey("Application Name"), host.Name, host.Name));

            // App version

            profile.Add(DictionaryForProfileItem("appVersion", SULocalizedStrings.StringForKey("Application Version"), host.Version, host.Version));

            // System version

            string version = Environment.OSVersion.ToString();

            profile.Add(DictionaryForProfileItem("osVersion", SULocalizedStrings.StringForKey("OS Version"), version, version));

            // .NET version

            string frameworkVersion = Environment.Version.ToString();

            profile.Add(DictionaryForProfileItem("dotNetVersion", SULocalizedStrings.StringForKey(".NET Version"), frameworkVersion, frameworkVersion));

            // 64-bit?

            if (Helpers.Is64BitOperatingSystem)
            {
                profile.Add(DictionaryForProfileItem("cpu64bit", SULocalizedStrings.StringForKey("CPU is 64-Bit?"), "1", SULocalizedStrings.StringForKey("Yes")));
            }
            else
            {
                profile.Add(DictionaryForProfileItem("cpu64bit", SULocalizedStrings.StringForKey("CPU is 64-Bit?"), "0", SULocalizedStrings.StringForKey("No")));
            }

            // CPU Count

            profile.Add(DictionaryForProfileItem("ncpu", SULocalizedStrings.StringForKey("Number of CPUs"), Environment.ProcessorCount.ToString(), Environment.ProcessorCount.ToString()));

            // CPU Speed

            // Use methods other than System.Management when possible, because WMI is both horrendously slow, and
            // quite prone to deciding to break or completely screw up by itself, it seems.

            string cpuSpeed;

            using (var cpuRegistryKey = Registry.LocalMachine.OpenSubKey(@"HARDWARE\DESCRIPTION\System\CentralProcessor\0", false))
                cpuSpeed = cpuRegistryKey.GetValue("~MHz").ToString();
            if (Helpers.StringIsNullOrWhiteSpace(cpuSpeed))
            {
                using (var mObj = new System.Management.ManagementObject("Win32_Processor.DeviceID='CPU0'"))
                    cpuSpeed = mObj["CurrentClockSpeed"].ToString();
            }

            profile.Add(DictionaryForProfileItem("cpuFreqMHz", SULocalizedStrings.StringForKey("CPU Speed (GHz)"), cpuSpeed.ToString(), (Double.Parse(cpuSpeed) / 1000.0).ToString()));

            // CPU Type

            // A problem with this is that Mac OS X and Windows have different values for this; on Windows this is
            // the processor architecture, and on OS X it is the CPU type.
            // Windows: http://msdn.microsoft.com/en-us/library/aa394373%28VS.85%29.aspx
            // OS X: http://www.opensource.apple.com/source/xnu/xnu-1228.12.14/osfmk/mach/machine.h

            var sysInfo = new NativeMethods.SYSTEM_INFO();

            NativeMethods.GetSystemInfoAbstracted(ref sysInfo);

            int    archSparkle = -1;
            string archDisplay = "Unknown";

            switch (sysInfo.wProcessorArchitecture)
            {
            case 0:
                archSparkle = 7;
                archDisplay = "x86";
                break;

            case 1:
                archSparkle = 8;
                archDisplay = "MIPS";
                break;

            case 2:
                archSparkle = 16;
                archDisplay = "Alpha";
                break;

            case 3:
                archSparkle = 3;
                archDisplay = "PowerPC";
                break;

            case 9:
                archSparkle = 7;
                archDisplay = "x86_64";
                break;
            }

            profile.Add(DictionaryForProfileItem("cputype", SULocalizedStrings.StringForKey("CPU Type"), archSparkle.ToString(), archDisplay));


            // CPU Subtype

            // Until someone wants to write something that will work this out, let's just send the equivalent to
            // the OS X _ALL. Actually, that's probably accurate, since .NET was designed to be portable.

            profile.Add(DictionaryForProfileItem("cpusubtype", SULocalizedStrings.StringForKey("CPU Subtype"), "0", "0"));

            // RAM

            ulong installedMemory = 0;
            var   memStatus       = new NativeMethods.MEMORYSTATUSEX();

            if (NativeMethods.GlobalMemoryStatusEx(memStatus))
            {
                installedMemory = memStatus.ullTotalPhys / 1024 / 1024;
            }

            profile.Add(DictionaryForProfileItem("ramMB", SULocalizedStrings.StringForKey("Memory (MB)"), installedMemory.ToString(), installedMemory.ToString()));

            // User preferred language

            profile.Add(DictionaryForProfileItem("lang", SULocalizedStrings.StringForKey("Preferred Language"), CultureInfo.CurrentCulture.TwoLetterISOLanguageName, CultureInfo.CurrentCulture.TwoLetterISOLanguageName));

            return(profile);
        }
コード例 #18
0
        public static List<Dictionary<string, string>> SystemProfileForHost(SUHost host)
        {
            List<Dictionary<string, string>> profile = new List<Dictionary<string, string>>();

            // App name

            profile.Add(DictionaryForProfileItem("appName", SULocalizedStrings.StringForKey("Application Name"), host.Name, host.Name));

            // App version

            profile.Add(DictionaryForProfileItem("appVersion", SULocalizedStrings.StringForKey("Application Version"), host.Version, host.Version));

            // System version

            string version = Environment.OSVersion.ToString();
            profile.Add(DictionaryForProfileItem("osVersion", SULocalizedStrings.StringForKey("OS Version"), version, version));

            // .NET version

            string frameworkVersion = Environment.Version.ToString();
            profile.Add(DictionaryForProfileItem("dotNetVersion", SULocalizedStrings.StringForKey(".NET Version"), frameworkVersion, frameworkVersion));

            // 64-bit?

            if (Helpers.Is64BitOperatingSystem) {
                profile.Add(DictionaryForProfileItem("cpu64bit", SULocalizedStrings.StringForKey("CPU is 64-Bit?"), "1", SULocalizedStrings.StringForKey("Yes")));
            } else {
                profile.Add(DictionaryForProfileItem("cpu64bit", SULocalizedStrings.StringForKey("CPU is 64-Bit?"), "0", SULocalizedStrings.StringForKey("No")));
            }

            // CPU Count

            profile.Add(DictionaryForProfileItem("ncpu", SULocalizedStrings.StringForKey("Number of CPUs"), Environment.ProcessorCount.ToString(), Environment.ProcessorCount.ToString()));

            // CPU Speed

            // Use methods other than System.Management when possible, because WMI is both horrendously slow, and
            // quite prone to deciding to break or completely screw up by itself, it seems.

            string cpuSpeed;
            using (var cpuRegistryKey = Registry.LocalMachine.OpenSubKey(@"HARDWARE\DESCRIPTION\System\CentralProcessor\0", false))
                cpuSpeed = cpuRegistryKey.GetValue("~MHz").ToString();
            if (Helpers.StringIsNullOrWhiteSpace(cpuSpeed))
                using (var mObj = new System.Management.ManagementObject("Win32_Processor.DeviceID='CPU0'"))
                    cpuSpeed = mObj["CurrentClockSpeed"].ToString();

            profile.Add(DictionaryForProfileItem("cpuFreqMHz", SULocalizedStrings.StringForKey("CPU Speed (GHz)"), cpuSpeed.ToString(), (Double.Parse(cpuSpeed) / 1000.0).ToString()));

            // CPU Type

            // A problem with this is that Mac OS X and Windows have different values for this; on Windows this is
            // the processor architecture, and on OS X it is the CPU type.
            // Windows: http://msdn.microsoft.com/en-us/library/aa394373%28VS.85%29.aspx
            // OS X: http://www.opensource.apple.com/source/xnu/xnu-1228.12.14/osfmk/mach/machine.h

            var sysInfo = new NativeMethods.SYSTEM_INFO();
            NativeMethods.GetSystemInfoAbstracted(ref sysInfo);

            int archSparkle = -1;
            string archDisplay = "Unknown";
            switch (sysInfo.wProcessorArchitecture)
            {
                case 0:
                    archSparkle = 7;
                    archDisplay = "x86";
                    break;
                case 1:
                    archSparkle = 8;
                    archDisplay = "MIPS";
                    break;
                case 2:
                    archSparkle = 16;
                    archDisplay = "Alpha";
                    break;
                case 3:
                    archSparkle = 3;
                    archDisplay = "PowerPC";
                    break;
                case 9:
                    archSparkle = 7;
                    archDisplay = "x86_64";
                    break;
            }

            profile.Add(DictionaryForProfileItem("cputype", SULocalizedStrings.StringForKey("CPU Type"), archSparkle.ToString(), archDisplay));

            // CPU Subtype

            // Until someone wants to write something that will work this out, let's just send the equivalent to
            // the OS X _ALL. Actually, that's probably accurate, since .NET was designed to be portable.

            profile.Add(DictionaryForProfileItem("cpusubtype", SULocalizedStrings.StringForKey("CPU Subtype"), "0", "0"));

            // RAM

            ulong installedMemory = 0;
            var memStatus = new NativeMethods.MEMORYSTATUSEX();
            if (NativeMethods.GlobalMemoryStatusEx(memStatus)) {
                installedMemory = memStatus.ullTotalPhys / 1024 / 1024;
            }

            profile.Add(DictionaryForProfileItem("ramMB", SULocalizedStrings.StringForKey("Memory (MB)"), installedMemory.ToString(), installedMemory.ToString()));

            // User preferred language

            profile.Add(DictionaryForProfileItem("lang", SULocalizedStrings.StringForKey("Preferred Language"), CultureInfo.CurrentCulture.TwoLetterISOLanguageName, CultureInfo.CurrentCulture.TwoLetterISOLanguageName));

            return profile;
        }