Пример #1
0
        private void CommandSelection_Click(object sender, EventArgs e)
        {
            while (flwCommandSelections.Controls.Count > 0)
            {
                flwCommandSelections.Controls.RemoveAt(0);
            }

            sharpRPA.UI.CustomControls.CommandGroupControl selectedControl = (sharpRPA.UI.CustomControls.CommandGroupControl)sender;

            var availableCommands = groupedCommands.Where(cmd => FindAssignedGroup(cmd) == selectedControl.GroupName).FirstOrDefault();

            foreach (var cmd in availableCommands)
            {
                //Instantiate Class
                Core.AutomationCommands.ScriptCommand newCommand = (Core.AutomationCommands.ScriptCommand)Activator.CreateInstance(cmd);

                sharpRPA.UI.CustomControls.CommandItemControl newitm = new sharpRPA.UI.CustomControls.CommandItemControl();
                if (uiImages.ContainsKey(newCommand.CommandName))
                {
                    newitm.CommandImage = uiImages[newCommand.CommandName];
                }

                newitm.CommandDisplay            = newCommand.SelectionName;
                newitm.FunctionalDescription     = FindFunctionalDescription(cmd);
                newitm.ImplementationDescription = FindImplementationDescription(cmd);
                newitm.ForeColor = Color.White;
                newitm.Click    += CommandItem_Click;
                flwCommandSelections.Controls.Add(newitm);
            }
        }
Пример #2
0
        public void AddCommandToListView(Core.AutomationCommands.ScriptCommand selectedCommand)
        {
            //add command
            lstScriptActions.Items.Add(CreateScriptCommandListViewItem(selectedCommand));

            //special types also get a following command and comment
            if ((selectedCommand is Core.AutomationCommands.BeginExcelDatasetLoopCommand) || (selectedCommand is Core.AutomationCommands.BeginListLoopCommand) || (selectedCommand is Core.AutomationCommands.BeginNumberOfTimesLoopCommand))
            {
                lstScriptActions.Items.Add(CreateScriptCommandListViewItem(new Core.AutomationCommands.CommentCommand()
                {
                    v_Comment = "Items in this section will run within the loop"
                }));
                lstScriptActions.Items.Add(CreateScriptCommandListViewItem(new Core.AutomationCommands.EndLoopCommand()));
            }
            else if (selectedCommand is Core.AutomationCommands.BeginIfCommand)
            {
                lstScriptActions.Items.Add(CreateScriptCommandListViewItem(new Core.AutomationCommands.CommentCommand()
                {
                    v_Comment = "Items in this section will run if the statement is true"
                }));
                lstScriptActions.Items.Add(CreateScriptCommandListViewItem(new Core.AutomationCommands.EndIfCommand()));
            }

            CreateUndoSnapshot();

            FormatCommandListView();
        }
Пример #3
0
        private void cboSelectedCommand_SelectionChangeCommitted(object sender, EventArgs e)
        {
            //find underlying command class and generate the required items on the UI flow layout for configuration
            var selectedCommandItem = cboSelectedCommand.Text;

            selectedCommand = commandList.Where(itm => itm.DisplayValue == selectedCommandItem).FirstOrDefault().CommandInstance;
            GenerateUIInputElements(selectedCommand);
        }
        public void ExecuteCommand(Core.Script.ScriptAction command, BackgroundWorker bgw)
        {
            //get command
            Core.AutomationCommands.ScriptCommand parentCommand = command.ScriptCommand;

            //handle pause
            while (isPaused)
            {
                System.Threading.Thread.Sleep(2000);
            }

            //bypass comments
            if (parentCommand is Core.AutomationCommands.CommentCommand || parentCommand.IsCommented)
            {
                bgwRunScript.ReportProgress(0, new object[] { parentCommand.LineNumber, "Skipping Line " + parentCommand.LineNumber + ": " + parentCommand.GetDisplayValue() });
                return;
            }

            //update listbox
            bgwRunScript.ReportProgress(0, new object[] { parentCommand.LineNumber, "Running Line " + parentCommand.LineNumber + ": " + parentCommand.GetDisplayValue() });

            //handle any errors
            try
            {
                //determine type of command
                if ((parentCommand is Core.AutomationCommands.BeginLoopCommand) || (parentCommand is Core.AutomationCommands.BeginIfCommand))
                {
                    //run the command and pass bgw/command as this command will recursively call this method for sub commands
                    parentCommand.RunCommand(this, command, bgw);
                }
                else
                {
                    //run the command
                    parentCommand.RunCommand(this);
                }
            }
            catch (Exception ex)
            {
                //error occuured so decide what user selected
                if (errorHandling != null)
                {
                    switch (errorHandling.v_ErrorHandlingAction)
                    {
                    case "Continue Processing":
                        bgwRunScript.ReportProgress(0, new object[] { parentCommand.LineNumber, "Error Occured at Line " + parentCommand.LineNumber + ":" + ex.ToString() });
                        bgwRunScript.ReportProgress(0, new object[] { parentCommand.LineNumber, "Continuing Per Error Handling" });
                        break;

                    default:
                        throw new Exception(ex.ToString());
                    }
                }
                else
                {
                    throw new Exception(ex.ToString());
                }
            }
        }
Пример #5
0
        public ScriptAction AddNewParentCommand(Core.AutomationCommands.ScriptCommand scriptCommand)
        {
            ScriptAction newExecutionCommand = new ScriptAction()
            {
                ScriptCommand = scriptCommand
            };

            Commands.Add(newExecutionCommand);
            return(newExecutionCommand);
        }
Пример #6
0
        public ScriptAction AddAdditionalAction(Core.AutomationCommands.ScriptCommand scriptCommand)
        {
            ScriptAction newExecutionCommand = new ScriptAction()
            {
                ScriptCommand = scriptCommand
            };

            AdditionalScriptCommands.Add(newExecutionCommand);
            return(newExecutionCommand);
        }
Пример #7
0
        private void PasteRow()
        {
            if (rowSelectedForCopy != null)
            {
                Core.AutomationCommands.ScriptCommand duplicatedCommand = (Core.AutomationCommands.ScriptCommand)Core.Common.Clone(rowSelectedForCopy.Tag);
                lstScriptActions.Items.Insert(lstScriptActions.SelectedIndices[0], CreateScriptCommandListViewItem(duplicatedCommand));
                FormatCommandListView();
            }

            CreateUndoSnapshot();
        }
