private void ExecuteCommands(ExecuteBangParam param) { switch (param.Type) { case ExecuteBangParam.BangType.SetVariable: { // Assume that the parameter is the name of the variable // Ask for input string sInput = GetUserInput(param.Options); // If the user cancelled out of the inputbox (ESC key, etc.), then abort if (sInput == null) { // Execute OnDismissAction if defined if (!String.IsNullOrEmpty(param.DismissAction)) { API.Execute(rm.GetSkin(), param.DismissAction); } break; } // Ask Rainmeter to set the variable using a bang (http://rainmeter.net/RainCMS/?q=Bangs) API.Execute(rm.GetSkin(), "!SetVariable " + param.Command + " \"" + sInput + "\""); // Note that the skin needs DynamicVariables=1 in the measure's settings or the above // code will have no effect. } break; case ExecuteBangParam.BangType.ExecuteBatch: { for (int i = 0; i < param.Commands.Count; ++i) { // Execute the line, but if there's a problem (error or they cancel the // input textbox), then abort if (!ExecuteLine(param.Commands[i], param.Options, param.OverrideOptions[i])) { // Execute OnDismissAction if defined if (!String.IsNullOrEmpty(param.DismissAction)) { API.Execute(rm.GetSkin(), param.DismissAction); } break; } // Continue to the next line, if there is any } } break; } }
private void ExecuteCommands(ExecuteBangParam param) { switch (param.Type) { case ExecuteBangParam.BangType.SetVariable: { // Assume that the parameter is the name of the variable // Ask for input string sInput = GetUserInput(param.Options); // If the user cancelled out of the inputbox (ESC key, etc.), then abort if (sInput == null) { // Execute OnDismissAction if defined if (!String.IsNullOrEmpty(param.DismissAction)) API.Execute(rm.GetSkin(), param.DismissAction); break; } // Ask Rainmeter to set the variable using a bang (http://rainmeter.net/RainCMS/?q=Bangs) API.Execute(rm.GetSkin(), "!SetVariable " + param.Command + " \"" + sInput + "\""); // Note that the skin needs DynamicVariables=1 in the measure's settings or the above // code will have no effect. } break; case ExecuteBangParam.BangType.ExecuteBatch: { for (int i = 0; i < param.Commands.Count; ++i) { // Execute the line, but if there's a problem (error or they cancel the // input textbox), then abort if (!ExecuteLine(param.Commands[i], param.Options, param.OverrideOptions[i])) { // Execute OnDismissAction if defined if (!String.IsNullOrEmpty(param.DismissAction)) API.Execute(rm.GetSkin(), param.DismissAction); break; } // Continue to the next line, if there is any } } break; } }
internal void ExecuteBang(string args) { bool go = false; lock (this.locker) { if (!this.IsExecuteBangRunning) { this.IsExecuteBangRunning = true; go = true; } } if (go) { ExecuteBangParam param = new ExecuteBangParam(args); if (ReadOptions(param)) // Read all options in main thread for thread-safety { ThreadPool.QueueUserWorkItem(_ => { try { ExecuteCommands(param); } catch (Exception ex) { API.Log(API.LogType.Error, "C# plugin in ExecuteBang(), " + ex.GetType().ToString() + ": " + ex.Message); } lock (this.locker) { this.IsExecuteBangRunning = false; } }); } else { // No need to continue lock (this.locker) { this.IsExecuteBangRunning = false; } } } }
private bool ReadOptions(ExecuteBangParam param) { // Get default options ReadOption("DefaultValue", param.Options); ReadOption("X", param.Options, true); ReadOption("Y", param.Options, true); ReadOption("W", param.Options, true); ReadOption("H", param.Options, true); ReadOption("StringStyle", param.Options); ReadOption("StringAlign", param.Options); ReadOption("FocusDismiss", param.Options); ReadOption("FontColor", param.Options); ReadOption("FontFace", param.Options); ReadOption("FontSize", param.Options, true); ReadOption("SolidColor", param.Options); ReadOption("Password", param.Options); ReadOption("TopMost", param.Options); param.DismissAction = rm.ReadString("OnDismissAction", "", false); #region Handle a single parameter // If our parameter list only contains a single word, then open a textbox immediately // and set a value. This mode does not do any batching. if (!param.Command.Contains(" ")) { param.Type = ExecuteBangParam.BangType.SetVariable; return(true); } #endregion #region Handle multiple parameters // Our parameter list contains at least two words, so split them up string[] sParts = param.Command.Split(new string[] { " " }, StringSplitOptions.None); // If the first parameter is 'ExecuteBatch' (not case sensitive)... if (sParts[0].Trim().ToUpper() == "EXECUTEBATCH") { param.Type = ExecuteBangParam.BangType.ExecuteBatch; // ExecuteBatch tells this plugin to go through the measure's settings to look // for lines beginning with "Command" and executing Rainmeter bangs for each one. // If a line contains $UserInput$, then an input textbox is opened and command // execution pauses until the user enters text or dismisses the textbox. If the // textbox is dismissed (Escape key, for example), all processing ends, otherwise // it continues depending on the range of commands selected. // // Each "Command" line allows overriding all settings that the input textbox // supports, therefor some checking and substitution is performed, thus a // more complex parser has been implemented. // // ExecuteBatch expects this syntax: // ExecuteBatch [All|#|#-#] // // This allows Rainmeter to call the plugin to execute a range including: // All All commands in the measure // # Only a single command in the measure // #-# A specific range of commands in the measure #region Determine range // Determine range. Default is 1 to 1,000,000,000, although if processing finds // that a requested line is blank, it will stop all processing (so 'All' will // only parse 14 lines if "Command15" does not exist or is blank). int iMin = 1; int iMax = 1000000000; try { if (sParts[1].Trim().ToUpper() != "ALL") { if (sParts[1].Contains("-")) { string[] sSubParts = sParts[1].Split(new string[] { "-" }, StringSplitOptions.None); iMin = int.Parse(sSubParts[0]); iMax = int.Parse(sSubParts[1]); } else { iMin = iMax = int.Parse(sParts[1]); } } } catch // handle all errors above { // Any error above will be ignored and the default range used instead. // This can occur if the measure asks to ExecuteBatch an invalid range // or the range could not be translated to an acceptable format. // // For example: ExecuteBatch asdf iMin = 1; iMax = 1000000000; } #endregion #region Parse commands in range // Parse each command in the range, aborting if any line returns 'false' or // the requested command line does not exist in the config for that measure. for (int i = iMin; i <= iMax; i++) { // Read this command's line string sLine = rm.ReadString("Command" + i.ToString(), "", false); // If empty/non-existent, abort if (string.IsNullOrEmpty(sLine)) { break; } #region Handle in-line overrides // Create a blank list of overrides Dictionary <string, string> Overrides = new Dictionary <string, string>(); // Start looking for overridable settings and adjust the list accordingly, // stripping out settings from the line if they are discovered. // // The supporting TagData() function allows for whitespace if quotes are // used. For example: // // DefaultValue="hello there, how are you" sLine = ScanAndReplace(sLine, "DefaultValue", Overrides); sLine = ScanAndReplace(sLine, "X", Overrides, true); sLine = ScanAndReplace(sLine, "Y", Overrides, true); sLine = ScanAndReplace(sLine, "W", Overrides, true); sLine = ScanAndReplace(sLine, "H", Overrides, true); sLine = ScanAndReplace(sLine, "StringStyle", Overrides); sLine = ScanAndReplace(sLine, "StringAlign", Overrides); sLine = ScanAndReplace(sLine, "FocusDismiss", Overrides); sLine = ScanAndReplace(sLine, "FontColor", Overrides); sLine = ScanAndReplace(sLine, "FontFace", Overrides); sLine = ScanAndReplace(sLine, "FontSize", Overrides, true); sLine = ScanAndReplace(sLine, "SolidColor", Overrides); sLine = ScanAndReplace(sLine, "Password", Overrides); sLine = ScanAndReplace(sLine, "TopMost", Overrides); param.OverrideOptions.Add(Overrides); #endregion param.Commands.Add(sLine); } #endregion return(param.Commands.Count > 0); } #endregion // Unhandled command, log the message but otherwise do nothing param.Type = ExecuteBangParam.BangType.Unknown; API.Log(API.LogType.Debug, "InputText: Received command \"" + sParts[0].Trim() + "\", left unhandled"); return(false); }
private bool ReadOptions(ExecuteBangParam param) { // Get default options ReadOption("DefaultValue", param.Options); ReadOption("X", param.Options, true); ReadOption("Y", param.Options, true); ReadOption("W", param.Options, true); ReadOption("H", param.Options, true); ReadOption("StringStyle", param.Options); ReadOption("StringAlign", param.Options); ReadOption("FocusDismiss", param.Options); ReadOption("FontColor", param.Options); ReadOption("FontFace", param.Options); ReadOption("FontSize", param.Options, true); ReadOption("SolidColor", param.Options); ReadOption("Password", param.Options); ReadOption("TopMost", param.Options); param.DismissAction = rm.ReadString("OnDismissAction", "", false); #region Handle a single parameter // If our parameter list only contains a single word, then open a textbox immediately // and set a value. This mode does not do any batching. if (!param.Command.Contains(" ")) { param.Type = ExecuteBangParam.BangType.SetVariable; return true; } #endregion #region Handle multiple parameters // Our parameter list contains at least two words, so split them up string[] sParts = param.Command.Split(new string[] { " " }, StringSplitOptions.None); // If the first parameter is 'ExecuteBatch' (not case sensitive)... if (sParts[0].Trim().ToUpper() == "EXECUTEBATCH") { param.Type = ExecuteBangParam.BangType.ExecuteBatch; // ExecuteBatch tells this plugin to go through the measure's settings to look // for lines beginning with "Command" and executing Rainmeter bangs for each one. // If a line contains $UserInput$, then an input textbox is opened and command // execution pauses until the user enters text or dismisses the textbox. If the // textbox is dismissed (Escape key, for example), all processing ends, otherwise // it continues depending on the range of commands selected. // // Each "Command" line allows overriding all settings that the input textbox // supports, therefor some checking and substitution is performed, thus a // more complex parser has been implemented. // // ExecuteBatch expects this syntax: // ExecuteBatch [All|#|#-#] // // This allows Rainmeter to call the plugin to execute a range including: // All All commands in the measure // # Only a single command in the measure // #-# A specific range of commands in the measure #region Determine range // Determine range. Default is 1 to 1,000,000,000, although if processing finds // that a requested line is blank, it will stop all processing (so 'All' will // only parse 14 lines if "Command15" does not exist or is blank). int iMin = 1; int iMax = 1000000000; try { if (sParts[1].Trim().ToUpper() != "ALL") { if (sParts[1].Contains("-")) { string[] sSubParts = sParts[1].Split(new string[] { "-" }, StringSplitOptions.None); iMin = int.Parse(sSubParts[0]); iMax = int.Parse(sSubParts[1]); } else iMin = iMax = int.Parse(sParts[1]); } } catch // handle all errors above { // Any error above will be ignored and the default range used instead. // This can occur if the measure asks to ExecuteBatch an invalid range // or the range could not be translated to an acceptable format. // // For example: ExecuteBatch asdf iMin = 1; iMax = 1000000000; } #endregion #region Parse commands in range // Parse each command in the range, aborting if any line returns 'false' or // the requested command line does not exist in the config for that measure. for (int i = iMin; i <= iMax; i++) { // Read this command's line string sLine = rm.ReadString("Command" + i.ToString(), "", false); // If empty/non-existent, abort if (string.IsNullOrEmpty(sLine)) break; #region Handle in-line overrides // Create a blank list of overrides Dictionary<string, string> Overrides = new Dictionary<string, string>(); // Start looking for overridable settings and adjust the list accordingly, // stripping out settings from the line if they are discovered. // // The supporting TagData() function allows for whitespace if quotes are // used. For example: // // DefaultValue="hello there, how are you" sLine = ScanAndReplace(sLine, "DefaultValue", Overrides); sLine = ScanAndReplace(sLine, "X", Overrides, true); sLine = ScanAndReplace(sLine, "Y", Overrides, true); sLine = ScanAndReplace(sLine, "W", Overrides, true); sLine = ScanAndReplace(sLine, "H", Overrides, true); sLine = ScanAndReplace(sLine, "StringStyle", Overrides); sLine = ScanAndReplace(sLine, "StringAlign", Overrides); sLine = ScanAndReplace(sLine, "FocusDismiss", Overrides); sLine = ScanAndReplace(sLine, "FontColor", Overrides); sLine = ScanAndReplace(sLine, "FontFace", Overrides); sLine = ScanAndReplace(sLine, "FontSize", Overrides, true); sLine = ScanAndReplace(sLine, "SolidColor", Overrides); sLine = ScanAndReplace(sLine, "Password", Overrides); sLine = ScanAndReplace(sLine, "TopMost", Overrides); param.OverrideOptions.Add(Overrides); #endregion param.Commands.Add(sLine); } #endregion return param.Commands.Count > 0; } #endregion // Unhandled command, log the message but otherwise do nothing param.Type = ExecuteBangParam.BangType.Unknown; API.Log(API.LogType.Debug, "InputText: Received command \"" + sParts[0].Trim() + "\", left unhandled"); return false; }