using Microsoft.Win32; using System; using System.Collections.Generic; using System.Drawing; using System.Globalization; using System.Text; using System.Text.RegularExpressions; public static class VoiceBotScript { public static void Run(IntPtr windowHandle) { //this will hold the information for all of the profiles on your computer Dictionary profiles = new Dictionary(); //open the the voicebot profiles registry key to loop through all of the saved profiles using (RegistryKey key = Registry.CurrentUser.CreateSubKey("Software\\Binary Fortress Software\\VoiceBot\\Profiles", RegistryKeyPermissionCheck.ReadSubTree)) { //if we failed to open the key, throw an exception if (key == null) throw new Exception("Failed to enumerate profiles"); //loop through all of the registry key names foreach (string profileId in key.GetSubKeyNames()) { //open the registry key of the profile using (RegistryKey profileKey = Registry.CurrentUser.OpenSubKey("Software\\Binary Fortress Software\\VoiceBot\\Profiles\\" + profileId, RegistryKeyPermissionCheck.ReadSubTree)) { //if we failed to open the key, throw an exception if (profileKey == null) throw new Exception("Failed to get profile data"); //create a new VoiceBotProfile class using the json data from ProfileData VoiceBotProfile profile = new VoiceBotProfile(profileKey.GetValue("ProfileData").ToString()); //check just to be safe if(profiles.ContainsKey(profile.Name)) continue; //add the profile to the dictionary profiles.Add(profile.Name, profile); } } } //get and sort the names from the dictionary to display to the user List names = new List(); names.AddRange(profiles.Keys); names.Sort(); //get the user to select a profile from a list string profileName = BFS.Dialog.GetUserInputList("What profile would you like to get the commands for?", names.ToArray()); //if the user hit cancel, exit out of the script if(string.IsNullOrEmpty(profileName)) return; //start up notepad, and wait for it to open uint appid = BFS.Application.Start("C:\\Windows\\notepad.exe", ""); while(!BFS.Application.IsAppRunningByAppID(appid)) BFS.General.ThreadWait(100); //focus notepad BFS.Window.Focus(BFS.Application.GetMainWindowByAppID(appid)); BFS.General.ThreadWait(100); //select all of the text in notepad //if you're using something like notepad++, I suggest replacing this with ^(n) to create a new document BFS.Input.SendKeys("^(a)"); BFS.General.ThreadWait(100); //paste the selected profile to notepad BFS.Clipboard.PasteText(profiles[profileName].ToString()); } //this class will parse the json data of the VoiceBot profile into something usable private class VoiceBotProfile { internal readonly string Name; internal readonly List Commands = new List(); internal readonly List CommandNames = new List(); internal int LargestCommandNameLength = 0; internal VoiceBotProfile(string json) { //get the command names foreach (Match match in Regex.Matches(json, "(?<=\"name\":\")(?:\\\\\"|.)*?(?=\")")) this.CommandNames.Add(this.DeserializeJSONString(match.ToString())); //process the title if (CommandNames.Count > 0) { this.Name = CommandNames[0]; string cultureCode = this.DeserializeJSONString(Regex.Match(json, "(?<=\"culturecode\":\")(?:\\\\\"|.)*?(?=\")").ToString()); if(!CultureInfo.CurrentCulture.Name.Equals(cultureCode, StringComparison.OrdinalIgnoreCase)) this.Name += " (" + cultureCode + ")"; if(this.Name.Length > this.LargestCommandNameLength) this.LargestCommandNameLength = this.Name.Length; this.CommandNames.RemoveAt(0); } //get the commands foreach (Match match in Regex.Matches(json, "(?<=\"command\":\")(?:\\\\\"|.)*?(?=\")")) this.Commands.Add(this.DeserializeJSONString(match.ToString())); } //this helper function will deserialize a json string private string DeserializeJSONString(string json) { return Regex.Replace(json, "(\\\\[^u])|(\\\\u\\d{4})", EscaedCharEvaluator); } //this evaluator will convert an escaped json string into something we can work with private static string EscaedCharEvaluator(Match match) { switch (match.ToString()[1]) { case '"': return "\""; case '\\': return "\\"; case '/': return "/"; case 'b': return "\b"; case 'f': return "\f"; case 'n': return "\n"; case 'r': return "\r"; case 't': return "\t"; case 'u': int result = 0; int.TryParse(match.ToString().Substring(2), out result); return char.ConvertFromUtf32(result); default: return match.ToString(); } } //this will override the ToString method of this class. It will format the profile data into something readable and printable public override string ToString() { StringBuilder builder = new StringBuilder(); builder.AppendLine(this.Name); builder.AppendLine(); for(int i = 0; (i < this.Commands.Count) && (i < this.CommandNames.Count); i++) { int tabCount = (this.LargestCommandNameLength / 4) - (this.CommandNames[i].Length / 4) + 2; if(tabCount == 0) tabCount = 1; string tabs = ""; for(int j = 0; j < tabCount; j++) tabs += "\t"; builder.Append(this.CommandNames[i]).Append(tabs).AppendLine(this.Commands[i]); } return builder.ToString(); } } }