Пример #8
0
        private ListViewItem CreateScriptCommandListViewItem(Core.AutomationCommands.ScriptCommand cmdDetails)
        {
            ListViewItem newCommand = new ListViewItem();

            newCommand.Text = cmdDetails.GetDisplayValue(); //+ "(" + cmdDetails.SelectedVariables() + ")";
            newCommand.SubItems.Add(cmdDetails.GetDisplayValue());
            newCommand.Tag       = cmdDetails;
            newCommand.ForeColor = cmdDetails.DisplayForeColor;

            newCommand.ImageIndex = uiImages.Images.IndexOfKey(cmdDetails.GetType().Name);
            return(newCommand);
        }
Пример #9
0
        /// <summary>
        /// adds a command as a nested command to a top-level command
        /// </summary>
        public ScriptAction AddAdditionalAction(Core.AutomationCommands.ScriptCommand scriptCommand)
        {
            if (AdditionalScriptCommands == null)
            {
                AdditionalScriptCommands = new List <ScriptAction>();
            }

            ScriptAction newExecutionCommand = new ScriptAction()
            {
                ScriptCommand = scriptCommand
            };

            AdditionalScriptCommands.Add(newExecutionCommand);
            return(newExecutionCommand);
        }
Пример #10
0
        private void AddCommandToListView(Core.AutomationCommands.ScriptCommand selectedCommand)
        {
            lstScriptActions.Items.Add(CreateScriptCommandListViewItem(selectedCommand));

            if (selectedCommand is Core.AutomationCommands.BeginLoopCommand)
            {
                lstScriptActions.Items.Add(CreateScriptCommandListViewItem(new Core.AutomationCommands.EndLoopCommand()));
            }
            else if (selectedCommand is Core.AutomationCommands.BeginIfCommand)
            {
                lstScriptActions.Items.Add(CreateScriptCommandListViewItem(new Core.AutomationCommands.EndIfCommand()));
            }

            CreateUndoSnapshot();

            FormatCommandListView();
        }
Пример #11
0
        /// <summary>
        /// Returns a path that contains the generated markdown files
        /// </summary>
        /// <returns></returns>
        public string GenerateMarkdownFiles()
        {
            //create directory if required
            var docsFolderName = "docs";

            if (!System.IO.Directory.Exists(docsFolderName))
            {
                System.IO.Directory.CreateDirectory(docsFolderName);
            }

            //get all commands
            var commandClasses = Assembly.GetExecutingAssembly().GetTypes()
                                 .Where(t => t.Namespace == "taskt.Core.AutomationCommands")
                                 .Where(t => t.Name != "ScriptCommand")
                                 .Where(t => t.IsAbstract == false)
                                 .Where(t => t.BaseType.Name == "ScriptCommand")
                                 .ToList();


            var           highLevelCommandInfo = new List <CommandMetaData>();
            StringBuilder sb;
            string        fullFileName;

            //loop each command
            foreach (var commandClass in commandClasses)
            {
                //instantiate and pull properties from command class
                Core.AutomationCommands.ScriptCommand instantiatedCommand = (Core.AutomationCommands.ScriptCommand)Activator.CreateInstance(commandClass);
                var groupName        = GetClassValue(commandClass, typeof(Core.AutomationCommands.Attributes.ClassAttributes.Group));
                var classDescription = GetClassValue(commandClass, typeof(Core.AutomationCommands.Attributes.ClassAttributes.Description));
                var usesDescription  = GetClassValue(commandClass, typeof(Core.AutomationCommands.Attributes.ClassAttributes.UsesDescription));
                var commandName      = instantiatedCommand.SelectionName;

                sb = new StringBuilder();

                //create string builder to build markdown document and append data
                sb.AppendLine("<!--TITLE: " + commandName + " Command -->");
                sb.AppendLine("<!-- SUBTITLE: a command in the " + groupName + " group. -->");

                sb.AppendLine("[Go To Automation Commands Overview](/automation-commands)");

                sb.AppendLine(Environment.NewLine);
                sb.AppendLine("# " + commandName + " Command");
                sb.AppendLine(Environment.NewLine);

                //append more
                sb.AppendLine("## What does this command do?");
                sb.AppendLine(classDescription);
                sb.AppendLine(Environment.NewLine);

                //more
                sb.AppendLine("## When would I want to use this command?");
                sb.AppendLine(usesDescription);
                sb.AppendLine(Environment.NewLine);

                //build parameter table based on required user inputs
                sb.AppendLine("## Command Parameters");
                sb.AppendLine("| Parameter Question   	| What to input  	|  Sample Data 	| Remarks  	|");
                sb.AppendLine("| ---                    | ---               | ---           | ---       |");

                //loop each property
                foreach (var prop in commandClass.GetProperties().Where(f => f.Name.StartsWith("v_")).ToList())
                {
                    //pull attributes from property
                    var commandLabel       = GetPropertyValue(prop, typeof(Core.AutomationCommands.Attributes.PropertyAttributes.PropertyDescription));
                    var helpfulExplanation = GetPropertyValue(prop, typeof(Core.AutomationCommands.Attributes.PropertyAttributes.InputSpecification));
                    var sampleUsage        = GetPropertyValue(prop, typeof(Core.AutomationCommands.Attributes.PropertyAttributes.SampleUsage));
                    var remarks            = GetPropertyValue(prop, typeof(Core.AutomationCommands.Attributes.PropertyAttributes.Remarks));

                    //append to parameter table
                    sb.AppendLine("|" + commandLabel + "|" + helpfulExplanation + "|" + sampleUsage + "|" + remarks + "|");
                }

                sb.AppendLine(Environment.NewLine);



                sb.AppendLine("## Developer/Additional Reference");
                sb.AppendLine("Automation Class Name: " + commandClass.Name);
                sb.AppendLine("Parent Namespace: " + commandClass.Namespace);
                sb.AppendLine("This page was generated on " + DateTime.Now.ToString("MM/dd/yy hh:mm tt"));


                sb.AppendLine(Environment.NewLine);

                sb.AppendLine("## Help");
                sb.AppendLine("[Open/Report an issue on GitHub](https://github.com/saucepleez/taskt/issues/new)");
                sb.AppendLine("[Ask a question on Gitter](https://gitter.im/taskt-rpa/Lobby)");



                //create kebob destination and command file nmae
                var kebobDestination = groupName.Replace(" ", "-").Replace("/", "-").ToLower();
                var kebobFileName    = commandName.Replace(" ", "-").Replace("/", "-").ToLower() + "-command.md";

                //create directory if required
                var destinationdirectory = docsFolderName + "\\" + kebobDestination;
                if (!System.IO.Directory.Exists(destinationdirectory))
                {
                    System.IO.Directory.CreateDirectory(destinationdirectory);
                }

                //write file
                fullFileName = System.IO.Path.Combine(destinationdirectory, kebobFileName);
                System.IO.File.WriteAllText(fullFileName, sb.ToString());

                //add to high level
                var serverPath = "/automation-commands/" + kebobDestination + "/" + kebobFileName.Replace(".md", "");
                highLevelCommandInfo.Add(new CommandMetaData()
                {
                    Group = groupName, Description = classDescription, Name = commandName, Location = serverPath
                });
            }

            sb = new StringBuilder();
            sb.AppendLine("<!--TITLE: Automation Commands -->");
            sb.AppendLine("<!-- SUBTITLE: an overview of available commands in taskt. -->");
            sb.AppendLine("## Automation Commands");
            sb.AppendLine("| Command Group   	| Command Name 	|  Command Description	|");
            sb.AppendLine("| ---                | ---           | ---                   |");


            foreach (var cmd in highLevelCommandInfo)
            {
                sb.AppendLine("|" + cmd.Group + "|[" + cmd.Name + "](" + cmd.Location + ")|" + cmd.Description + "|");
            }

            sb.AppendLine("This page was generated on " + DateTime.Now.ToString("MM/dd/yy hh:mm tt"));

            sb.AppendLine(Environment.NewLine);


            sb.AppendLine("## Help");
            sb.AppendLine("[Open/Report an issue on GitHub](https://github.com/saucepleez/taskt/issues/new)");
            sb.AppendLine("[Ask a question on Gitter](https://gitter.im/taskt-rpa/Lobby)");

            //write file
            fullFileName = System.IO.Path.Combine(docsFolderName, "automation-commands.md");
            System.IO.File.WriteAllText(fullFileName, sb.ToString());


            return(docsFolderName);
        }
