diff --git a/PowerRefresher.csproj b/PowerRefresher.csproj index 2ba889e..68a156f 100644 --- a/PowerRefresher.csproj +++ b/PowerRefresher.csproj @@ -25,7 +25,7 @@ true true 0 - 1.2.0.%2a + 1.3.0.%2a false true true diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index e7524b9..82fe6f2 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.2.0.0")] -[assembly: AssemblyFileVersion("1.2.0.0")] +[assembly: AssemblyVersion("1.3.0.0")] +[assembly: AssemblyFileVersion("1.3.0.0")] diff --git a/README.md b/README.md index effd6c5..6a2007d 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,7 @@ Simply, you have to execute the program and set all the options shown in the use * Language: *Choose your Power BI Desktop application language*

input - **Options** * Refresh all: *Check to refresh all the queries/tables/fields present on the model. If uncheck this option, you have to select which fields want to be updated from the below list.* + * Enable Script Visuals: *Check to allow the application to enable script visuals automatically, if they exist in the file. Only enable script visuals if you trust the author and source.* * Publish: *Check to publish your file into a workspace after it has been updated. You must put the target workspace name in the box next to the checkbox control.* * Close file on finish: *Check to close `*.pbix` file on process finish* * Close application on finish: *Check to close `PowerRefresher` on process finish. If this option is enabled, when the application is closed, a log file will be created and shown with all the update details*

