├── .gitignore ├── App.xaml ├── App.xaml.cs ├── Brushes.xaml ├── Commands └── MenuItemClickCommand.cs ├── Converters ├── BitmapSource2VisibilityConverter.cs ├── BoolToGridRowConverter.cs ├── MenuWidthToMarginConverter.cs ├── NameToResourceConverter.cs ├── PiToTooltipConverter.cs ├── Stretch2BoolConverter.cs └── TextToBoolConverter.cs ├── DataProviders ├── DriveManager.cs ├── ImageManager.cs ├── ImmersiveApp.cs ├── ImmersiveAppsProvider.cs ├── MfuList.cs ├── NetManager.cs └── PowerItemTree.cs ├── Helpers ├── API.cs ├── Analytics.cs ├── GATracer.cs ├── Log.cs ├── RemovableFileSystemWatcher.cs ├── SettingsManager.cs └── Util.cs ├── Images ├── PayPal.gif ├── Pin.png ├── Power8Logo.design ├── Power8Logo_Red.ico ├── Power8Logo_Red16x16.ico ├── Power8Logo_Red48x48.ico ├── Unpin.png ├── logo_alfa │ ├── Power8Logo7_Blue_alfa.png │ ├── Power8Logo7_Green_alfa.png │ ├── Power8Logo7_Red_alfa.png │ ├── Power8Logo7_alfa.png │ ├── Power8Logo7_marine_alfa.png │ ├── Power8Logo7_violet_alfa.png │ └── Power8Logo7_yellow_alfa.png └── logo_black │ ├── Power8Logo7_Blue.png │ ├── Power8Logo7_Green.png │ ├── Power8Logo7_Red.png │ ├── Power8Logo7_black.png │ ├── Power8Logo7_marine.png │ ├── Power8Logo7_violet.png │ └── Power8Logo7_yellow.png ├── P8Installer ├── P8Installer.aip ├── P8Installer.aiproj └── P8Installer.back.aip ├── Power8-VS2010.sln ├── Power8.csproj ├── Power8.manifest ├── Power8.sln ├── PowerItem.cs ├── Properties ├── AssemblyInfo.cs ├── NoLoc.Designer.cs ├── NoLoc.resx ├── Resources.Designer.cs ├── Resources.ar.resx ├── Resources.cs.resx ├── Resources.de.resx ├── Resources.el.resx ├── Resources.es.resx ├── Resources.fi.resx ├── Resources.fr.resx ├── Resources.hr.resx ├── Resources.hu.resx ├── Resources.it.resx ├── Resources.ko.resx ├── Resources.nl.resx ├── Resources.pt.resx ├── Resources.resx ├── Resources.ro.resx ├── Resources.ru.Designer.cs ├── Resources.ru.resx ├── Resources.sl.resx ├── Resources.sr.resx ├── Resources.sv.Designer.cs ├── Resources.sv.resx ├── Resources.tr.resx ├── Resources.uk.resx ├── Resources.zh-Hans.resx ├── Resources.zh-TW.resx ├── Settings.Designer.cs └── Settings.settings ├── README.md ├── Styles.xaml ├── Views ├── About.xaml ├── About.xaml.cs ├── BtnStck.xaml ├── BtnStck.xaml.cs ├── ComputerList.xaml ├── ComputerList.xaml.cs ├── ConfirmActionWindow.xaml ├── ConfirmActionWindow.xaml.cs ├── DisposableLinkWindow.cs ├── DisposableWindow.cs ├── Donate.xaml ├── Donate.xaml.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── MenuedButton.xaml ├── MenuedButton.xaml.cs ├── RestartExplorer.Designer.cs ├── RestartExplorer.cs ├── SettingsWnd.xaml ├── SettingsWnd.xaml.cs ├── UpdateNotifier.xaml ├── UpdateNotifier.xaml.cs ├── WelcomeArrow.xaml └── WelcomeArrow.xaml.cs └── app.config /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # This .gitignore file was automatically created by Microsoft(R) Visual Studio. 3 | ################################################################################ 4 | 5 | /obj 6 | *.suo 7 | /P8Installer/P8Installer-cache 8 | /P8Installer/P8Installer-SetupFiles 9 | /bin/Debug 10 | /bin/Release 11 | *.user 12 | /.vs 13 | -------------------------------------------------------------------------------- /App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 42 | 43 | 44 | 46 | 48 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Net; 3 | using Power8.Helpers; 4 | using Power8.Views; 5 | using System; 6 | using System.Diagnostics; 7 | using System.IO; 8 | using System.Runtime.InteropServices; 9 | using System.Windows; 10 | using System.Windows.Controls; 11 | using System.Windows.Interop; 12 | #if DEBUG 13 | using System.Runtime.ExceptionServices; 14 | #endif 15 | 16 | 17 | namespace Power8 18 | { 19 | /// 20 | /// Bootstrapper for the application 21 | /// 22 | public partial class App 23 | { 24 | public readonly Process Proc = Process.GetCurrentProcess(); 25 | 26 | /// 27 | /// Application initializer. Performs compatibility check, 28 | /// starts diagnostics if required, works settings around, 29 | /// and initializes the process of generating of internal data structures. 30 | /// 31 | public App() 32 | { 33 | if(Util.OsIs.VistaExact) //If run on shit 34 | { 35 | MessageBox.Show( 36 | Power8.Properties.Resources.Err_VistaDetected, 37 | Power8.Properties.NoLoc.Stg_AppShortName, MessageBoxButton.OK, MessageBoxImage.Error); 38 | Environment.Exit(2); //means: OS not found 39 | } 40 | //Global error mode setter - in 1st place to fix nasty startup error on Win10x86 41 | API.SetErrorMode(API.ErrMode.FailCriticalErrors); 42 | 43 | //Power8s in our session but with different pid 44 | foreach (var p in Process.GetProcessesByName("Power8") 45 | .Where(p => p.SessionId == Proc.SessionId && p.Id != Proc.Id)) 46 | { 47 | p.Kill(); 48 | } 49 | 50 | Util.MainDisp = Dispatcher; //store main thread dispatcher. Widely used in Application. 51 | 52 | #if DEBUG 53 | //System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo("ru"); 54 | 55 | //Error handling and detection 56 | var l = new TextWriterTraceListener(Environment.ExpandEnvironmentVariables(@"%temp%\p8log.txt")); 57 | l.Write("\r\n\r\nPower8 Log opened at " + DateTime.Now + "\r\n\r\n"); 58 | Debug.AutoFlush = true; 59 | Debug.Listeners.Add(l); 60 | #endif 61 | 62 | DispatcherUnhandledException += (sender, e) => Util.DispatchUnhandledException(e.Exception); 63 | AppDomain.CurrentDomain.UnhandledException += HandleUnhandled; 64 | 65 | ServicePointManager.SecurityProtocol |= (SecurityProtocolType) 3840; //Support for TLS 1.1 and TLS 1.2 66 | 67 | var dbRoot = Util.GetSettingsIndependentDbRoot(); 68 | try 69 | { 70 | var ids = Directory.GetFiles(dbRoot, "*" + ClientIDExtension); 71 | string clientId; 72 | if (ids.Length == 0) 73 | { 74 | clientId = Guid.NewGuid().ToString(); 75 | File.Create(dbRoot + "\\" + clientId + ClientIDExtension); 76 | } 77 | else 78 | { 79 | clientId = Path.GetFileNameWithoutExtension(ids[0]); 80 | } 81 | Analytics.Init(TrackID, clientId, Power8.Properties.NoLoc.Stg_AppShortName, 82 | Util.GetAppVersion().ToString()); 83 | } 84 | catch (Exception ex) 85 | { 86 | Log.Raw("Unable to read client ID to init analytics: " + ex); 87 | } 88 | 89 | //Move settings from previous ver 90 | var std = Power8.Properties.Settings.Default; 91 | if (!std.FirstRunDone) 92 | { 93 | try 94 | { 95 | std.Upgrade(); 96 | } 97 | catch (Exception ex) 98 | { 99 | Log.Raw("Unable to upgrade settings: " + ex); 100 | } 101 | std.Save();//FirstRunDone is updated later in Main Window code 102 | Analytics.PostEvent(Analytics.Category.Deploy, std.FirstRunDone ? "Update" : "Fresh", null, 1); 103 | BtnStck.Instanciated += (o, e) => Util.InstanciateClass(t: typeof (Donate)); 104 | } 105 | 106 | //Initialize standard folder icon 107 | ImageManager.GetImageContainerSync(new PowerItem { Argument = dbRoot, IsFolder = true }, API.Shgfi.SMALLICON); 108 | 109 | //Build tree 110 | Util.ForkPool(PowerItemTree.InitTree, "InitTree"); 111 | 112 | //react on DwmCompositionChanged event 113 | ComponentDispatcher.ThreadFilterMessage += WndProc; 114 | } 115 | /// 116 | /// Gets the running instance of App 117 | /// 118 | public static new App Current 119 | { 120 | get { return (App) Application.Current; } 121 | } 122 | 123 | private const string ClientIDExtension = ".clientid"; 124 | private const string TrackID = "UA-30314159-2"; 125 | 126 | /// 127 | /// Handles Unhandled appdomain exception and calls the code to write that down everywhere. 128 | /// Undr DEBUG it also catches uncatchable exceptions 129 | /// 130 | #if DEBUG 131 | [HandleProcessCorruptedStateExceptions] 132 | #endif 133 | public void HandleUnhandled(object sender, UnhandledExceptionEventArgs e) 134 | { 135 | Util.DispatchUnhandledException(e.ExceptionObject as Exception); 136 | } 137 | 138 | #region DWM CompositionChanged event 139 | 140 | // ReSharper disable RedundantAssignment 141 | /// 142 | /// App WndProc. Filter. Used only to hande DWMCOMPOSITIONCHANGED event. 143 | /// 144 | /// Structure with message, lparame, wparam, etc. 145 | /// IntPtr wrapped to bool as 1/0. Retval of WndProc. 146 | private void WndProc(ref MSG msg, ref bool handled) 147 | { 148 | if (msg.message == (int)API.WM.DWMCOMPOSITIONCHANGED) 149 | { 150 | var h = DwmCompositionChanged; 151 | if (h != null) 152 | h(this, null); 153 | handled = true; 154 | return; 155 | } 156 | handled = false; 157 | } 158 | // ReSharper restore RedundantAssignment 159 | /// 160 | /// WM_DWMCOMPOSITIONCHANGED converted to event model. e is always null. 161 | /// Sender is this App. 162 | /// 163 | public event EventHandler DwmCompositionChanged; 164 | 165 | #endregion 166 | 167 | //App stores global context menu as resource. 168 | #region Global Context menu 169 | 170 | /// 171 | /// Handles Run/Run As/Open/Open all users folder commands 172 | /// 173 | private void RunRunasOpenOpencommonClick(object sender, RoutedEventArgs e) 174 | { 175 | try 176 | { 177 | var n = ((MenuItem) sender).Name; 178 | if (n == "AppRun" || n == "AppOpenFolder") //TODO: maybe compare byref to menuitems? 179 | Util.ExtractRelatedPowerItem(e).Invoke(); 180 | else //Open common folder is also handled via "RunAsAdmin" command. See below. 181 | Util.ExtractRelatedPowerItem(e).InvokeVerb(API.SEVerbs.RunAsAdmin); 182 | //This was done to simplify the implementation. Passing this command switches 183 | //the flag in ResolveItem() that exchanges discovered Common item (if exists) 184 | //with User one. This relates to Start menu _folders_ explicitly and only. 185 | //Along with that, this flag is passed to process start info, regardless of PowerItem 186 | //type (file/folder/link...). That type, however, influences the enabled state of 187 | //menu items, so you shouldn't be able to do something wrong. 188 | } 189 | catch (Exception ex) 190 | { 191 | Util.DispatchCaughtException(ex); 192 | } 193 | } 194 | /// 195 | /// Displays properties of a clicked object. Depending on which item 196 | /// was clicked, the automatic link resolution may take place. 197 | /// 198 | private void ShowPropertiesClick(object sender, RoutedEventArgs e) 199 | { 200 | try 201 | { 202 | var info = new API.ShellExecuteInfo 203 | { 204 | fMask = //need all them for Properties verb 205 | API.SEIFlags.SEE_MASK_INVOKEIDLIST | API.SEIFlags.SEE_MASK_NOCLOSEPROCESS | 206 | API.SEIFlags.SEE_MASK_FLAG_NO_UI | API.SEIFlags.SEE_MASK_NOASYNC, 207 | hwnd = BtnStck.Instance.GetHandle(), //otherwise will be in background 208 | nShow = API.SWCommands.HIDE, //hides some other window, kind of worker one 209 | lpVerb = API.SEVerbs.Properties, 210 | lpFile = Args4PropsAndCont(Util.ExtractRelatedPowerItem(e), ((MenuItem)sender).Name) 211 | }; 212 | var executer = new Util.ShellExecuteHelper(info); //Needed to be executed on STA htread 213 | if (!executer.ShellExecuteOnSTAThread()) 214 | throw new ExternalException(string.Format( 215 | Power8.Properties.Resources.Err_ShellExecExErrorFormatString, executer.ErrorCode, executer.ErrorText)); 216 | } 217 | catch (Exception ex) 218 | { 219 | Util.DispatchCaughtException(ex); 220 | } 221 | } 222 | /// 223 | /// Shows source PowerItem in a folder 224 | /// 225 | private void OpenContainerClick(object sender, RoutedEventArgs e) 226 | { 227 | try 228 | { 229 | Util.StartExplorerSelect(Args4PropsAndCont(Util.ExtractRelatedPowerItem(e), ((MenuItem) sender).Name)); 230 | } 231 | catch (Exception ex) 232 | { 233 | Util.DispatchCaughtException(ex); 234 | } 235 | } 236 | /// 237 | /// Handles click on "Remove item". Adds an exclusion to exclusions list. 238 | /// 239 | private void RemoveItemClick(object sender, RoutedEventArgs e) 240 | { 241 | MfuList.AddExclusion(Util.ExtractRelatedPowerItem(e)); 242 | } 243 | /// 244 | /// Handles click on "Add item to custom list". Adds an item to user's custom MFU list. 245 | /// 246 | private void IncludeCustom(object sender, RoutedEventArgs e) 247 | { 248 | MfuList.Add2Custom(Util.ExtractRelatedPowerItem(e)); 249 | } 250 | /// 251 | /// Handles click on "Remove item from custom list". Removes an item to user's custom MFU list. 252 | /// 253 | private void ExcludeCustom(object sender, RoutedEventArgs e) 254 | { 255 | MfuList.RemoveCustom(Util.ExtractRelatedPowerItem(e)); 256 | } 257 | /// 258 | /// Returns string, of a Path kind, that can be passed to a system, and will 259 | /// represent the passed PowerItem. Depending on Caller Name, may invoke 260 | /// automatic Link resolution for Link PowerItems. "Denamespaces" the 261 | /// passed ControlPanel item returning open command for it. 262 | /// 263 | /// The PowerItem which has to be located/properties for 264 | /// which have to be shown. 265 | /// String, the name of clicked menu item, hendler 266 | /// of which is calling this method. Recognizes "AppOpenTargetContainer" and 267 | /// "AppShowTargetProperties". 268 | /// Path to binary FS object that represents the passed PowerItem or 269 | /// the target of its link. 270 | private static string Args4PropsAndCont(PowerItem item, string callerName) 271 | { 272 | string arg = null; 273 | if (item.IsControlPanelChildItem) 274 | { 275 | var executor = Util.GetOpenCommandForClass(item.Argument); 276 | if (executor != null && File.Exists(executor.Item1)) 277 | arg = executor.Item1; 278 | } 279 | if (arg == null) 280 | arg = PowerItemTree.GetResolvedArgument(item); 281 | if (item.IsLink && (callerName == "AppOpenTargetContainer" 282 | || callerName == "AppShowTargetProperties")) 283 | arg = item.ResolvedLink; 284 | return arg; 285 | } 286 | /// 287 | /// Gets or sets Data Context for the whole menu. MUST be called in ALL 288 | /// ContextMenuOpening event handlers with something like: 289 | /// App.Current.MDC = Util.ExtractRelatedPowerItem(e); 290 | /// 291 | public object MenuDataContext 292 | { 293 | get { return ((ContextMenu) Resources["fsMenuItemsContextMenu"]).DataContext; } 294 | set { ((ContextMenu) Resources["fsMenuItemsContextMenu"]).DataContext = value; } 295 | } 296 | 297 | #endregion 298 | 299 | } 300 | } 301 | -------------------------------------------------------------------------------- /Brushes.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /Commands/MenuItemClickCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Input; 3 | using Power8.Properties; 4 | using Power8.Views; 5 | 6 | namespace Power8.Commands 7 | { 8 | /// 9 | /// Standard PowerItem invoker, used thoughout all the menus 10 | /// (not the context menus though). Parameter should be bound to data item. 11 | /// 12 | public class MenuItemClickCommand : ICommand 13 | { 14 | public void Execute(object parameter) 15 | { 16 | var powerItem = parameter as PowerItem; 17 | try 18 | { 19 | if (powerItem == null) 20 | throw new Exception(Resources.Err_NoPiExtracted); 21 | powerItem.Invoke(); 22 | } 23 | catch (Exception ex) 24 | { 25 | Util.DispatchCaughtException(ex); 26 | } 27 | BtnStck.Instance.Hide(); 28 | } 29 | 30 | public bool CanExecute(object parameter) 31 | { 32 | return true; 33 | } 34 | #pragma warning disable 0067 //Unused event 35 | public event EventHandler CanExecuteChanged; 36 | #pragma warning restore 0067 37 | } 38 | } -------------------------------------------------------------------------------- /Converters/BitmapSource2VisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Globalization; 4 | using System.Windows; 5 | using System.Windows.Data; 6 | using System.Windows.Media.Imaging; 7 | 8 | namespace Power8.Converters 9 | { 10 | /// 11 | /// This class is used to switch visibility of Main Start Button grids On and Off. 12 | /// It behaves depending on the fact is the value null, and what parameter is passed. 13 | /// 14 | [ValueConversion(typeof(BitmapSource), typeof(Visibility))] 15 | [TypeConverter(typeof(BitmapSource))] 16 | class BitmapSource2VisibilityConverter : IValueConverter 17 | { 18 | /// 19 | /// Converts the fact of value existence and parameter into visibility 20 | /// 21 | /// Something or null. Treat null as false. 22 | /// Not used 23 | /// String, "true" or something else, e.g. "false". The "true" 24 | /// parameter preserves the conversion logic straightforward (needed only for one UI element) 25 | /// and other ones invert it. 26 | /// Not used 27 | /// When using normal logic, returns Visibility.Hidden when value is null 28 | /// and Visibility.Visible otherwise. Inverts tre return pair for the inverted 29 | /// logic. 30 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 31 | { 32 | if (((string)parameter) == "true") 33 | return value == null ? Visibility.Hidden : Visibility.Visible; 34 | return value == null ? Visibility.Visible : Visibility.Hidden; 35 | } 36 | 37 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 38 | { 39 | throw new NotImplementedException(); 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /Converters/BoolToGridRowConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Globalization; 4 | using System.Windows.Data; 5 | 6 | namespace Power8.Converters 7 | { 8 | [ValueConversion(typeof(bool), typeof(int))] 9 | [TypeConverter(typeof(bool))] 10 | class BoolToGridRowConverter : IValueConverter 11 | { 12 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 13 | { 14 | var v = (bool) value; //true means window is above middle of the screen 15 | var p = bool.Parse(((string)parameter) ?? "false"); //true means start menu 16 | return v ^ p ? 2 : 0; 17 | } 18 | 19 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 20 | { 21 | throw new NotImplementedException(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Converters/MenuWidthToMarginConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Globalization; 4 | using System.Windows; 5 | using System.Windows.Data; 6 | using Power8.Helpers; 7 | 8 | namespace Power8.Converters 9 | { 10 | /// 11 | /// Reimplement system menu style together with control template is too complex task. 12 | /// The data templates were the solution to get rid of Image generator. 13 | /// On the other hand, all data template stuff goes to Content property of MenuItem. 14 | /// So we need to shift data to the left to show Icon properly. Here comes the converter. 15 | /// One way converter. No data/parameters are considered. Returns Thickness shift for 16 | /// current OS. 17 | /// 18 | [ValueConversion(typeof(double), typeof(Thickness))] 19 | [TypeConverter(typeof(double))] 20 | class MenuWidthToMarginConverter : IValueConverter 21 | { 22 | /// 23 | /// Predefined shift values. W8RP hack is because templates and styles are 24 | /// treated in different way on W8. 25 | /// 26 | private static readonly Thickness Classic = new Thickness(-14, 2, 0, 2), 27 | Regular = new Thickness(-30, 0, 0, 0), 28 | W8RPMenuHack = new Thickness(-42, 0, 0, 0); 29 | 30 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 31 | { 32 | var dbl = (int) SystemParameters.MenuWidth; 33 | if (dbl == 18 /*XP/7 Classic*/ || //following is the definition of HighContrast on 8 34 | (Util.OsIs.EightOrMore && !API.DwmIsCompositionEnabled())) 35 | { 36 | return Classic; 37 | } 38 | if (dbl == 19) //Aero/7 basic/XP theme 39 | { 40 | return Util.OsIs.EightRpOrMore ? W8RPMenuHack : Regular; 41 | } 42 | Log.Raw("dbl=" + dbl); 43 | return new Thickness(0, 0, 0, 0); 44 | } 45 | 46 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 47 | { 48 | throw new NotImplementedException(); 49 | } 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /Converters/NameToResourceConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Globalization; 4 | using System.Windows.Data; 5 | 6 | namespace Power8.Converters 7 | { 8 | /// 9 | /// There's no easy way to have localization in XAML. MS suggests to use additional proxy class 10 | /// with a number of properties. I dislike this way, so let's just use a converter that is able 11 | /// to find localized content based on element's name (by default) or any other stuff. 12 | /// One way converter. Data: string (usually name of element). Returns (CR_+ data) resource. 13 | /// 14 | [ValueConversion(typeof(string), typeof(string))] 15 | [TypeConverter(typeof(string))] 16 | class NameToResourceConverter:IValueConverter 17 | { 18 | /// 19 | /// Converts the control name given into a localized control text. 20 | /// 21 | /// String, the name of control. "CR_" is added to it and is searched in resources. 22 | /// Not used 23 | /// Not used 24 | /// Not used 25 | /// String to be put into control Content or Text or similar property 26 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 27 | { 28 | return Properties.Resources.ResourceManager.GetString("CR_" + (string) value); 29 | } 30 | 31 | /// Shortcut to be used from the code 32 | /// String, the name of control. "CR_" is added to it and is searched in resources. 33 | /// String to be put into control Content or Text or similar property 34 | public string Convert(string controlName) 35 | { 36 | return (string) Convert(controlName, null, null, null); 37 | } 38 | 39 | /// Not implemented 40 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 41 | { 42 | throw new NotImplementedException(); 43 | } 44 | 45 | /// 46 | /// Static instance to be used from code-behind 47 | /// 48 | public static NameToResourceConverter Instance = new NameToResourceConverter(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Converters/PiToTooltipConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Globalization; 4 | using System.IO; 5 | using System.Windows.Data; 6 | using Power8.Properties; 7 | 8 | namespace Power8.Converters 9 | { 10 | /// 11 | /// This converter tries to get tooltip fo PowerItem passed in various ways. In general, 12 | /// it is the resolved argument of PowerItem, but other options available as well. 13 | /// One-way converter. Data: PowerItem. Returns: the descriptive tooltip. 14 | /// 2nd option: when "pin" is passed as parameter, returns pinned/unpinned string 15 | /// for boolean passed as data item. 16 | /// 17 | [ValueConversion(typeof(PowerItem), typeof(string))] 18 | [TypeConverter(typeof(PowerItem))] 19 | class PiToTooltipConverter : IValueConverter 20 | { 21 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 22 | { 23 | if (parameter != null && (string)parameter == "pin") 24 | return (bool?) value == true ? Resources.Str_Unpin : Resources.Str_Pin; 25 | var pi = value as PowerItem; 26 | if (pi == null) 27 | return Resources.Err_CantGetTooltip; 28 | if (!pi.IsNotPureControlPanelFlowItem) 29 | return Resources.Str_CplElement; 30 | if (pi.IsSpecialObject) 31 | { 32 | var cmd = Util.GetOpenCommandForClass(pi.Argument); 33 | return cmd == null ? pi.FriendlyName + GetSuffixForSpecialObject(pi) : cmd.Item1; 34 | } 35 | try 36 | { 37 | return PowerItemTree.GetResolvedArgument(pi); 38 | } 39 | catch (IOException) 40 | { 41 | return Resources.Err_CantGetTooltip; 42 | } 43 | } 44 | 45 | private static string GetSuffixForSpecialObject(PowerItem item) 46 | { 47 | if (item.IsLibrary) return Resources.Str_Library; 48 | if (item.SpecialFolderId == API.Csidl.POWER8IMMERSIVE) return " (" + item.Argument + ")"; 49 | return null; 50 | } 51 | 52 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 53 | { 54 | throw new NotImplementedException(); 55 | } 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /Converters/Stretch2BoolConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Globalization; 4 | using System.Windows.Data; 5 | using System.Windows.Media; 6 | 7 | namespace Power8.Converters 8 | { 9 | /// 10 | /// This class is used to switch UseLayoutRounding on Image of MainButton 11 | /// to True when "No scale" chosen by user in app settings. This makes picture sharper 12 | /// but makes no sense when applied to scaled image. 13 | /// 14 | [ValueConversion(typeof(Stretch), typeof(bool))] 15 | [TypeConverter(typeof(Stretch))] 16 | class Stretch2BoolConverter : IValueConverter 17 | { 18 | /// 19 | /// Returns true when Stretch.None is passed. 20 | /// 21 | /// System.Windows.Media.Stretch of image chosen. 22 | /// Not used 23 | /// Not used 24 | /// Not used 25 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 26 | { 27 | return ((Stretch) value) == Stretch.None; 28 | } 29 | 30 | /// 31 | /// Not implemented 32 | /// 33 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 34 | { 35 | throw new NotImplementedException(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Converters/TextToBoolConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Globalization; 4 | using System.Windows.Data; 5 | 6 | namespace Power8.Converters 7 | { 8 | /// 9 | /// This converter returns !String.IsNullOrWhiteSpace(of value passed) 10 | /// Used to dynamically enabled/disable UI elements in case they're logically tied to 11 | /// some textual field 12 | /// 13 | [ValueConversion(typeof(String), typeof(Boolean))] 14 | [TypeConverter(typeof(String))] 15 | class TextToBoolConverter : IValueConverter 16 | { 17 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 18 | { 19 | return !String.IsNullOrWhiteSpace((string)value); 20 | } 21 | 22 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 23 | { 24 | throw new NotImplementedException(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /DataProviders/ImageManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Concurrent; 4 | using System.IO; 5 | using System.Runtime.InteropServices; 6 | using System.Threading; 7 | using System.Windows.Interop; 8 | using System.Windows.Media; 9 | using System.Windows.Media.Imaging; 10 | using Power8.Helpers; 11 | 12 | namespace Power8 13 | { 14 | /// 15 | /// Maintains cached lists of icons, resolves icons from resources and so on... 16 | /// 17 | public static class ImageManager 18 | { 19 | //Image cache 20 | private static readonly Hashtable Cache = new Hashtable(); 21 | //Image processing queue 22 | private static readonly ConcurrentQueue> ImageQueue = 23 | new ConcurrentQueue>(); 24 | 25 | static ImageManager() 26 | { 27 | Util.ForkStart(ImageProcessor, "Image processsor"); 28 | } 29 | 30 | private static void ImageProcessor() 31 | { 32 | begin: 33 | 34 | while (ImageQueue.Count > 0) 35 | { 36 | Tuple e; 37 | if (ImageQueue.TryDequeue(out e)) 38 | { 39 | var asyncContainer = GetImageContainerSync(e.Item1, e.Item2); 40 | Util.Send(() => e.Item1.Icon = asyncContainer); 41 | } 42 | else 43 | { 44 | break; 45 | } 46 | } 47 | 48 | if (!Util.MainDisp.HasShutdownStarted) 49 | { 50 | Thread.Sleep(333); 51 | goto begin; //just don't want unneeded code nesting here, anyway IL will be same. 52 | } 53 | } 54 | 55 | /// 56 | /// Gets a string that represents a kind of tag for icon for PowerItem passed 57 | /// 58 | /// PowerItem which we need icon for 59 | /// Resolved argument for item. 60 | private static string GetObjectDescriptor(PowerItem item, string resolved) 61 | { 62 | if (item.IsFolder || item.IsSpecialObject) 63 | return item.NonCachedIcon ? resolved : "*"; 64 | var rl = resolved.ToLower(); 65 | return rl.EndsWith(".lnk") 66 | || rl.EndsWith(".exe") 67 | || rl.EndsWith(".cpl") 68 | ? resolved : Path.GetExtension(resolved); 69 | } 70 | 71 | /// 72 | /// Starts asynchronous extraction of ImageContainer for PowerItem 73 | /// 74 | /// PowerItem we need icon extracted for 75 | /// type of icon needed - small or large 76 | /// Always null 77 | public static ImageContainer GetImageContainer(PowerItem item, API.Shgfi iconNeeded) 78 | { 79 | ImageQueue.Enqueue(new Tuple(item, iconNeeded)); 80 | return null; 81 | } 82 | 83 | /// 84 | /// Synchronous getter of an icon for PowerItem 85 | /// 86 | /// PowerItem we need icon extracted for 87 | /// type of icon needed - small or large 88 | /// ImageContainer with ImageSources extracted. Can be null. 89 | public static ImageContainer GetImageContainerSync(PowerItem item, API.Shgfi iconNeeded) 90 | { 91 | Log.Raw("begin>>>>>>>>>>>>>>>", item.FriendlyName); 92 | //Checking if there's cached ImageContainer 93 | string resolvedArg, descr; 94 | try 95 | { 96 | resolvedArg = PowerItemTree.GetResolvedArgument(item); 97 | descr = GetObjectDescriptor(item, resolvedArg); 98 | } 99 | catch (IOException) 100 | { 101 | return null; 102 | } 103 | lock (Cache) 104 | { 105 | var container = (ImageContainer)(Cache.ContainsKey(descr) ? Cache[descr] : null); 106 | Log.Fmt("arg<={0}, descr<={1}, container<={2}", resolvedArg, descr, 107 | (container != null ? "not " : "") + "null"); 108 | if (container == null) //No cached instance 109 | { 110 | container = new ImageContainer(resolvedArg, descr, item.SpecialFolderId); 111 | Cache.Add(descr, container); 112 | if (iconNeeded == API.Shgfi.SMALLICON) 113 | container.ExtractSmall(); 114 | else 115 | container.ExtractLarge(); 116 | } 117 | #if DEBUG 118 | Log.Raw("end<<<<<<<<<<<<<<", item.FriendlyName); 119 | #endif 120 | return container; 121 | } 122 | } 123 | //todo: change description 124 | /// 125 | /// Returns ImageContainer for hIcon provided 126 | /// 127 | /// Object description, tag, under which the container will be stored in cache 128 | /// HICON you obtained after some unmanaged interactions. DestroyIcon() is NOT being 129 | /// called automatically 130 | /// ImageContainer with ImageSource`s for the given hIcon 131 | public static ImageContainer GetImageContainerForIconSync(string description, IntPtr unmanagedIcon) 132 | { 133 | Log.Raw("Wrapping HICON " + unmanagedIcon, description); 134 | lock (Cache) 135 | { 136 | if (Cache.ContainsKey(description)) 137 | return (ImageContainer)Cache[description]; 138 | var container = unmanagedIcon == IntPtr.Zero 139 | ? new ImageContainer(description) 140 | : new ImageContainer(unmanagedIcon); 141 | Cache.Add(description, container); 142 | return container; 143 | } 144 | } 145 | 146 | 147 | /// 148 | /// Holds the cached instance of bitmap sources for big and large icons to be displayed. 149 | /// Can automatically extract icons from the file or special object given. 150 | /// 151 | public class ImageContainer 152 | { 153 | // ReSharper disable NotAccessedField.Local 154 | private readonly string _objectDescriptor; //needed for debug purposes 155 | // ReSharper restore NotAccessedField.Local 156 | private readonly string _initialObject; //Path to file or special object 157 | private readonly API.Csidl _id; //SpecialFolderId from source PowerItem, if any 158 | private ImageSource _smallBitmap, _largeBitmap; 159 | private bool _smallExtracted, _largeExtracted; 160 | private Brush _background = Brushes.Transparent, _foreground = Brushes.Black; 161 | 162 | /// 163 | /// Gets 16x16 BitmapSource-representation of target icon 164 | /// 165 | public ImageSource SmallBitmap 166 | { 167 | get 168 | { 169 | if (!_smallExtracted) 170 | ExtractSmall(); 171 | return _smallBitmap; 172 | } 173 | private set { _smallBitmap = value; } 174 | } 175 | /// 176 | /// Gets 32x32 BitmapSource-representation of target icon 177 | /// 178 | public ImageSource LargeBitmap 179 | { 180 | get 181 | { 182 | if (!_largeExtracted) 183 | ExtractLarge(); 184 | return _largeBitmap; 185 | } 186 | private set { _largeBitmap = value; } 187 | } 188 | 189 | /// 190 | /// Constructs the instance of ImageContainer from data from PowerItem 191 | /// 192 | /// Path to file or special object 193 | /// Tag that will be set in cache for this ImageContainer. Used for debugging. 194 | /// SpecialFolderId from source PowerItem 195 | public ImageContainer(string objectToGetIcons, string typeDescriptor, API.Csidl specialId) 196 | { 197 | _initialObject = objectToGetIcons; 198 | _objectDescriptor = typeDescriptor; 199 | _id = specialId; 200 | } 201 | /// 202 | /// Constructs the instance of ImageContainer from the HICON extracted already 203 | /// 204 | /// HICON you have already extracted 205 | public ImageContainer(IntPtr unmanagedIcon) 206 | { 207 | SmallBitmap = ExtractInternal(unmanagedIcon); 208 | LargeBitmap = SmallBitmap; 209 | } 210 | /// 211 | /// Constructs the instance of ImageContainer for existing image file 212 | /// 213 | /// path to image file 214 | public ImageContainer(string imagePath) 215 | { 216 | SmallBitmap = ExtractInternal(imagePath); 217 | LargeBitmap = SmallBitmap; 218 | } 219 | 220 | /// 221 | /// Extracts 16*16 icon when ImageContainer is constructed with PowerItem data 222 | /// 223 | public void ExtractSmall() 224 | { 225 | if (_smallBitmap != null) 226 | return; 227 | var smallIconHandle = GetUnmanagedIcon(API.Shgfi.SMALLICON); 228 | if (smallIconHandle != IntPtr.Zero) 229 | { 230 | SmallBitmap = ExtractInternal(smallIconHandle); 231 | SmallBitmap.Freeze(); 232 | Util.PostBackgroundIconDestroy(smallIconHandle); 233 | } 234 | #if DEBUG 235 | else 236 | { 237 | Log.Raw("FAILED with code " + Marshal.GetLastWin32Error(), _initialObject); 238 | } 239 | #endif 240 | _smallExtracted = true; 241 | } 242 | /// 243 | /// Extracts 32*32 icon when ImageContainer is constructed with PowerItem data 244 | /// 245 | public void ExtractLarge() 246 | { 247 | if(_largeBitmap != null) 248 | return; 249 | var largeIconHandle = GetUnmanagedIcon(API.Shgfi.LARGEICON); 250 | if (largeIconHandle != IntPtr.Zero) 251 | { 252 | LargeBitmap = ExtractInternal(largeIconHandle); 253 | LargeBitmap.Freeze(); 254 | Util.PostBackgroundIconDestroy(largeIconHandle); 255 | } 256 | #if DEBUG 257 | else 258 | { 259 | Log.Raw("FAILED with code " + Marshal.GetLastWin32Error(), _initialObject); 260 | } 261 | #endif 262 | _largeExtracted = true; 263 | } 264 | 265 | /// 266 | /// Converts HICON to BitmapSource, without calling of DestroyIcon() 267 | /// 268 | /// HICON that is already extracted 269 | private static BitmapSource ExtractInternal(IntPtr handle) 270 | { 271 | var bs = Imaging.CreateBitmapSourceFromHIcon(handle, System.Windows.Int32Rect.Empty, 272 | BitmapSizeOptions.FromEmptyOptions()); 273 | bs.Freeze(); 274 | return bs; 275 | } 276 | 277 | /// 278 | /// Returns BitmapSource for image file 279 | /// 280 | /// path to image file 281 | private static BitmapSource ExtractInternal(string imagePath) 282 | { 283 | var bs = new BitmapImage(new Uri(imagePath)); 284 | bs.Freeze(); 285 | return bs; 286 | } 287 | /// 288 | /// Returns HICON of provided size (or of default size if requested one isn't available) 289 | /// 290 | /// 291 | private IntPtr GetUnmanagedIcon(API.Shgfi iconType) 292 | { 293 | Log.Raw("begin", _initialObject); 294 | //Way 1, straightforward: "Hey shell, give me an icon for that file!" 295 | var shinfo = new API.ShfileinfoW(); 296 | var zeroFails = API.SHGetFileInfo(_initialObject, 0, ref shinfo, (uint) Marshal.SizeOf(shinfo), API.Shgfi.ICON | iconType); 297 | Log.Raw("ShGetFileInfo returned " + zeroFails); 298 | if (zeroFails == IntPtr.Zero) //lot of stuff will work via this 299 | { 300 | //Shell failed 301 | //Way 2: way around: "Hey registry, and how should display the stuff of a kind?" 302 | var temp = Util.GetDefaultIconResourceIdForClass(_initialObject); 303 | Log.Raw("GetDefaultIconResourceIdForClass returned " + (temp ?? "NULL!!")); 304 | if (!string.IsNullOrEmpty(temp)) 305 | { 306 | zeroFails = Util.ResolveIconicResource(temp); 307 | Log.Raw("ResolveIconicResource returned " + zeroFails); 308 | } 309 | if(zeroFails != IntPtr.Zero)//ResolveIconicResource() succeeded and zeroFails contains required handle 310 | { 311 | shinfo.hIcon = zeroFails; 312 | } 313 | else if (_id != API.Csidl.INVALID)//For PowerItems initialized without argument but with folderId 314 | {//No icon, or Registry doesn't know 315 | //Way 3, cumbersome: "Hey shell, I know that stuff means something for ya. Give me the icon for the thing this staff means!" 316 | var ppIdl = IntPtr.Zero; 317 | var hRes = API.SHGetSpecialFolderLocation(IntPtr.Zero, _id, ref ppIdl); //I know, obsolete, but works ;) 318 | Log.Fmt("SHGetSp.F.Loc. for id<={0} returned result code {1}", _id, hRes); 319 | zeroFails = (hRes != 0 320 | ? IntPtr.Zero 321 | : API.SHGetFileInfo(ppIdl, 0, ref shinfo, (uint) Marshal.SizeOf(shinfo), 322 | API.Shgfi.ICON | API.Shgfi.PIDL | API.Shgfi.USEFILEATTRIBUTES | iconType)); 323 | Marshal.FreeCoTaskMem(ppIdl); 324 | Log.Raw("ShGetFileInfo (2p) returned " + zeroFails); 325 | } 326 | } 327 | Log.Fmt("end<<<<<, zf={0}, hi={1}", zeroFails, shinfo.hIcon); 328 | return zeroFails == IntPtr.Zero || shinfo.hIcon == IntPtr.Zero ? IntPtr.Zero : shinfo.hIcon; 329 | } 330 | 331 | public Brush Background 332 | { 333 | get { return _background; } 334 | set { _background = value; } 335 | } 336 | 337 | public Brush Foreground 338 | { 339 | get { return _foreground; } 340 | set { _foreground = value; } 341 | } 342 | } 343 | } 344 | } 345 | -------------------------------------------------------------------------------- /DataProviders/ImmersiveApp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Media; 5 | 6 | namespace Power8.DataProviders 7 | { 8 | public class ImmersiveApp 9 | { 10 | public string ApplicationCompany { get; set; } 11 | public string ApplicationDescription { get; set; } 12 | //---- 13 | public string ApplicationName { get; set; } 14 | public string ApplicationDisplayName { get; set; } 15 | 16 | public string DisplayName 17 | { 18 | get { return string.IsNullOrWhiteSpace(ApplicationDisplayName) ? ApplicationName : ApplicationDisplayName; } 19 | } 20 | 21 | public string AppUserModelID { get; set; } 22 | public string PackageId { get; set; } 23 | //------ 24 | public string ApplicationPath { get; set; } 25 | public string File { get; set; } 26 | //------ 27 | public string Logo 28 | { 29 | get { return Logos.Count > 0 ? Logos.First().Value : null; } 30 | } 31 | public Dictionary Logos { get; set; } 32 | public Color Background { get; set; } 33 | public Color Foreground { get; set; } 34 | public Brush BackgroundBrush { get { return new SolidColorBrush(Background); } } 35 | public Brush ForegroundBrush { get { return new SolidColorBrush(Foreground); } } 36 | public string DisplayState { get; set; } 37 | 38 | private readonly string[] _blackList = { "Windows.ImmersiveControlPanel", "Microsoft.Windows.Cortana", "BrowserChoice" }; 39 | public bool IsSystemApp() 40 | { 41 | return DisplayState == "none" || _blackList.Any(bl => PackageId.StartsWith(bl, StringComparison.OrdinalIgnoreCase)); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /DataProviders/NetManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Management; 4 | using System.Net; 5 | #if !DEBUG 6 | using System.DirectoryServices; 7 | using System.Linq; 8 | #endif 9 | using Power8.Helpers; 10 | 11 | namespace Power8 12 | { 13 | /// 14 | /// Provides data related to the network activity PC might have 15 | /// 16 | static class NetManager 17 | { 18 | private static string _host, _wg; 19 | 20 | /// 21 | /// Gets the computer name 22 | /// 23 | public static string Hostname 24 | { 25 | get { return _host ?? (_host = Dns.GetHostName()); } 26 | } 27 | 28 | /// 29 | /// Gets the name of domain or workgroup 30 | /// 31 | public static string DomainOrWorkgroup 32 | { 33 | get 34 | { 35 | if (_wg == null) 36 | { 37 | try 38 | { 39 | using (var m = new ManagementObjectSearcher("select Domain from Win32_ComputerSystem")) 40 | using (var e = m.Get().GetEnumerator()) 41 | { 42 | if (e.MoveNext()) 43 | _wg = e.Current.GetPropertyValue("Domain").ToString(); 44 | } 45 | } 46 | catch (Exception ex){Log.Raw(ex.Message);} 47 | finally 48 | { 49 | if (string.IsNullOrWhiteSpace(_wg)) //modern 50 | _wg = Environment.GetEnvironmentVariable("USERDOMAIN"); 51 | if (string.IsNullOrWhiteSpace(_wg)) //old 52 | _wg = Environment.GetEnvironmentVariable("COMPUTERNAME"); 53 | } 54 | } 55 | return _wg; 56 | } 57 | } 58 | 59 | private static readonly List ComputerNames = new List(); 60 | /// 61 | /// Returns the list of UPPERCASED computer names which are visible in domain or workgroup. 62 | /// In debug, returns "Computer1"..."Computer3000" 63 | /// 64 | public static List ComputersNearby 65 | { 66 | get 67 | { 68 | if (ComputerNames.Count == 0) 69 | { 70 | #if DEBUG 71 | for (int i = 0; i < 3000; i++) 72 | { 73 | ComputerNames.Add("COMPUTER" + i); 74 | } 75 | #else 76 | try 77 | { 78 | using (var workgroup = new DirectoryEntry("WinNT://" + DomainOrWorkgroup)) 79 | { 80 | ComputerNames.AddRange(workgroup.Children 81 | .Cast() 82 | .Where(e => e.SchemaClassName == "Computer") 83 | .Select(e => e.Name.ToUpper())); 84 | } 85 | } 86 | catch (Exception ex) 87 | { 88 | Util.DispatchCaughtException(ex); 89 | ComputerNames.Add(Hostname); 90 | } 91 | #endif 92 | } 93 | return ComputerNames; 94 | } 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Helpers/Analytics.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Specialized; 4 | using System.Net; 5 | using System.Text; 6 | using System.Threading; 7 | 8 | namespace Power8.Helpers 9 | { 10 | public static class Analytics 11 | { 12 | private static AnalyticsClient _web; 13 | 14 | public static void Init(string trackingId, string clientId, string appName, string appVersion) 15 | { 16 | _web = new AnalyticsClient(trackingId, clientId, appName, appVersion); 17 | } 18 | 19 | public static void PostEvent(Category category, string action, string label, int? value) 20 | { 21 | AnalyticsCallAsync("event", new Dictionary 22 | { 23 | {"ec", category.ToString()}, 24 | {"ea", Cut(action, 500)}, 25 | {"el", Cut(label, 500)}, 26 | {"ev", value.HasValue ? value.ToString() : null} 27 | }); 28 | } 29 | 30 | public static void PostException(Exception ex, bool isFatal) 31 | { 32 | var exType = 33 | #if DEBUG 34 | "DBG" + 35 | #endif 36 | ex.GetType().Name; 37 | 38 | AnalyticsCallAsync("exception", new Dictionary 39 | { 40 | {"exd", Cut(exType, 150)}, 41 | {"exf", isFatal ? "1" : "0"} 42 | }); 43 | 44 | if (isFatal) 45 | { 46 | PostEvent(Category.Error, exType, ex.ToString(), null); 47 | } 48 | } 49 | 50 | private static string Cut(String original, int maxLength) 51 | { 52 | if (original == null) 53 | return null; 54 | return original.Length > maxLength ? original.Substring(0, maxLength) : original; 55 | } 56 | 57 | public enum Category 58 | { 59 | Deploy, Runtime, Error 60 | } 61 | 62 | private static void AnalyticsCallAsync(string hitType, Dictionary args) 63 | { 64 | if (_web == null) 65 | { 66 | Log.Raw("Analytics subsystem is not initialized"); 67 | return; 68 | } 69 | Util.ForkPool(() => 70 | { 71 | try 72 | { 73 | lock (_web) 74 | { 75 | var result = _web.PostAnalyticsHit(hitType, args); 76 | Log.Fmt("Code: {0}, data: {1}", _web.ResponseCode, new string(Encoding.Default.GetChars(result)).Replace('\0', ' ')); 77 | } 78 | } 79 | catch (Exception ex) 80 | { 81 | Log.Raw(ex.ToString()); 82 | } 83 | }, "Google Analytics call for " + hitType); 84 | } 85 | 86 | private class AnalyticsClient : WebClient 87 | { 88 | public AnalyticsClient(string resourceId, string clientId, string appName, string appVersion) 89 | { 90 | Encoding = Encoding.UTF8; 91 | _resourceId = resourceId; 92 | _clientId = clientId; 93 | _appName = appName; 94 | _appVer = appVersion; 95 | Headers[HttpRequestHeader.UserAgent] = 96 | string.Format("{0}/{1} ({2})", _appName, _appVer, Environment.OSVersion); 97 | _responseCodeHolder = new ThreadLocal(); 98 | } 99 | public byte[] PostAnalyticsHit(string hitType, Dictionary hitArgs) 100 | { 101 | var data = new NameValueCollection(); 102 | data["v"] = "1"; 103 | data["tid"] = _resourceId; 104 | data["cid"] = _clientId; 105 | data["an"] = _appName; 106 | data["av"] = _appVer; 107 | data["t"] = hitType; 108 | data["ul"] = Thread.CurrentThread.CurrentUICulture.Name; 109 | if (1 == Interlocked.CompareExchange(ref _sessionStarting, 0, 1)) 110 | { 111 | data["sc"] = "start"; 112 | } 113 | foreach (var a in hitArgs) 114 | { 115 | if (a.Value != null) 116 | data[a.Key] = a.Value; 117 | } 118 | return UploadValues(@"https://ssl.google-analytics.com/collect", WebRequestMethods.Http.Post, data); 119 | } 120 | 121 | public HttpStatusCode ResponseCode 122 | { 123 | get 124 | { 125 | return _responseCodeHolder.Value; 126 | } 127 | private set 128 | { 129 | _responseCodeHolder.Value = value; 130 | } 131 | } 132 | 133 | private readonly ThreadLocal _responseCodeHolder; 134 | private readonly string _resourceId, _clientId, _appName, _appVer; 135 | 136 | protected override WebResponse GetWebResponse(WebRequest request) 137 | { 138 | var resp = base.GetWebResponse(request); 139 | var hResp = resp as HttpWebResponse; 140 | if (hResp != null) 141 | { 142 | ResponseCode = hResp.StatusCode; 143 | } 144 | return resp; 145 | } 146 | 147 | private int _sessionStarting = 1; 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /Helpers/GATracer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | 6 | namespace Power8.Helpers 7 | { 8 | public class GATracer: Exception 9 | { 10 | private readonly int _id; 11 | private readonly Exception _original; 12 | private readonly Dictionary _data; 13 | private GATracer(int id, Exception original, Dictionary traceData) 14 | { 15 | _id = id; 16 | _original = original; 17 | _data = traceData; 18 | } 19 | 20 | public override string ToString() 21 | { 22 | var b = new StringBuilder("TID:"); 23 | b.Append(_id).Append("."); 24 | foreach (var data in _data) 25 | { 26 | b.AppendFormat("{0}:{1};", data.Key, data.Value); 27 | } 28 | b.Append("@"); 29 | int pos = 0, len = 0; 30 | bool first = true; 31 | var orig = _original.ToString(); 32 | using (var r = new StringReader(orig)) 33 | { 34 | do 35 | { 36 | var l = r.ReadLine() ?? string.Empty; 37 | if (l.Contains("Power8")) 38 | break; 39 | if (first) 40 | first = false; 41 | else 42 | pos += len; //position of PRE-last line 43 | len = l.Length; //length of LAST line 44 | len += Environment.NewLine.Length; 45 | } while (r.Peek() > -1); 46 | } 47 | if (pos < orig.Length) 48 | b.Append(orig.Substring(pos)); 49 | b.Append(_original); 50 | return b.ToString(); 51 | } 52 | 53 | public static void PostTraceData(Trace id, Exception original, Dictionary traceData) 54 | { 55 | Analytics.PostException(new GATracer((int)id, original, traceData), true); 56 | } 57 | 58 | public enum Trace 59 | { 60 | ArgumentExceptionInScanFolderSync, 61 | Win32ExceptionInRestart, 62 | Next 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Helpers/Log.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Text; 4 | using System.Threading; 5 | 6 | namespace Power8.Helpers 7 | { 8 | public static class Log 9 | { 10 | /// 11 | /// Logs message passed to the current debug log. 12 | /// Prepends calling method name, date, time and thread id. 13 | /// Optionally adds info on object which the callee was invoked to serve for. 14 | /// 15 | /// Text to log 16 | /// Description or name of the object calling method is working on. 17 | /// If the method doesn't serve any particular object at the moment, leave it unset. 18 | [Conditional("DEBUG")] 19 | public static void Raw(string message, string obj = null) 20 | { 21 | var b = new StringBuilder(DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss.ffff\t")); 22 | var mtd = new StackTrace().GetFrame(obj == string.Empty ? 2 : 1).GetMethod(); 23 | var loc = mtd.DeclaringType == null ? "global" : mtd.DeclaringType.Name; 24 | b.AppendFormat("{0}\t{1}::{2}", Thread.CurrentThread.ManagedThreadId, loc, mtd.Name); 25 | if(!string.IsNullOrEmpty(obj)) 26 | b.Append(" for " + obj); 27 | b.Append("\t" + message); 28 | Debug.WriteLine(b.ToString()); 29 | } 30 | /// 31 | /// Logs message passed to the current debug log. 32 | /// Prepends calling method name, date, time and thread id. 33 | /// 34 | /// Format string as used by String.Format(). 35 | /// Format string args as used by String.Format(). 36 | [Conditional("DEBUG")] 37 | public static void Fmt(string format, params object[] args) 38 | { 39 | Raw(string.Format(format, args), string.Empty); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Helpers/RemovableFileSystemWatcher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace Power8.Helpers 7 | { 8 | /// 9 | /// This is the FileSystemWatcher that can react on the system "undock device" notifications. 10 | /// To work it requires: 11 | /// 1) a window with WndProc to Register the notifications 12 | /// 2) this window to call ProcessDeviceNotification when corresponding event arrives 13 | /// Currently this bind is done via DriveManager. 14 | /// 15 | class RemovableFileSystemWatcher : FileSystemWatcher 16 | { 17 | private readonly IntPtr _reporter; 18 | /// 19 | /// Constructor 20 | /// 21 | /// Root of what to watch. See parent class docs for help 22 | /// on this parameter. 23 | /// HWND of the window that will be used as reporting 24 | /// proxy. See ProcessDeviceNotification() method documentation, and also the 25 | /// DriveManager class for more info. 26 | public RemovableFileSystemWatcher(string path, IntPtr reportingHwnd) : base(path) 27 | { 28 | _reporter = reportingHwnd; 29 | } 30 | 31 | new public bool EnableRaisingEvents 32 | { 33 | get { return base.EnableRaisingEvents; } 34 | set 35 | { 36 | Log.Raw("Value passed: " + value); 37 | base.EnableRaisingEvents = value; 38 | if (value) Lock(); 39 | else Unlock(); 40 | } 41 | } 42 | 43 | private IntPtr _hNotification = IntPtr.Zero, _hDrive = IntPtr.Zero; 44 | private static readonly IntPtr InvalidHandle = new IntPtr(-1); 45 | 46 | private void Unlock() 47 | { 48 | if (_hNotification != IntPtr.Zero) 49 | { 50 | API.UnregisterDeviceNotification(_hNotification); 51 | _hNotification = IntPtr.Zero; 52 | } 53 | if (_hDrive != IntPtr.Zero) 54 | { 55 | API.CloseHandle(_hDrive); 56 | _hDrive = IntPtr.Zero; 57 | } 58 | Log.Raw("Unlocked " + Path); 59 | } 60 | 61 | private void Lock() 62 | { 63 | var file = API.CreateFile(string.Format(@"\\.\{0}:", Path[0]), 64 | API.FileAccessRights.GENERIC_READ, 65 | FileShare.ReadWrite, 66 | IntPtr.Zero, 67 | FileMode.Open, 68 | API.CreateFileOptions.FILE_OPTIONS_NOT_SET, 69 | IntPtr.Zero); 70 | if (file == IntPtr.Zero || file == InvalidHandle) 71 | { 72 | Log.Raw("Cannot CreateFile " + Path); 73 | return; //might be real fixed drive 74 | } 75 | 76 | _hDrive = file; 77 | 78 | var msg = new API.DEV_BROADCAST_HANDLE { dbch_handle = file }; 79 | _hNotification = API.RegisterDeviceNotification(_reporter, msg, API.RDNFlags.DEVICE_NOTIFY_WINDOW_HANDLE); 80 | 81 | if (_hNotification == IntPtr.Zero || _hNotification == InvalidHandle) 82 | { 83 | Log.Raw("Cannot lock " + Path); 84 | Unlock(); //this drive appears to be non-notifiable 85 | } 86 | else 87 | { 88 | Log.Raw("Locked " + Path); 89 | } 90 | } 91 | 92 | /// 93 | /// This method must be called from the WndProcof a window identified by HWND passed to 94 | /// constructor of this class in case of WM_DEVICECHANGE event occurs. See DriveManager 95 | /// class for more details on parameters. 96 | /// 97 | /// The wParam from message, as is 98 | /// The lParam from message, as is 99 | /// Logical value, indicating whether this instance should be the last one 100 | /// that processes the message. True may be returned because the message itself doesn't 101 | /// satisfy the requirements of a class, or because this instance is identified itself 102 | /// against the message and performed targeted processing. False means that the message 103 | /// should be also passed for processing to some other instance of this class within the 104 | /// application. 105 | public bool ProcessDeviceNotification(IntPtr wParam, IntPtr lParam) 106 | { 107 | var code = (API.DeviceChangeMessages) wParam; 108 | 109 | switch (code) 110 | { 111 | case API.DeviceChangeMessages.DBT_DEVICEQUERYREMOVE: 112 | case API.DeviceChangeMessages.DBT_DEVICEQUERYREMOVEFAILED: 113 | case API.DeviceChangeMessages.DBT_CUSTOMEVENT: 114 | return Process(code, lParam); 115 | default: 116 | return true; 117 | } 118 | } 119 | 120 | private bool Process(API.DeviceChangeMessages wParam, IntPtr lParam) 121 | { 122 | var o = new API.DEV_BROADCAST_HANDLE(); 123 | if (lParam != IntPtr.Zero) Marshal.PtrToStructure(lParam, o); 124 | 125 | if (o.dbch_hdevnotify != _hNotification) 126 | { 127 | return false; 128 | } 129 | 130 | Log.Fmt("Device event {0}, custom event guid {1}", wParam, o.dbch_eventguid); 131 | 132 | switch (wParam) 133 | { 134 | case API.DeviceChangeMessages.DBT_DEVICEQUERYREMOVE: 135 | EnableRaisingEvents = false; 136 | break; 137 | case API.DeviceChangeMessages.DBT_DEVICEQUERYREMOVEFAILED: 138 | EnableRaisingEvents = true; 139 | break; 140 | case API.DeviceChangeMessages.DBT_CUSTOMEVENT: 141 | if (API.DevEvent.Queryable.Contains(o.dbch_eventguid)) 142 | { 143 | EnableRaisingEvents = false; 144 | } 145 | else if (API.DevEvent.Failed.Contains(o.dbch_eventguid)) 146 | { 147 | EnableRaisingEvents = true; 148 | } 149 | break; 150 | } 151 | return true; 152 | } 153 | 154 | protected override void Dispose(bool disposing) 155 | { 156 | Log.Raw("Dispose called"); 157 | try 158 | { 159 | Unlock(); 160 | } 161 | finally 162 | { 163 | base.Dispose(disposing); 164 | WasDisposed = true; 165 | } 166 | } 167 | 168 | public bool WasDisposed { get; private set; } 169 | } 170 | } -------------------------------------------------------------------------------- /Images/PayPal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Images/PayPal.gif -------------------------------------------------------------------------------- /Images/Pin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Images/Pin.png -------------------------------------------------------------------------------- /Images/Power8Logo.design: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Images/Power8Logo.design -------------------------------------------------------------------------------- /Images/Power8Logo_Red.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Images/Power8Logo_Red.ico -------------------------------------------------------------------------------- /Images/Power8Logo_Red16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Images/Power8Logo_Red16x16.ico -------------------------------------------------------------------------------- /Images/Power8Logo_Red48x48.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Images/Power8Logo_Red48x48.ico -------------------------------------------------------------------------------- /Images/Unpin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Images/Unpin.png -------------------------------------------------------------------------------- /Images/logo_alfa/Power8Logo7_Blue_alfa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Images/logo_alfa/Power8Logo7_Blue_alfa.png -------------------------------------------------------------------------------- /Images/logo_alfa/Power8Logo7_Green_alfa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Images/logo_alfa/Power8Logo7_Green_alfa.png -------------------------------------------------------------------------------- /Images/logo_alfa/Power8Logo7_Red_alfa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Images/logo_alfa/Power8Logo7_Red_alfa.png -------------------------------------------------------------------------------- /Images/logo_alfa/Power8Logo7_alfa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Images/logo_alfa/Power8Logo7_alfa.png -------------------------------------------------------------------------------- /Images/logo_alfa/Power8Logo7_marine_alfa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Images/logo_alfa/Power8Logo7_marine_alfa.png -------------------------------------------------------------------------------- /Images/logo_alfa/Power8Logo7_violet_alfa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Images/logo_alfa/Power8Logo7_violet_alfa.png -------------------------------------------------------------------------------- /Images/logo_alfa/Power8Logo7_yellow_alfa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Images/logo_alfa/Power8Logo7_yellow_alfa.png -------------------------------------------------------------------------------- /Images/logo_black/Power8Logo7_Blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Images/logo_black/Power8Logo7_Blue.png -------------------------------------------------------------------------------- /Images/logo_black/Power8Logo7_Green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Images/logo_black/Power8Logo7_Green.png -------------------------------------------------------------------------------- /Images/logo_black/Power8Logo7_Red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Images/logo_black/Power8Logo7_Red.png -------------------------------------------------------------------------------- /Images/logo_black/Power8Logo7_black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Images/logo_black/Power8Logo7_black.png -------------------------------------------------------------------------------- /Images/logo_black/Power8Logo7_marine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Images/logo_black/Power8Logo7_marine.png -------------------------------------------------------------------------------- /Images/logo_black/Power8Logo7_violet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Images/logo_black/Power8Logo7_violet.png -------------------------------------------------------------------------------- /Images/logo_black/Power8Logo7_yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Images/logo_black/Power8Logo7_yellow.png -------------------------------------------------------------------------------- /P8Installer/P8Installer.aiproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | All 5 | 2.0 6 | d8e31d82-456e-4e4e-8cb7-722b9975754b 7 | msi 8 | . 9 | P8Installer.aip 10 | 11 | 12 | . 13 | True 14 | P8Installer 15 | P8Installer 16 | P8Installer 17 | C:\Program Files (x86)\Caphyon\Advanced Installer 11.6.3\bin\x86\AdvancedInstaller.com 18 | -buildslist DefaultBuild 19 | 20 | 21 | 22 | 23 | Code 24 | 25 | 26 | 27 | 28 | Power8 29 | {010d2da1-c477-4cfe-8171-eee326e29fa0} 30 | True 31 | Built 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /Power8-VS2010.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Power8", "Power8.csproj", "{010D2DA1-C477-4CFE-8171-EEE326E29FA0}" 5 | EndProject 6 | Project("{840C416C-B8F3-42BC-B0DD-F6BB14C9F8CB}") = "P8Installer", "P8Installer\P8Installer.aiproj", "{D8E31D82-456E-4E4E-8CB7-722B9975754B}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | All|Any CPU = All|Any CPU 11 | All|x86 = All|x86 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|x86 = Debug|x86 14 | DefaultBuild|Any CPU = DefaultBuild|Any CPU 15 | DefaultBuild|x86 = DefaultBuild|x86 16 | Release|Any CPU = Release|Any CPU 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.All|Any CPU.ActiveCfg = Release|Any CPU 21 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.All|Any CPU.Build.0 = Release|Any CPU 22 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.All|x86.ActiveCfg = Release|Any CPU 23 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.Debug|x86.ActiveCfg = Debug|x86 26 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.Debug|x86.Build.0 = Debug|x86 27 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.DefaultBuild|Any CPU.ActiveCfg = Debug|Any CPU 28 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.DefaultBuild|Any CPU.Build.0 = Debug|Any CPU 29 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.DefaultBuild|x86.ActiveCfg = Debug|Any CPU 30 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.Release|x86.ActiveCfg = Release|x86 33 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.Release|x86.Build.0 = Release|x86 34 | {D8E31D82-456E-4E4E-8CB7-722B9975754B}.All|Any CPU.ActiveCfg = All|x86 35 | {D8E31D82-456E-4E4E-8CB7-722B9975754B}.All|x86.ActiveCfg = All|x86 36 | {D8E31D82-456E-4E4E-8CB7-722B9975754B}.All|x86.Build.0 = All|x86 37 | {D8E31D82-456E-4E4E-8CB7-722B9975754B}.Debug|Any CPU.ActiveCfg = DefaultBuild|x86 38 | {D8E31D82-456E-4E4E-8CB7-722B9975754B}.Debug|x86.ActiveCfg = DefaultBuild|x86 39 | {D8E31D82-456E-4E4E-8CB7-722B9975754B}.Debug|x86.Build.0 = DefaultBuild|x86 40 | {D8E31D82-456E-4E4E-8CB7-722B9975754B}.DefaultBuild|Any CPU.ActiveCfg = DefaultBuild|x86 41 | {D8E31D82-456E-4E4E-8CB7-722B9975754B}.DefaultBuild|x86.ActiveCfg = DefaultBuild|x86 42 | {D8E31D82-456E-4E4E-8CB7-722B9975754B}.DefaultBuild|x86.Build.0 = DefaultBuild|x86 43 | {D8E31D82-456E-4E4E-8CB7-722B9975754B}.Release|Any CPU.ActiveCfg = DefaultBuild|x86 44 | {D8E31D82-456E-4E4E-8CB7-722B9975754B}.Release|Any CPU.Build.0 = DefaultBuild|x86 45 | {D8E31D82-456E-4E4E-8CB7-722B9975754B}.Release|x86.ActiveCfg = DefaultBuild|x86 46 | {D8E31D82-456E-4E4E-8CB7-722B9975754B}.Release|x86.Build.0 = DefaultBuild|x86 47 | EndGlobalSection 48 | GlobalSection(SolutionProperties) = preSolution 49 | HideSolutionNode = FALSE 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /Power8.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /Power8.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.2.32630.192 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Power8", "Power8.csproj", "{010D2DA1-C477-4CFE-8171-EEE326E29FA0}" 7 | EndProject 8 | Project("{840C416C-B8F3-42BC-B0DD-F6BB14C9F8CB}") = "P8Installer", "P8Installer\P8Installer.aiproj", "{D8E31D82-456E-4E4E-8CB7-722B9975754B}" 9 | ProjectSection(ProjectDependencies) = postProject 10 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0} = {010D2DA1-C477-4CFE-8171-EEE326E29FA0} 11 | EndProjectSection 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|Any CPU = Debug|Any CPU 16 | Debug|x86 = Debug|x86 17 | Release|Any CPU = Release|Any CPU 18 | Release|x86 = Release|x86 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 22 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.Debug|Any CPU.Build.0 = Debug|Any CPU 23 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.Debug|x86.ActiveCfg = Debug|x86 24 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.Debug|x86.Build.0 = Debug|x86 25 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.Release|Any CPU.Build.0 = Release|Any CPU 27 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.Release|x86.ActiveCfg = Release|x86 28 | {010D2DA1-C477-4CFE-8171-EEE326E29FA0}.Release|x86.Build.0 = Release|x86 29 | {D8E31D82-456E-4E4E-8CB7-722B9975754B}.Debug|Any CPU.ActiveCfg = DefaultBuild 30 | {D8E31D82-456E-4E4E-8CB7-722B9975754B}.Debug|x86.ActiveCfg = DefaultBuild 31 | {D8E31D82-456E-4E4E-8CB7-722B9975754B}.Release|Any CPU.ActiveCfg = DefaultBuild 32 | {D8E31D82-456E-4E4E-8CB7-722B9975754B}.Release|Any CPU.Build.0 = DefaultBuild 33 | {D8E31D82-456E-4E4E-8CB7-722B9975754B}.Release|x86.ActiveCfg = DefaultBuild 34 | {D8E31D82-456E-4E4E-8CB7-722B9975754B}.Release|x86.Build.0 = DefaultBuild 35 | EndGlobalSection 36 | GlobalSection(SolutionProperties) = preSolution 37 | HideSolutionNode = FALSE 38 | EndGlobalSection 39 | GlobalSection(ExtensibilityGlobals) = postSolution 40 | SolutionGuid = {0328D4E2-8321-470B-A495-D1871BDECE3D} 41 | EndGlobalSection 42 | EndGlobal 43 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | using System.Windows; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Power8")] 9 | [assembly: AssemblyDescription("Start menu replacer for Windows XP, 7, 8 and 10")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Power8 Team")] 12 | [assembly: AssemblyProduct("Power8")] 13 | [assembly: AssemblyCopyright("© Power8 Team 2012-2022")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | //In order to begin building localizable applications, set 23 | //CultureYouAreCodingWith in your .csproj file 24 | //inside a . For example, if you are using US english 25 | //in your source files, set the to en-US. Then uncomment 26 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 27 | //the line below to match the UICulture setting in the project file. 28 | 29 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 30 | 31 | 32 | [assembly: ThemeInfo( 33 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 34 | //(used if a resource is not found in the page, 35 | // or application resource dictionaries) 36 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 37 | //(used if a resource is not found in the page, 38 | // app, or any theme specific resource dictionaries) 39 | )] 40 | 41 | 42 | // Version information for an assembly consists of the following four values: 43 | // 44 | // Major Version 45 | // Minor Version 46 | // Build Number 47 | // Revision 48 | // 49 | // You can specify all the values or you can default the Build and Revision Numbers 50 | // by using the '*' as shown below: 51 | // [assembly: AssemblyVersion("1.0.*")] 52 | [assembly: AssemblyVersion("1.6.4.1640")] 53 | [assembly: AssemblyFileVersion("1.6.4.1640")] 54 | //7zuri=https://github.com/AgentMC/power8/releases/download/v.1.6.4.1640/Power8_v.1.6.4.1640.7z 55 | //msuri=https://github.com/AgentMC/power8/releases/download/v.1.6.4.1640/Power8_v.1.6.4.1640.msi 56 | -------------------------------------------------------------------------------- /Properties/NoLoc.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Power8.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class NoLoc { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal NoLoc() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Power8.Properties.NoLoc", typeof(NoLoc).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to The Programs system folder ({0}) cannot be located under StartMenu folder ({2}). {1} may be unstable. . 65 | /// 66 | internal static string Err_CantFindProgramsDir { 67 | get { 68 | return ResourceManager.GetString("Err_CantFindProgramsDir", resourceCulture); 69 | } 70 | } 71 | 72 | /// 73 | /// Looks up a localized string similar to Type constructor did not return the type object.. 74 | /// 75 | internal static string Err_GotNoTypeObject { 76 | get { 77 | return ResourceManager.GetString("Err_GotNoTypeObject", resourceCulture); 78 | } 79 | } 80 | 81 | /// 82 | /// Looks up a localized string similar to Type disposition event cannot be reacted on.. 83 | /// 84 | internal static string Err_TypeIsNotIComponent { 85 | get { 86 | return ResourceManager.GetString("Err_TypeIsNotIComponent", resourceCulture); 87 | } 88 | } 89 | 90 | /// 91 | /// Looks up a localized string similar to an unhandled exceptoion occured in Power8. Details are below. 92 | ///. 93 | /// 94 | internal static string Err_UnhandledGeneric { 95 | get { 96 | return ResourceManager.GetString("Err_UnhandledGeneric", resourceCulture); 97 | } 98 | } 99 | 100 | /// 101 | /// Looks up a localized string similar to Power8. 102 | /// 103 | internal static string Stg_AppShortName { 104 | get { 105 | return ResourceManager.GetString("Stg_AppShortName", resourceCulture); 106 | } 107 | } 108 | 109 | /// 110 | /// Looks up a localized string similar to raw/master/Properties/AssemblyInfo.cs. 111 | /// 112 | internal static string Stg_AssemblyInfoURI { 113 | get { 114 | return ResourceManager.GetString("Stg_AssemblyInfoURI", resourceCulture); 115 | } 116 | } 117 | 118 | /// 119 | /// Looks up a localized string similar to wiki/Donate. 120 | /// 121 | internal static string Stg_DonateUri { 122 | get { 123 | return ResourceManager.GetString("Stg_DonateUri", resourceCulture); 124 | } 125 | } 126 | 127 | /// 128 | /// Looks up a localized string similar to wiki/DuplicatedIconsHack. 129 | /// 130 | internal static string Stg_DuplicatedIconsHackUri { 131 | get { 132 | return ResourceManager.GetString("Stg_DuplicatedIconsHackUri", resourceCulture); 133 | } 134 | } 135 | 136 | /// 137 | /// Looks up a localized string similar to https://github.com/AgentMC/power8/. 138 | /// 139 | internal static string Stg_Power8URI { 140 | get { 141 | return ResourceManager.GetString("Stg_Power8URI", resourceCulture); 142 | } 143 | } 144 | 145 | /// 146 | /// Looks up a localized string similar to Software\Microsoft\Windows\CurrentVersion\Run. 147 | /// 148 | internal static string Stg_RegKeyRun { 149 | get { 150 | return ResourceManager.GetString("Stg_RegKeyRun", resourceCulture); 151 | } 152 | } 153 | 154 | /// 155 | /// Looks up a localized string similar to Exiting because {0}. 156 | /// 157 | internal static string Str_FailFastFormat { 158 | get { 159 | return ResourceManager.GetString("Str_FailFastFormat", resourceCulture); 160 | } 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /Properties/NoLoc.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | The Programs system folder ({0}) cannot be located under StartMenu folder ({2}). {1} may be unstable. 122 | 123 | 124 | Type constructor did not return the type object. 125 | 126 | 127 | Type disposition event cannot be reacted on. 128 | 129 | 130 | an unhandled exceptoion occured in Power8. Details are below. 131 | 132 | String written to App event log. May not be localized. If you touch it, leave ending paragraph sign. 133 | 134 | 135 | Power8 136 | Default message box title. May not be localized. 137 | 138 | 139 | raw/master/Properties/AssemblyInfo.cs 140 | May not be localized. 141 | 142 | 143 | wiki/Donate 144 | 145 | 146 | wiki/DuplicatedIconsHack 147 | 148 | 149 | https://github.com/AgentMC/power8/ 150 | May not be localized. 151 | 152 | 153 | Software\Microsoft\Windows\CurrentVersion\Run 154 | May not be localized. 155 | 156 | 157 | Exiting because {0} 158 | String written to App event log. May not be localized. 159 | 160 | -------------------------------------------------------------------------------- /Properties/Resources.ru.Designer.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Properties/Resources.ru.Designer.cs -------------------------------------------------------------------------------- /Properties/Resources.sv.Designer.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMC/power8/ed47d2dd8ec2ba7a5092e910d26a411a95de123b/Properties/Resources.sv.Designer.cs -------------------------------------------------------------------------------- /Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | False 7 | 8 | 9 | 10 | 11 | 12 | False 13 | 14 | 15 | False 16 | 17 | 18 | False 19 | 20 | 21 | True 22 | 23 | 24 | True 25 | 26 | 27 | 2 28 | 29 | 30 | True 31 | 32 | 33 | 34 | 35 | 36 | True 37 | 38 | 39 | True 40 | 41 | 42 | True 43 | 44 | 45 | True 46 | 47 | 48 | True 49 | 50 | 51 | False 52 | 53 | 54 | 55 | 56 | 57 | True 58 | 59 | 60 | True 61 | 62 | 63 | False 64 | 65 | 66 | False 67 | 68 | 69 | True 70 | 71 | 72 | True 73 | 74 | 75 | False 76 | 77 | 78 | False 79 | 80 | 81 | False 82 | 83 | 84 | 2 85 | 86 | 87 | True 88 | 89 | 90 | True 91 | 92 | 93 | False 94 | 95 | 96 | False 97 | 98 | 99 | <?xml version="1.0" encoding="utf-8"?> 100 | <P8SearchProviders> 101 | <Provider key="b">https://www.bing.com/search?q={0}</Provider> 102 | <Provider key="d">https://www.baidu.com/s?wd={0}</Provider> 103 | <Provider key="g">https://google.com/search?q={0}</Provider> 104 | <Provider key="w">https://en.wikipedia.org/w/index.php?search={0}</Provider> 105 | <Provider key="y">https://search.yahoo.com/search?p={0}</Provider> 106 | <Provider key="в">https://ru.wikipedia.org/w/index.php?search={0}</Provider> 107 | </P8SearchProviders> 108 | 109 | 110 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ![http://www.chip.de/ii/1/6/0/7/0/2/3/7/cf953d1cbf1fcd3d.jpg](http://www.chip.de/ii/1/6/0/7/0/2/3/7/cf953d1cbf1fcd3d.jpg) Power 8 # 2 | 3 | ## The start menu replacer for Win8, styled and integrated inside taskbar. ## 4 | 5 | Designed for Windows8, works under Windows10, XP SP3 and Se7en SP1 as well.
6 | Please see all the info on [our Wiki](https://github.com/AgentMC/power8/wiki) 7 | 8 | ### ATTENTION! If you see "Unable to check for updates" warning on Power8 button, please manually update to [release 1.6.1.1619](https://github.com/AgentMC/power8/releases/tag/v.1.6.1.1619)! 9 | -------------------------------------------------------------------------------- /Views/About.xaml: -------------------------------------------------------------------------------- 1 |  8 | 9 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 87 |