Пример #12
0
        //handle events for the form
        private void frmNewCommand_Load(object sender, EventArgs e)
        {
            //Track the creation mode required - Add or Edit depending on calling Form
            if (creationMode == CreationMode.Add)
            {
                //Set DisplayMember to track DisplayValue from the class
                cboSelectedCommand.DisplayMember = "DisplayValue";

                //Pull all available automation commands
                var commandClasses = Assembly.GetExecutingAssembly().GetTypes()
                                     .Where(t => t.Namespace == "sharpRPA.Core.AutomationCommands")
                                     .Where(t => t.Name != "ScriptCommand")
                                     .Where(t => t.IsAbstract == false)
                                     .Where(t => t.BaseType.Name == "ScriptCommand")
                                     .ToList();

                //Loop through each class
                foreach (var commandClass in commandClasses)
                {
                    var    groupingAttribute = commandClass.GetCustomAttributes(typeof(Core.AutomationCommands.Attributes.ClassAttributes.Group), true);
                    string groupAttribute    = "";
                    if (groupingAttribute.Length > 0)
                    {
                        var attributeFound = (Core.AutomationCommands.Attributes.ClassAttributes.Group)groupingAttribute[0];
                        groupAttribute = attributeFound.groupName;
                    }

                    //Instantiate Class
                    Core.AutomationCommands.ScriptCommand newCommand = (Core.AutomationCommands.ScriptCommand)Activator.CreateInstance(commandClass);

                    //If command is enabled, pull for display and configuration
                    if (newCommand.CommandEnabled)
                    {
                        CommandItem newCommandItem = new CommandItem();
                        newCommandItem.DisplayValue    = string.Join(" - ", groupAttribute, newCommand.SelectionName);
                        newCommandItem.CommandInstance = newCommand;
                        commandList.Add(newCommandItem);
                    }
                }

                commandList = commandList.OrderBy(itm => itm.DisplayValue).ToList();

                //set combobox to coammand list
                cboSelectedCommand.DataSource = commandList;

                if ((defaultStartupCommand != null) && (commandList.Where(x => x.DisplayValue == defaultStartupCommand).Count() > 0))

                {
                    cboSelectedCommand.SelectedIndex = cboSelectedCommand.FindStringExact(defaultStartupCommand);
                }
                else
                {
                    //set index to first item
                    cboSelectedCommand.SelectedIndex = 0;
                }

                //force commit event to populate the flow layout
                cboSelectedCommand_SelectionChangeCommitted(null, null);
            }
            else

            {
                //enable only the command passed for edit mode
                cboSelectedCommand.Items.Add(selectedCommand.SelectionName);
                cboSelectedCommand.SelectedIndex = 0;
                cboSelectedCommand.Enabled       = false;
                cboSelectedCommand.Text          = selectedCommand.SelectionName;
                GenerateUIInputElements(selectedCommand);
            }
        }