options @@ -92,23 +93,24 @@ Simply, you have to execute the program and set all the options shown in the use Run the **PowerRefresher** application by passing the following arguments: ```batchfile --target=path -timeout=180 -refresh_mode=all/fields -fields="[field1,fieldN]" -publish=bool -workspace=name -closefile=bool -closeapp=bool -pbi_lang=en/es +-target=path -timeout=180 -refresh_mode=all/fields -fields="[field1,fieldN]" -publish=bool -workspace=name -enable_script_visuals=bool -closefile=bool -closeapp=bool -pbi_lang=en/es ``` -| Command | Description | -|--------------|------------------------------------------------| -|`target` |Full pbix file path | -|`timeout` |Waiting timeout in seconds (max. 600) | -|`refresh_mode`|Refresh mode, all or selected fields | -|`fields` |Fields to update | -|`publish` |True if you want to publish file | -|`workspace` |Target workspace name (to publish into) | -|`closefile` |True if you want to close file on finish | -|`closeapp` |True if you want to close app on finish | -|`pbi_lang` |For English use **en**, for Spanish use **es** | +| Command | Description | +|---------------------------|-----------------------------------------------------| +|`target` |Full pbix file path | +|`timeout` |Waiting timeout in seconds (max. 600) | +|`refresh_mode` |Refresh mode, all or selected fields | +|`fields` |Fields to update | +|`publish` |True if you want to publish file | +|`workspace` |Target workspace name (to publish into) | +|`enable_script_visuals` |Allow the app to enable script visuals automatically | +|`closefile` |True if you want to close file on finish | +|`closeapp` |True if you want to close app on finish | +|`pbi_lang` |For English use **en**, for Spanish use **es** | #### Example ```batchfile --target="C:\Users\MyUser\Desktop\My File.pbix" -timeout=180 -refresh_mode=fields -fields="[Table1,Table2]" -publish=true -workspace="My workspace" -closefile=true -closeapp=true -pbi_lang=en +-target="C:\Users\MyUser\Desktop\My File.pbix" -timeout=180 -refresh_mode=fields -fields="[Table1,Table2]" -publish=true -workspace="My workspace" -enable_script_visuals=false -closefile=true -closeapp=true -pbi_lang=en ``` > **Note**: *Remember that you can generate the script from the* `Generate Script` *button.* diff --git a/frmMain.Designer.cs b/frmMain.Designer.cs index 69f900b..a7bf64c 100644 --- a/frmMain.Designer.cs +++ b/frmMain.Designer.cs @@ -33,6 +33,9 @@ private void InitializeComponent() System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmMain)); this.lblTitle = new System.Windows.Forms.Label(); this.gbInput = new System.Windows.Forms.GroupBox(); + this.spanishAppLang = new System.Windows.Forms.RadioButton(); + this.englishAppLang = new System.Windows.Forms.RadioButton(); + this.pbiLangLabel = new System.Windows.Forms.Label(); this.numericTimeout = new System.Windows.Forms.NumericUpDown(); this.lblTimeout = new System.Windows.Forms.Label(); this.cmdSetInput = new System.Windows.Forms.Button(); @@ -57,9 +60,7 @@ private void InitializeComponent() this.cmdStartRefresh = new System.Windows.Forms.Button(); this.helpToolTip = new System.Windows.Forms.ToolTip(this.components); this.cmdGenerateScript = new System.Windows.Forms.Button(); - this.pbiLangLabel = new System.Windows.Forms.Label(); - this.englishAppLang = new System.Windows.Forms.RadioButton(); - this.spanishAppLang = new System.Windows.Forms.RadioButton(); + this.chkEnableScriptVisuals = new System.Windows.Forms.CheckBox(); this.gbInput.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.numericTimeout)).BeginInit(); this.gbOptions.SuspendLayout(); @@ -95,6 +96,39 @@ private void InitializeComponent() this.gbInput.TabStop = false; this.gbInput.Text = "Input"; // + // spanishAppLang + // + this.spanishAppLang.AutoSize = true; + this.spanishAppLang.Location = new System.Drawing.Point(247, 54); + this.spanishAppLang.Name = "spanishAppLang"; + this.spanishAppLang.Size = new System.Drawing.Size(66, 17); + this.spanishAppLang.TabIndex = 4; + this.spanishAppLang.Text = "Spanish"; + this.spanishAppLang.UseVisualStyleBackColor = true; + this.spanishAppLang.CheckedChanged += new System.EventHandler(this.spanishAppLang_CheckedChanged); + // + // englishAppLang + // + this.englishAppLang.AutoSize = true; + this.englishAppLang.Checked = true; + this.englishAppLang.Location = new System.Drawing.Point(182, 54); + this.englishAppLang.Name = "englishAppLang"; + this.englishAppLang.Size = new System.Drawing.Size(63, 17); + this.englishAppLang.TabIndex = 4; + this.englishAppLang.TabStop = true; + this.englishAppLang.Text = "English"; + this.englishAppLang.UseVisualStyleBackColor = true; + this.englishAppLang.CheckedChanged += new System.EventHandler(this.englishAppLang_CheckedChanged); + // + // pbiLangLabel + // + this.pbiLangLabel.AutoSize = true; + this.pbiLangLabel.Location = new System.Drawing.Point(7, 56); + this.pbiLangLabel.Name = "pbiLangLabel"; + this.pbiLangLabel.Size = new System.Drawing.Size(169, 13); + this.pbiLangLabel.TabIndex = 3; + this.pbiLangLabel.Text = "PowerBI Applicaction Language"; + // // numericTimeout // this.numericTimeout.Location = new System.Drawing.Point(391, 22); @@ -159,6 +193,7 @@ private void InitializeComponent() this.gbOptions.Controls.Add(this.lblModelFields); this.gbOptions.Controls.Add(this.chkCloseFileOnFinish); this.gbOptions.Controls.Add(this.chkPublish); + this.gbOptions.Controls.Add(this.chkEnableScriptVisuals); this.gbOptions.Controls.Add(this.chkRefreshAll); this.gbOptions.Location = new System.Drawing.Point(12, 139); this.gbOptions.Name = "gbOptions"; @@ -364,38 +399,16 @@ private void InitializeComponent() this.cmdGenerateScript.UseVisualStyleBackColor = true; this.cmdGenerateScript.Click += new System.EventHandler(this.cmdGenerateScript_Click); // - // pbiLangLabel - // - this.pbiLangLabel.AutoSize = true; - this.pbiLangLabel.Location = new System.Drawing.Point(7, 56); - this.pbiLangLabel.Name = "pbiLangLabel"; - this.pbiLangLabel.Size = new System.Drawing.Size(169, 13); - this.pbiLangLabel.TabIndex = 3; - this.pbiLangLabel.Text = "PowerBI Applicaction Language"; - // - // englishAppLang + // chkEnableScriptVisuals // - this.englishAppLang.AutoSize = true; - this.englishAppLang.Checked = true; - this.englishAppLang.Location = new System.Drawing.Point(182, 54); - this.englishAppLang.Name = "englishAppLang"; - this.englishAppLang.Size = new System.Drawing.Size(63, 17); - this.englishAppLang.TabIndex = 4; - this.englishAppLang.TabStop = true; - this.englishAppLang.Text = "English"; - this.englishAppLang.UseVisualStyleBackColor = true; - this.englishAppLang.CheckedChanged += new System.EventHandler(this.englishAppLang_CheckedChanged); - // - // spanishAppLang - // - this.spanishAppLang.AutoSize = true; - this.spanishAppLang.Location = new System.Drawing.Point(247, 54); - this.spanishAppLang.Name = "spanishAppLang"; - this.spanishAppLang.Size = new System.Drawing.Size(66, 17); - this.spanishAppLang.TabIndex = 4; - this.spanishAppLang.Text = "Spanish"; - this.spanishAppLang.UseVisualStyleBackColor = true; - this.spanishAppLang.CheckedChanged += new System.EventHandler(this.spanishAppLang_CheckedChanged); + this.chkEnableScriptVisuals.AutoSize = true; + this.chkEnableScriptVisuals.Location = new System.Drawing.Point(96, 22); + this.chkEnableScriptVisuals.Name = "chkEnableScriptVisuals"; + this.chkEnableScriptVisuals.Size = new System.Drawing.Size(132, 17); + this.chkEnableScriptVisuals.TabIndex = 0; + this.chkEnableScriptVisuals.Text = "Enable Script Visuals"; + this.helpToolTip.SetToolTip(this.chkEnableScriptVisuals, "Only enable script visuals if you trust the author and source."); + this.chkEnableScriptVisuals.UseVisualStyleBackColor = true; // // frmMain // @@ -462,6 +475,7 @@ private void InitializeComponent() private System.Windows.Forms.RadioButton spanishAppLang; private System.Windows.Forms.RadioButton englishAppLang; private System.Windows.Forms.Label pbiLangLabel; + private System.Windows.Forms.CheckBox chkEnableScriptVisuals; } } diff --git a/frmMain.cs b/frmMain.cs index beb8507..9dedc43 100644 --- a/frmMain.cs +++ b/frmMain.cs @@ -13,6 +13,7 @@ public partial class frmMain : Form //Default Control Strings : English private string REFRESH_BUTTON = "refreshQueries"; private string REFRESH_DIALOG = "modalDialog"; + private string SCRIPT_VISUAL_DIALOG = "MessageDialog"; private string CANCEL_REFRESH_BUTTON = "Close"; private string SAVE_BUTTON = "save"; private string SAVE_WAIT_MESSAGE = "Working on it"; @@ -24,6 +25,7 @@ public partial class frmMain : Form private string REPLACE_DIALOG = "KoPublishWithImpactViewDialog"; private string REPLACE_BUTTON = "Replace"; private string SUCCESS_PUBLISH = "Got it"; + private string ENABLE_BUTTON = "Enable"; private string REFRESH_CONTEXTUAL_MENU = "FieldListMenuItem_RefreshEntity"; @@ -41,6 +43,8 @@ public partial class frmMain : Form private AutomationElement targetWorkspaceElement; private AutomationElement replaceDatasetDialog; private AutomationElement refreshContextualMenu; + private AutomationElement enableScriptVisualsDialog; + private AutomationElement enableScriptVisualsButton; private WindowPattern windowPattern; private InvokePattern invokePattern; @@ -48,11 +52,12 @@ public partial class frmMain : Form private int timeout; private string targetCmd, refreshModeCmd, fieldsCmd, workspaceNameCmd, pbiLangCmd; - private bool publishCmd, closeFileCmd, closeAppCmd, userArgsPassed; + private bool enableScriptVisualsCmd, publishCmd, closeFileCmd, closeAppCmd, userArgsPassed; private int timeoutCmd; private Stopwatch stopWatch; public frmMain() => InitializeComponent(); + private void frmMain_Load(object sender, EventArgs e) { userArgsPassed = false; @@ -60,7 +65,7 @@ private void frmMain_Load(object sender, EventArgs e) if (args.Length == 1) return; - if ((args.Length < 10 && args.Length > 1) || (args.Length > 10 && args.Length > 1) || args[1].Contains("help") || !IsValidArgs() || !GetAndStoreArguments()) + if ((args.Length < 11 && args.Length > 1) || (args.Length > 11 && args.Length > 1) || args[1].Contains("help") || !IsValidArgs() || !GetAndStoreArguments()) { ShowMessage(Properties.Resources.helpMessage, MessageBoxIcon.Information); return; @@ -68,13 +73,14 @@ private void frmMain_Load(object sender, EventArgs e) userArgsPassed = true; } + private void frmMain_Shown(object sender, EventArgs e) { if (userArgsPassed) { SetFormValues(); SetPbiControlStringsByLang(englishAppLang.Checked ? "en" : "es"); - GetFileData(); + if (GetFileData() == false) return; Thread.Sleep(1500); cmdStartRefresh.PerformClick(); } @@ -251,7 +257,7 @@ private void GetApplicationWindowPattern() windowPattern = (WindowPattern)pbi.GetCurrentPattern(WindowPattern.Pattern); windowPattern.SetWindowVisualState(WindowVisualState.Maximized); } - private void GetFileData() + private bool GetFileData() { String windowTitleFilename = null; txtOutput.Text = null; @@ -269,18 +275,59 @@ private void GetFileData() //Selecting field if needed if (refreshModeCmd == "fields") SetModelFieldsFromArgs(); + + //Enable script visual if needed + checkScriptVisuals(); + + return true; + //do + //{ + // Thread.Sleep(500); + // refreshDialog = pbi.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, REFRESH_DIALOG)); + // cancelRefreshButton = pbi.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.HelpTextProperty, CANCEL_REFRESH_BUTTON)); + //} while (refreshDialog != null && cancelRefreshButton == null); + } catch (Exception e) { txtOutput.Text += "[FAILED]\nAn unexpected error has occurred: " + e.Message; SetOutputLineColor(txtOutput.Lines.Length - 1, Color.Red); ShowMessage("An unexpected error has occurred. Check the output for details.", MessageBoxIcon.Error, "Unexpected error"); + return false; + } + } + + private void checkScriptVisuals() + { + timeout = 0; + do + { + timeout += 1; + Thread.Sleep(1000); + enableScriptVisualsDialog = pbi.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, SCRIPT_VISUAL_DIALOG)); + } while (enableScriptVisualsDialog == null || timeout < 5); + if (enableScriptVisualsDialog != null) + { + txtOutput.Text += "\nScript Visuals detected... "; + if (chkEnableScriptVisuals.Checked) + { + enableScriptVisualsButton = enableScriptVisualsDialog.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, ENABLE_BUTTON)); + invokePattern = (InvokePattern)enableScriptVisualsButton.GetCurrentPattern(InvokePattern.Pattern); + invokePattern.Invoke(); + + txtOutput.Text += "Enabled! [DONE]"; + } + else + { + throw new Exception("Visual scripts detected in the file. The application is not authorized to enable them, the process will be aborted."); + } } } + private bool GetAndStoreArguments() { string[] args = Environment.GetCommandLineArgs(); - for (int i = 1; i <= 9; i++) + for (int i = 1; i <= 10; i++) { switch (i) { @@ -308,14 +355,18 @@ private bool GetAndStoreArguments() workspaceNameCmd = publishCmd ? args[i].Replace("-workspace=", null) : null; break; case 7: + if (args[i].Replace("-enable_script_visuals=", null).ToLower() != "false" && args[i].Replace("-enable_script_visuals=", null).ToLower() != "true") return false; + enableScriptVisualsCmd = args[i].Replace("-enable_script_visuals=", null).ToLower() == "true"; + break; + case 8: if (args[i].Replace("-closefile=", null).ToLower() != "false" && args[i].Replace("-closefile=", null).ToLower() != "true") return false; closeFileCmd = args[i].Replace("-closefile=", null).ToLower() == "true"; break; - case 8: + case 9: if (args[i].Replace("-closeapp=", null).ToLower() != "false" && args[i].Replace("-closeapp=", null).ToLower() != "true") return false; closeAppCmd = args[i].Replace("-closeapp=", null).ToLower() == "true"; break; - case 9: + case 10: if (args[i].Replace("-pbi_lang=", null).ToLower() != "en" && args[i].Replace("-pbi_lang=", null).ToLower() != "es") return false; pbiLangCmd = args[i].Replace("-pbi_lang=", null).ToLower(); break; @@ -352,6 +403,8 @@ private void SetPbiControlStringsByLang(string lang) REPLACE_BUTTON = "Reemplazar"; SUCCESS_PUBLISH = "Entendido"; REFRESH_CONTEXTUAL_MENU = "FieldListMenuItem_RefreshEntity"; + SCRIPT_VISUAL_DIALOG = "MessageDialog"; + ENABLE_BUTTON = "Habilitar"; break; case "en": REFRESH_BUTTON = "refreshQueries"; @@ -368,6 +421,8 @@ private void SetPbiControlStringsByLang(string lang) REPLACE_BUTTON = "Replace"; SUCCESS_PUBLISH = "Got it"; REFRESH_CONTEXTUAL_MENU = "FieldListMenuItem_RefreshEntity"; + SCRIPT_VISUAL_DIALOG = "MessageDialog"; + ENABLE_BUTTON = "Enable"; break; default: break; @@ -423,6 +478,7 @@ private void SetFormValues() SetPbiControlStringsByLang(pbiLangCmd); numericTimeout.Value = timeoutCmd; chkRefreshAll.Checked = refreshModeCmd == "all"; + chkEnableScriptVisuals.Checked = enableScriptVisualsCmd; chkPublish.Checked = publishCmd; if (publishCmd) txtWorkspace.Text = workspaceNameCmd; chkCloseFileOnFinish.Checked = closeFileCmd; @@ -445,6 +501,7 @@ private void GenerateScript() commandLineScript += $"-fields=\"{(chkRefreshAll.Checked ? null : GetSelectedFieldsForScript())}\" "; commandLineScript += $"-publish={chkPublish.Checked} "; commandLineScript += $"-workspace=\"{(chkPublish.Checked ? txtWorkspace.Text : null)}\" "; + commandLineScript += $"-enable_script_visuals={chkEnableScriptVisuals.Checked} "; commandLineScript += $"-closefile={chkCloseFileOnFinish.Checked} "; commandLineScript += $"-closeapp={chkCloseAppOnFinish.Checked} "; commandLineScript += $"-pbi_lang={(englishAppLang.Checked ? "en" : "es")}"; @@ -794,7 +851,7 @@ private void FetchFieldsFromModel() private bool IsValidArgs() { string[] args = Environment.GetCommandLineArgs(); - for (int i = 1; i < 9; i++) + for (int i = 1; i < 10; i++) { switch (i) { @@ -817,12 +874,15 @@ private bool IsValidArgs() if (!args[i].Contains("workspace")) return false; break; case 7: - if (!args[i].Contains("closefile")) return false; + if (!args[i].Contains("enable_script_visuals")) return false; break; case 8: - if (!args[i].Contains("closeapp")) return false; + if (!args[i].Contains("closefile")) return false; break; case 9: + if (!args[i].Contains("closeapp")) return false; + break; + case 10: if (!args[i].Contains("pbi_lang")) return false; break; } diff --git a/images/options_gui.png b/images/options_gui.png index 835e280..00f0cb7 100644 Binary files a/images/options_gui.png and b/images/options_gui.png differ diff --git a/images/screen.png b/images/screen.png index e53061e..2addb2d 100644 Binary files a/images/screen.png and b/images/screen.png differ