Пример #13
0
        private Control GenerateInputControl(PropertyInfo inputField, Core.AutomationCommands.ScriptCommand currentCommand)
        {
            //create control to capture input which will be assigned to the class variable
            dynamic InputControl;

            //check if selection options were assigned
            var selectionOptions = inputField.GetCustomAttributes(typeof(Core.AutomationCommands.Attributes.PropertyAttributes.PropertyUISelectionOption));

            if (selectionOptions.Count() > 0)
            {
                //create combobox for selection item
                InputControl        = new ComboBox();
                InputControl.Height = 30;
                InputControl.Width  = 250;
                InputControl.Font   = new Font("Segoe UI", 12, FontStyle.Regular);

                //loop through options
                foreach (Core.AutomationCommands.Attributes.PropertyAttributes.PropertyUISelectionOption option in selectionOptions)
                {
                    InputControl.Items.Add(option.uiOption);
                }

                ComboBox control = InputControl;
                //additional helper for specific fields
                if (inputField.Name == "v_SeleniumElementAction")
                {
                    control.SelectedIndexChanged += seleniumAction_SelectionChangeCommitted;
                }
                else if (inputField.Name == "v_IfActionType")
                {
                    control.SelectedIndexChanged += ifAction_SelectionChangeCommitted;
                }
            }
            else
            {
                //legacy population method
                if (inputField.Name == "v_WindowName")
                {
                    InputControl        = new ComboBox();
                    InputControl.Height = 30;
                    InputControl.Width  = 200;
                    //add an option for current window which is the window which is currently in the foreground
                    InputControl.Items.Add("Current Window");
                    //get all running processes
                    Process[] processlist = Process.GetProcesses();
                    //pull the main window title for each
                    foreach (Process process in processlist)
                    {
                        if (!String.IsNullOrEmpty(process.MainWindowTitle))
                        {
                            //add to the control list of available windows
                            InputControl.Items.Add(process.MainWindowTitle);
                        }
                    }
                }
                else if (inputField.Name == "v_ScreenshotWindowName")
                {
                    InputControl        = new ComboBox();
                    InputControl.Height = 30;
                    InputControl.Width  = 200;
                    //add an option for current window which is the window which is currently in the foreground
                    InputControl.Items.Add("Desktop");
                    //get all running processes
                    Process[] processlist = Process.GetProcesses();
                    //pull the main window title for each
                    foreach (Process process in processlist)
                    {
                        if (!String.IsNullOrEmpty(process.MainWindowTitle))
                        {
                            //add to the control list of available windows
                            InputControl.Items.Add(process.MainWindowTitle);
                        }
                    }
                }
                else if (inputField.Name == "v_AutomationWindowName")
                {
                    InputControl        = new ComboBox();
                    InputControl.Height = 30;
                    InputControl.Width  = 200;

                    //get all running processes
                    Process[] processlist = Process.GetProcesses();
                    //pull the main window title for each
                    foreach (Process process in processlist)
                    {
                        if (!String.IsNullOrEmpty(process.MainWindowTitle))
                        {
                            //add to the control list of available windows
                            InputControl.Items.Add(process.MainWindowTitle);
                        }
                    }

                    InputControl.SelectedIndexChanged +=
                        new System.EventHandler(AutomationWindowName_SelectedIndexChanged);
                }
                else if (inputField.Name == "v_AutomationHandleName")
                {
                    InputControl        = new ComboBox();
                    InputControl.Height = 30;
                    InputControl.Width  = 200;
                }
                else if (inputField.Name == "v_AutomationHandleDisplayName")
                {
                    InputControl        = new ComboBox();
                    InputControl.Height = 30;
                    InputControl.Width  = 200;

                    InputControl.SelectedIndexChanged +=
                        new System.EventHandler(DisplayHandleSelected_SelectedIndexChanged);
                }
                else if (inputField.Name == "v_MouseClick")
                {
                    InputControl        = new ComboBox();
                    InputControl.Height = 30;
                    InputControl.Width  = 300;
                    InputControl.Items.Add("None");
                    InputControl.Items.Add("Left Click");
                    InputControl.Items.Add("Middle Click");
                    InputControl.Items.Add("Right Click");
                    InputControl.Items.Add("Left Down");
                    InputControl.Items.Add("Middle Down");
                    InputControl.Items.Add("Right Down");
                    InputControl.Items.Add("Left Up");
                    InputControl.Items.Add("Middle Up");
                    InputControl.Items.Add("Right Up");
                }
                else if (inputField.Name == "v_WebAction")
                {
                    InputControl        = new ComboBox();
                    InputControl.Height = 30;
                    InputControl.Width  = 300;

                    InputControl.Items.Add("Invoke Click");
                    InputControl.Items.Add("Left Click");
                    InputControl.Items.Add("Middle Click");
                    InputControl.Items.Add("Right Click");

                    InputControl.Items.Add("Get Attribute");
                    InputControl.Items.Add("Set Attribute");

                    ComboBox webAction = (ComboBox)InputControl;
                    webAction.SelectedIndexChanged += webAction_SelectionChangeCommitted;
                }
                else if ((inputField.Name == "v_userVariableName") || (inputField.Name == "v_applyToVariableName"))
                {
                    InputControl = new ComboBox();
                    foreach (var scriptVariable in scriptVariables)
                    {
                        if (!string.IsNullOrEmpty(scriptVariable.variableName))
                        {
                            InputControl.Items.Add(scriptVariable.variableName);
                        }
                    }
                }
                else if ((inputField.Name == "v_WebActionParameterTable") || (inputField.Name == "v_IfActionParameterTable"))
                {
                    InputControl = new DataGridView();

                    InputControl.Name   = inputField.Name;
                    InputControl.Width  = 500;
                    InputControl.Height = 140;

                    DataGridViewTextBoxColumn propertyName = new DataGridViewTextBoxColumn();
                    propertyName.HeaderText       = "Parameter Name";
                    propertyName.DataPropertyName = "Parameter Name";
                    InputControl.Columns.Add(propertyName);

                    DataGridViewTextBoxColumn propertyValue = new DataGridViewTextBoxColumn();
                    propertyValue.HeaderText       = "Parameter Value";
                    propertyValue.DataPropertyName = "Parameter Value";
                    InputControl.Columns.Add(propertyValue);

                    InputControl.AutoSizeColumnsMode   = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
                    InputControl.AllowUserToAddRows    = false;
                    InputControl.AllowUserToDeleteRows = false;

                    //set datasource

                    if (currentCommand is Core.AutomationCommands.IEBrowserElementCommand)
                    {
                        var cmd = (Core.AutomationCommands.IEBrowserElementCommand)currentCommand;
                        InputControl.DataSource = cmd.v_WebActionParameterTable;
                        InputControl.Font       = new Font("Segoe UI", 8, FontStyle.Regular);
                    }
                    else if (currentCommand is Core.AutomationCommands.SeleniumBrowserElementActionCommand)
                    {
                        var cmd = (Core.AutomationCommands.SeleniumBrowserElementActionCommand)currentCommand;
                        InputControl.DataSource = cmd.v_WebActionParameterTable;
                        InputControl.Font       = new Font("Segoe UI", 8, FontStyle.Regular);
                    }
                    else if (currentCommand is Core.AutomationCommands.BeginIfCommand)
                    {
                        var cmd = (Core.AutomationCommands.BeginIfCommand)currentCommand;
                        InputControl.DataSource = cmd.v_IfActionParameterTable;
                        InputControl.Font       = new Font("Segoe UI", 8, FontStyle.Regular);
                    }
                }
                else if (inputField.Name == "v_IEBrowserName")
                {
                    InputControl        = new ComboBox();
                    InputControl.Width  = 300;
                    InputControl.Height = 50;

                    var shellWindows = new ShellWindows();
                    foreach (IWebBrowser2 shellWindow in shellWindows)
                    {
                        if (shellWindow.Document is MSHTML.HTMLDocument)
                        {
                            InputControl.Items.Add(shellWindow.Document.Title);
                        }
                    }
                }
                else if (inputField.Name == "v_Comment")
                {
                    // assumed that all "v_Comment" will need to have a larger box for typing user comments about the action
                    InputControl = new TextBox();

                    if (currentCommand is Core.AutomationCommands.CommentCommand)
                    {
                        InputControl.Height = 300;
                        InputControl.Width  = 400;
                    }
                    else
                    {
                        InputControl.Height = 100;
                        InputControl.Width  = 300;
                    }

                    InputControl.Multiline = true;
                }
                else if (inputField.Name == "v_WebSearchTable")
                {
                    InputControl = new DataGridView();

                    InputControl.Name   = inputField.Name;
                    InputControl.Width  = 400;
                    InputControl.Height = 180;

                    InputControl.AutoGenerateColumns = false;
                    DataGridViewCheckBoxColumn enabledColumn = new DataGridViewCheckBoxColumn();
                    enabledColumn.HeaderText       = "Enabled";
                    enabledColumn.DataPropertyName = "Enabled";
                    InputControl.Columns.Add(enabledColumn);

                    DataGridViewTextBoxColumn propertyName = new DataGridViewTextBoxColumn();
                    propertyName.HeaderText       = "Property Name";
                    propertyName.DataPropertyName = "Property Name";
                    InputControl.Columns.Add(propertyName);

                    DataGridViewTextBoxColumn propertyValue = new DataGridViewTextBoxColumn();
                    propertyValue.HeaderText       = "Property Value";
                    propertyValue.DataPropertyName = "Property Value";
                    InputControl.Columns.Add(propertyValue);

                    InputControl.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;

                    //set datasource
                    var cmd = (Core.AutomationCommands.IEBrowserElementCommand)currentCommand;
                    InputControl.DataSource = cmd.v_WebSearchTable;
                    InputControl.Font       = new Font("Segoe UI", 8, FontStyle.Regular);
                }
                else
                {
                    //variable is simply a standard variable
                    InputControl        = new TextBox();
                    InputControl.Height = 30;
                    InputControl.Width  = 300;
                }

                //standard for all controls
                InputControl.Visible = true;
                InputControl.Name    = inputField.Name;
            }

            if (!(InputControl is DataGridView)) //dgv already has binding set
            {
                InputControl.Font = new Font("Segoe UI", 12, FontStyle.Regular);
                InputControl.DataBindings.Add("Text", currentCommand, inputField.Name, false, DataSourceUpdateMode.OnPropertyChanged);
            }

            return(InputControl);
        }
Пример #14
0
        //handles generation of controls for the main flowlayout and tracking/assignment of input elements

        /// <summary>
        /// Generate UI elements for data-collection based on the selected command
        /// </summary>
        private void GenerateUIInputElements(Core.AutomationCommands.ScriptCommand currentCommand)
        {
            //remove all existing controls
            while (flw_InputVariables.Controls.Count > 0)
            {
                flw_InputVariables.Controls.RemoveAt(0);
            }

            //find all input variables -- all input variables start with "v_" in the associated class
            var inputVariableFields = currentCommand.GetType().GetProperties().Where(f => f.Name.StartsWith("v_")).ToList();

            //set form height
            int formHeight = 0;

            //loop through available variables
            foreach (var inputField in inputVariableFields)
            {
                //create a label for each variable name
                Label inputLabel = new Label();
                inputLabel.AutoSize  = true;
                inputLabel.Font      = new Font("Segoe UI", 10, FontStyle.Bold);
                inputLabel.ForeColor = Color.SteelBlue;
                inputLabel.Name      = "lbl_" + inputField.Name;
                formHeight          += 50;
                //apply friendly translation
                var propertyAttributesAssigned = inputField.GetCustomAttributes(typeof(Core.AutomationCommands.Attributes.PropertyAttributes.PropertyDescription), true);

                if (propertyAttributesAssigned.Length > 0)
                {
                    var attribute = (Core.AutomationCommands.Attributes.PropertyAttributes.PropertyDescription)propertyAttributesAssigned[0];
                    inputLabel.Text = attribute.propertyDescription;
                }
                else
                {
                    inputLabel.Text = inputField.Name;
                }

                var inputControl = GenerateInputControl(inputField, currentCommand);

                formHeight += inputControl.Height;

                //add label and input control to flow layout
                flw_InputVariables.Controls.Add(inputLabel);

                //find if UI helpers are applied
                var propertyAllowsVars = inputField.GetCustomAttributes(typeof(Core.AutomationCommands.Attributes.PropertyAttributes.PropertyUIHelper), true);

                if (propertyAllowsVars.Length > 0)
                {
                    foreach (Core.AutomationCommands.Attributes.PropertyAttributes.PropertyUIHelper attrib in propertyAllowsVars)
                    {
                        sharpRPA.UI.CustomControls.CommandItemControl variableInsertion = new sharpRPA.UI.CustomControls.CommandItemControl();
                        variableInsertion.Padding   = new System.Windows.Forms.Padding(10, 0, 0, 0);
                        variableInsertion.ForeColor = Color.Black;
                        variableInsertion.Tag       = inputControl;

                        switch (attrib.additionalHelper)
                        {
                        case Core.AutomationCommands.Attributes.PropertyAttributes.PropertyUIHelper.UIAdditionalHelperType.ShowVariableHelper:
                            //show variable selector
                            variableInsertion.CommandImage   = UI.Images.GetUIImage("VariableCommand");
                            variableInsertion.CommandDisplay = "Insert Variable";
                            variableInsertion.Click         += ShowVariableSelector;
                            flw_InputVariables.Controls.Add(variableInsertion);
                            break;

                        case Core.AutomationCommands.Attributes.PropertyAttributes.PropertyUIHelper.UIAdditionalHelperType.ShowFileSelectionHelper:
                            //show file selector
                            variableInsertion.CommandImage   = UI.Images.GetUIImage("ClipboardGetTextCommand");
                            variableInsertion.CommandDisplay = "Select a File";
                            variableInsertion.ForeColor      = Color.Black;
                            variableInsertion.Tag            = inputControl;
                            variableInsertion.Click         += ShowFileSelector;
                            flw_InputVariables.Controls.Add(variableInsertion);
                            break;

                        default:
                            break;
                        }
                    }

                    //var attribute = (Core.AutomationCommands.Attributes.PropertyAttributes.PropertyUIHelper)propertyAllowsVars[0];
                    //if (attribute.propertyAllowsVariables)
                    //{
                    //    //show variable selector
                    //    sharpRPA.UI.CustomControls.CommandItemControl variableInsertion = new sharpRPA.UI.CustomControls.CommandItemControl();
                    //    variableInsertion.CommandImage = UI.Images.GetUIImage("VariableCommand");
                    //    variableInsertion.CommandDisplay = "Insert Variable";
                    //    variableInsertion.ForeColor = Color.Black;
                    //    variableInsertion.Tag = inputControl;
                    //    variableInsertion.Click += ShowVariableSelector;
                    //    flw_InputVariables.Controls.Add(variableInsertion);
                    //}
                }

                //these types get a helper button to launch another form
                if (inputField.Name == "v_WebSearchTable")
                {
                    Core.AutomationCommands.IEBrowserElementCommand webCommand = (Core.AutomationCommands.IEBrowserElementCommand)currentCommand;
                    sharpRPA.UI.CustomControls.CommandItemControl   newitm     = new sharpRPA.UI.CustomControls.CommandItemControl();

                    newitm.CommandImage   = UI.Images.GetUIImage(webCommand.CommandName);
                    newitm.CommandDisplay = "Click here to Capture Web Element";
                    newitm.ForeColor      = Color.Black;
                    newitm.Click         += ShowElementCaptureForm;
                    flw_InputVariables.Controls.Add(newitm);
                }
                else if (inputField.Name == "v_XMousePosition")
                {
                    Core.AutomationCommands.SendMouseMoveCommand  mouseCommand = (Core.AutomationCommands.SendMouseMoveCommand)currentCommand;
                    sharpRPA.UI.CustomControls.CommandItemControl newitm       = new sharpRPA.UI.CustomControls.CommandItemControl();
                    newitm.CommandImage   = UI.Images.GetUIImage(mouseCommand.CommandName);
                    newitm.CommandDisplay = "Click here to Capture Mouse Position";
                    newitm.ForeColor      = Color.Black;
                    newitm.Click         += ShowMouseCaptureForm;
                    flw_InputVariables.Controls.Add(newitm);
                }

                //add to flow layout
                flw_InputVariables.Controls.Add(inputControl);

                //handle edit mode to add combobox data
                if ((creationMode == CreationMode.Edit) && (currentCommand is Core.AutomationCommands.BeginIfCommand) && (inputControl is DataGridView))
                {
                    Core.AutomationCommands.BeginIfCommand ifCmd = (Core.AutomationCommands.BeginIfCommand)currentCommand;
                    if (ifCmd.v_IfActionType == "Value")
                    {
                        DataGridViewComboBoxCell comparisonComboBox = new DataGridViewComboBoxCell();
                        comparisonComboBox.Items.Add("is equal to");
                        comparisonComboBox.Items.Add("is greater than");
                        comparisonComboBox.Items.Add("is greater than or equal to");
                        comparisonComboBox.Items.Add("is less than");
                        comparisonComboBox.Items.Add("is less than or equal to");
                        comparisonComboBox.Items.Add("is not equal to");

                        //assign cell as a combobox
                        DataGridView inputCtrl = (DataGridView)inputControl;
                        inputCtrl.Rows[1].Cells[1] = comparisonComboBox;
                    }
                }
            }

            if ((currentCommand is Core.AutomationCommands.IEBrowserElementCommand) && (creationMode == CreationMode.Edit))
            {
                Core.AutomationCommands.IEBrowserElementCommand webCommand = (Core.AutomationCommands.IEBrowserElementCommand)currentCommand;

                if (webCommand.v_WebAction == "Invoke Click")
                {
                    DataGridView webActionParameterBox    = (DataGridView)flw_InputVariables.Controls["v_WebActionParameterTable"];
                    Label        additionalParameterLabel = (Label)flw_InputVariables.Controls["lbl_v_WebActionParameterTable"];
                    additionalParameterLabel.Visible = false;
                    webActionParameterBox.Visible    = false;
                }
            }

            //add additional offset
            this.Height = formHeight + 200;
        }
Пример #15
0
        private void frmScriptBuilder_Load(object sender, EventArgs e)
        {
            //detect latest release
            //HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create("https://api.github.com/repos/saucepleez/sharpRPA/releases");
            //myHttpWebRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2;)";
            //HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();

            //StreamReader reader = new StreamReader(myHttpWebResponse.GetResponseStream(), Encoding.UTF8);
            //String responseString = reader.ReadToEnd();

            //Newtonsoft.Json.Linq.JArray jsonArray = Newtonsoft.Json.Linq.JArray.Parse(responseString);
            //dynamic data = Newtonsoft.Json.Linq.JObject.Parse(jsonArray[0].ToString());



            //create undo list
            undoList = new List <List <ListViewItem> >();

            //get app settings
            var appSettingClass = new Core.ApplicationSettings();

            appSettings = appSettingClass.GetOrCreateApplicationSettings();

            //get server setting preferences
            var serverSettings = appSettings.ServerSettings;


            //try to connect to server
            if ((serverSettings.ServerConnectionEnabled) && (serverSettings.ConnectToServerOnStartup))
            {
                CreateSocketConnection(serverSettings.ServerURL);
            }



            //create folder to store scripts
            var rpaScriptsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\sharpRPA\\My Scripts\\";

            if (!System.IO.Directory.Exists(rpaScriptsFolder))
            {
                UI.Forms.Supplemental.frmDialog userDialog = new UI.Forms.Supplemental.frmDialog("Would you like to create a folder to save your scripts in now? A script folder is required to save scripts generated with this application. The new script folder path would be '" + rpaScriptsFolder + "'.", "Unable to locate Script Folder!", UI.Forms.Supplemental.frmDialog.DialogType.YesNo, 0);

                if (userDialog.ShowDialog() == DialogResult.OK)
                {
                    System.IO.Directory.CreateDirectory(rpaScriptsFolder);
                }
            }

            //get latest files for recent files list on load
            GenerateRecentFiles();

            //get current version
            lblCurrentVersion.Text = "v" + new Version(System.Windows.Forms.Application.ProductVersion);

            //no height for status bar
            tlpControls.RowStyles[3].Height = 0;

            //instantiate for script variables
            scriptVariables = new List <Core.Script.ScriptVariable>();

            //pnlHeader.BackColor = Color.FromArgb(255, 214, 88);

            //instantiate and populate display icons for commands
            uiImages = UI.Images.UIImageList();



            lstScriptActions.SmallImageList = uiImages;



            // tvCommands.ImageList = uiImages;
            // tvCommands.ImageList.Images.Add(new Bitmap(1,1));

            //get commands
            var groupedCommands = Core.Common.GetGroupedCommands();

            foreach (var cmd in groupedCommands)
            {
                var      group    = cmd.Key as Core.AutomationCommands.Attributes.ClassAttributes.Group;
                TreeNode newGroup = new TreeNode(group.groupName);
                // newGroup.ImageIndex = tvCommands.ImageList.Images.Count - 1;
                // newGroup.SelectedImageIndex = tvCommands.ImageList.Images.Count - 1;

                foreach (var subcmd in cmd)
                {
                    Core.AutomationCommands.ScriptCommand newCommand = (Core.AutomationCommands.ScriptCommand)Activator.CreateInstance(subcmd);
                    TreeNode subNode = new TreeNode(newCommand.SelectionName);
                    //subNode.ImageIndex = uiImages.Images.IndexOfKey(newCommand.GetType().Name);
                    // subNode.SelectedImageIndex = uiImages.Images.IndexOfKey(newCommand.GetType().Name);
                    newGroup.Nodes.Add(subNode);
                }


                tvCommands.Nodes.Add(newGroup);
            }

            //tvCommands.ImageList = uiImages;
        }
Пример #16
0
        public void ExecuteCommand(Core.Script.ScriptAction command, BackgroundWorker bgw)
        {
            //get command
            Core.AutomationCommands.ScriptCommand parentCommand = command.ScriptCommand;

            //handle pause request
            if (parentCommand.PauseBeforeExeucution)
            {
                bgwRunScript.ReportProgress(0, new PauseRequest());
                isPaused = true;
            }

            //handle pause
            bool isFirstWait = true;

            while (isPaused)
            {
                //only show pause first loop
                if (isFirstWait)
                {
                    bgwRunScript.ReportProgress(0, new ProgressUpdate()
                    {
                        LineNumber = parentCommand.LineNumber, UpdateText = "Paused on Line " + parentCommand.LineNumber + ": " + parentCommand.GetDisplayValue()
                    });
                    bgwRunScript.ReportProgress(0, new ProgressUpdate()
                    {
                        LineNumber = parentCommand.LineNumber, UpdateText = "[Please select 'Resume' when ready]"
                    });
                    isFirstWait = false;
                }

                //wait
                System.Threading.Thread.Sleep(2000);
            }



            //bypass comments
            if (parentCommand is Core.AutomationCommands.CommentCommand || parentCommand.IsCommented)
            {
                // bgwRunScript.ReportProgress(0, new object[] { parentCommand.LineNumber, "Skipping Line " + parentCommand.LineNumber + ": " + parentCommand.GetDisplayValue() });
                bgwRunScript.ReportProgress(0, new ProgressUpdate()
                {
                    LineNumber = parentCommand.LineNumber, UpdateText = "Skipping Line " + parentCommand.LineNumber + ": " + parentCommand.GetDisplayValue()
                });
                return;
            }

            //update listbox
            //bgwRunScript.ReportProgress(0, new object[] { parentCommand.LineNumber, "Running Line " + parentCommand.LineNumber + ": " + parentCommand.GetDisplayValue() });
            bgwRunScript.ReportProgress(0, new ProgressUpdate()
            {
                LineNumber = parentCommand.LineNumber, UpdateText = "Running Line " + parentCommand.LineNumber + ": " + parentCommand.GetDisplayValue()
            });


            //handle any errors
            try
            {
                //determine type of command
                if ((parentCommand is Core.AutomationCommands.BeginLoopCommand) || (parentCommand is Core.AutomationCommands.BeginIfCommand))
                {
                    //run the command and pass bgw/command as this command will recursively call this method for sub commands
                    parentCommand.RunCommand(this, command, bgw);
                }
                else
                {
                    //run the command
                    parentCommand.RunCommand(this);
                }
            }
            catch (Exception ex)
            {
                //error occuured so decide what user selected
                if (errorHandling != null)
                {
                    switch (errorHandling.v_ErrorHandlingAction)
                    {
                    case "Continue Processing":
                        //bgwRunScript.ReportProgress(0, new object[] { parentCommand.LineNumber, "Error Occured at Line " + parentCommand.LineNumber + ":" + ex.ToString() });
                        //bgwRunScript.ReportProgress(0, new object[] { parentCommand.LineNumber, "Continuing Per Error Handling" });
                        bgwRunScript.ReportProgress(0, new ProgressUpdate()
                        {
                            LineNumber = parentCommand.LineNumber, UpdateText = "Error Occured at Line " + parentCommand.LineNumber + ":" + ex.ToString()
                        });
                        bgwRunScript.ReportProgress(0, new ProgressUpdate()
                        {
                            LineNumber = parentCommand.LineNumber, UpdateText = "Continuing Per Error Handling"
                        });

                        break;

                    default:
                        throw new Exception(ex.ToString());
                    }
                }
                else
                {
                    throw new Exception(ex.ToString());
                }
            }
        }
Пример #17
0
        public void ExecuteCommand(Core.Script.ScriptAction command)
        {
            //get command
            Core.AutomationCommands.ScriptCommand parentCommand = command.ScriptCommand;

            //update execution line numbers
            LineNumberChanged(parentCommand.LineNumber);

            //handle pause request
            if (parentCommand.PauseBeforeExeucution)
            {
                ReportProgress("Pausing Before Execution");
                IsScriptPaused = true;
            }

            //handle pause
            bool isFirstWait = true;

            while (IsScriptPaused)
            {
                //only show pause first loop
                if (isFirstWait)
                {
                    CurrentStatus = EngineStatus.Paused;
                    ReportProgress("Paused at Line " + parentCommand.LineNumber + " - " + parentCommand.GetDisplayValue());
                    ReportProgress("Paused on Line " + parentCommand.LineNumber + ": " + parentCommand.GetDisplayValue());
                    ReportProgress("[Please select 'Resume' when ready]");
                    isFirstWait = false;
                }

                //wait
                System.Threading.Thread.Sleep(2000);
            }

            CurrentStatus = EngineStatus.Running;

            //handle if cancellation was requested
            if (IsCancellationPending)
            {
                return;
            }


            //bypass comments
            if (parentCommand is Core.AutomationCommands.CommentCommand || parentCommand.IsCommented)
            {
                ReportProgress("Skipping Line " + parentCommand.LineNumber + ": " + parentCommand.GetDisplayValue().ConvertToUserVariable(this));
                return;
            }

            //report intended execution
            ReportProgress("Running Line " + parentCommand.LineNumber + ": " + parentCommand.GetDisplayValue());


            //handle any errors
            try
            {
                //determine type of command
                if ((parentCommand is Core.AutomationCommands.BeginNumberOfTimesLoopCommand) || (parentCommand is Core.AutomationCommands.BeginContinousLoopCommand) || (parentCommand is Core.AutomationCommands.BeginListLoopCommand) || (parentCommand is Core.AutomationCommands.BeginIfCommand) || parentCommand is Core.AutomationCommands.BeginExcelDatasetLoopCommand)
                {
                    //run the command and pass bgw/command as this command will recursively call this method for sub commands
                    parentCommand.RunCommand(this, command);
                }
                else if (parentCommand is Core.AutomationCommands.SequenceCommand)
                {
                    parentCommand.RunCommand(this, command);
                }
                else if (parentCommand is Core.AutomationCommands.StopTaskCommand)
                {
                    IsCancellationPending = true;
                    return;
                }
                else if (parentCommand is Core.AutomationCommands.ExitLoopCommand)
                {
                    CurrentLoopCancelled = true;
                }
                else if (parentCommand is Core.AutomationCommands.SetEngineDelayCommand)
                {
                    //get variable
                    var setEngineCommand = (Core.AutomationCommands.SetEngineDelayCommand)parentCommand;
                    var engineDelay      = setEngineCommand.v_EngineSpeed.ConvertToUserVariable(this);
                    var delay            = int.Parse(engineDelay);

                    //update delay setting
                    this.engineSettings.DelayBetweenCommands = delay;
                }
                else
                {
                    //sleep required time
                    System.Threading.Thread.Sleep(engineSettings.DelayBetweenCommands);

                    //run the command
                    parentCommand.RunCommand(this);
                }
            }
            catch (Exception ex)
            {
                ErrorsOccured.Add(new ScriptError()
                {
                    LineNumber = parentCommand.LineNumber, ErrorMessage = ex.Message, StackTrace = ex.ToString()
                });

                //error occuured so decide what user selected
                if (ErrorHandler != null)
                {
                    switch (ErrorHandler.v_ErrorHandlingAction)
                    {
                    case "Continue Processing":

                        ReportProgress("Error Occured at Line " + parentCommand.LineNumber + ":" + ex.ToString());
                        ReportProgress("Continuing Per Error Handling");

                        break;

                    default:

                        throw new Exception(ex.ToString());
                    }
                }
                else
                {
                    throw new Exception(ex.ToString());
                }
            }
        }
Пример #18
0
        public void GenerateMarkdownFiles()
        {
            //get all commands
            var commandClasses = Assembly.GetExecutingAssembly().GetTypes()
                                 .Where(t => t.Namespace == "taskt.Core.AutomationCommands")
                                 .Where(t => t.Name != "ScriptCommand")
                                 .Where(t => t.IsAbstract == false)
                                 .Where(t => t.BaseType.Name == "ScriptCommand")
                                 .ToList();

            //loop each command
            foreach (var commandClass in commandClasses)
            {
                //instantiate and pull properties from command class
                Core.AutomationCommands.ScriptCommand instantiatedCommand = (Core.AutomationCommands.ScriptCommand)Activator.CreateInstance(commandClass);
                var groupName        = GetClassValue(commandClass, typeof(Core.AutomationCommands.Attributes.ClassAttributes.Group));
                var classDescription = GetClassValue(commandClass, typeof(Core.AutomationCommands.Attributes.ClassAttributes.Description));
                var usesDescription  = GetClassValue(commandClass, typeof(Core.AutomationCommands.Attributes.ClassAttributes.UsesDescription));
                var commandName      = instantiatedCommand.SelectionName;

                //create string builder to build markdown document and append data
                StringBuilder sb = new StringBuilder();
                sb.AppendLine("<!--TITLE: " + commandName + " Command -->");
                sb.AppendLine("<!-- SUBTITLE: a command in the " + groupName + " group -->");
                sb.AppendLine("# " + commandName + " Command");
                sb.AppendLine(Environment.NewLine);

                //append more
                sb.AppendLine("## What does this command do?");
                sb.AppendLine(classDescription);
                sb.AppendLine(Environment.NewLine);

                //more
                sb.AppendLine("## When would I want to use this command?");
                sb.AppendLine(usesDescription);
                sb.AppendLine(Environment.NewLine);

                //build parameter table based on required user inputs
                sb.AppendLine("## Command Parameters");
                sb.AppendLine("| Parameter Question   	| What to input  	|  Sample Data 	| Remarks  	|");
                sb.AppendLine("| ---                    | ---               | ---           | ---       |");

                //loop each property
                foreach (var prop in commandClass.GetProperties().Where(f => f.Name.StartsWith("v_")).ToList())
                {
                    //pull attributes from property
                    var commandLabel       = GetPropertyValue(prop, typeof(Core.AutomationCommands.Attributes.PropertyAttributes.PropertyDescription));
                    var helpfulExplanation = GetPropertyValue(prop, typeof(Core.AutomationCommands.Attributes.PropertyAttributes.InputSpecification));
                    var sampleUsage        = GetPropertyValue(prop, typeof(Core.AutomationCommands.Attributes.PropertyAttributes.SampleUsage));
                    var remarks            = GetPropertyValue(prop, typeof(Core.AutomationCommands.Attributes.PropertyAttributes.Remarks));

                    //append to parameter table
                    sb.AppendLine("|" + commandLabel + "|" + helpfulExplanation + "|" + sampleUsage + "|" + remarks + "|");
                }

                sb.AppendLine(Environment.NewLine);

                //create directory if required
                var docsFolderName = "docs";
                if (!System.IO.Directory.Exists(docsFolderName))
                {
                    System.IO.Directory.CreateDirectory(docsFolderName);
                }

                //create kebob destination and command file nmae
                var kebobDestination = groupName.Replace(" ", "-").Replace("/", "-").ToLower();
                var kebobFileName    = commandName.Replace(" ", "-").Replace("/", "-").ToLower() + "-command.md";

                //create directory if required
                var destinationdirectory = docsFolderName + "\\" + kebobDestination;
                if (!System.IO.Directory.Exists(destinationdirectory))
                {
                    System.IO.Directory.CreateDirectory(destinationdirectory);
                }

                //write file
                var fullFileName = System.IO.Path.Combine(destinationdirectory, kebobFileName);
                System.IO.File.WriteAllText(fullFileName, sb.ToString());
            }
        }