diff --git a/BismNormalizer/AlmToolkit/AlmToolkit.csproj b/BismNormalizer/AlmToolkit/AlmToolkit.csproj
index ca87ab2..a0a9ec4 100644
--- a/BismNormalizer/AlmToolkit/AlmToolkit.csproj
+++ b/BismNormalizer/AlmToolkit/AlmToolkit.csproj
@@ -42,6 +42,9 @@
app.manifest
+
+ BismNorm.ico
+
..\packages\Microsoft.AnalysisServices.retail.amd64.18.0.5\lib\net45\Microsoft.AnalysisServices.dll
@@ -155,6 +158,7 @@
+
Always
diff --git a/BismNormalizer/AlmToolkit/Images/BismNormalizerLogo.ico b/BismNormalizer/AlmToolkit/BismNorm.ico
similarity index 100%
rename from BismNormalizer/AlmToolkit/Images/BismNormalizerLogo.ico
rename to BismNormalizer/AlmToolkit/BismNorm.ico
diff --git a/BismNormalizer/AlmToolkit/ComparisonForm.Designer.cs b/BismNormalizer/AlmToolkit/ComparisonForm.Designer.cs
index dfdabf5..02cb244 100644
--- a/BismNormalizer/AlmToolkit/ComparisonForm.Designer.cs
+++ b/BismNormalizer/AlmToolkit/ComparisonForm.Designer.cs
@@ -86,22 +86,21 @@
this.StatusBarComparsion.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripStatusLabel1,
this.toolStripProgressBar1});
- this.StatusBarComparsion.Location = new System.Drawing.Point(0, 564);
+ this.StatusBarComparsion.Location = new System.Drawing.Point(0, 810);
this.StatusBarComparsion.Name = "StatusBarComparsion";
- this.StatusBarComparsion.Padding = new System.Windows.Forms.Padding(1, 0, 19, 0);
- this.StatusBarComparsion.Size = new System.Drawing.Size(1100, 22);
+ this.StatusBarComparsion.Size = new System.Drawing.Size(1176, 22);
this.StatusBarComparsion.TabIndex = 48;
this.StatusBarComparsion.Text = "Comparison Status";
//
// toolStripStatusLabel1
//
this.toolStripStatusLabel1.Name = "toolStripStatusLabel1";
- this.toolStripStatusLabel1.Size = new System.Drawing.Size(0, 12);
+ this.toolStripStatusLabel1.Size = new System.Drawing.Size(0, 17);
//
// toolStripProgressBar1
//
this.toolStripProgressBar1.Name = "toolStripProgressBar1";
- this.toolStripProgressBar1.Size = new System.Drawing.Size(133, 12);
+ this.toolStripProgressBar1.Size = new System.Drawing.Size(100, 16);
this.toolStripProgressBar1.Visible = false;
//
// tabHome
@@ -329,7 +328,7 @@
this.pnlRibbon.Location = new System.Drawing.Point(0, 0);
this.pnlRibbon.Margin = new System.Windows.Forms.Padding(1);
this.pnlRibbon.Name = "pnlRibbon";
- this.pnlRibbon.Size = new System.Drawing.Size(1100, 142);
+ this.pnlRibbon.Size = new System.Drawing.Size(1176, 115);
this.pnlRibbon.TabIndex = 49;
//
// maqSoftwareLogo
@@ -338,10 +337,10 @@
this.maqSoftwareLogo.BackColor = System.Drawing.Color.White;
this.maqSoftwareLogo.Cursor = System.Windows.Forms.Cursors.Hand;
this.maqSoftwareLogo.Image = ((System.Drawing.Image)(resources.GetObject("maqSoftwareLogo.Image")));
- this.maqSoftwareLogo.Location = new System.Drawing.Point(681, 39);
+ this.maqSoftwareLogo.Location = new System.Drawing.Point(862, 32);
this.maqSoftwareLogo.Margin = new System.Windows.Forms.Padding(1);
this.maqSoftwareLogo.Name = "maqSoftwareLogo";
- this.maqSoftwareLogo.Size = new System.Drawing.Size(217, 62);
+ this.maqSoftwareLogo.Size = new System.Drawing.Size(163, 50);
this.maqSoftwareLogo.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.maqSoftwareLogo.TabIndex = 3;
this.maqSoftwareLogo.TabStop = false;
@@ -351,10 +350,10 @@
//
this.powerBiLogo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.powerBiLogo.Image = ((System.Drawing.Image)(resources.GetObject("powerBiLogo.Image")));
- this.powerBiLogo.Location = new System.Drawing.Point(895, 34);
+ this.powerBiLogo.Location = new System.Drawing.Point(1022, 28);
this.powerBiLogo.Margin = new System.Windows.Forms.Padding(1);
this.powerBiLogo.Name = "powerBiLogo";
- this.powerBiLogo.Size = new System.Drawing.Size(199, 71);
+ this.powerBiLogo.Size = new System.Drawing.Size(149, 58);
this.powerBiLogo.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.powerBiLogo.TabIndex = 2;
this.powerBiLogo.TabStop = false;
@@ -382,7 +381,7 @@
this.ribbonMain.OrbStyle = System.Windows.Forms.RibbonOrbStyle.Office_2013;
this.ribbonMain.OrbText = "File";
this.ribbonMain.RibbonTabFont = new System.Drawing.Font("Trebuchet MS", 9F);
- this.ribbonMain.Size = new System.Drawing.Size(1100, 111);
+ this.ribbonMain.Size = new System.Drawing.Size(1176, 90);
this.ribbonMain.TabIndex = 1;
this.ribbonMain.Tabs.Add(this.tabHome);
this.ribbonMain.Tabs.Add(this.tabHelp);
@@ -434,10 +433,9 @@
this.pnlHeader.BackColor = System.Drawing.SystemColors.HighlightText;
this.pnlHeader.Controls.Add(this.spltSourceTarget);
this.pnlHeader.Dock = System.Windows.Forms.DockStyle.Top;
- this.pnlHeader.Location = new System.Drawing.Point(0, 142);
- this.pnlHeader.Margin = new System.Windows.Forms.Padding(4);
+ this.pnlHeader.Location = new System.Drawing.Point(0, 115);
this.pnlHeader.Name = "pnlHeader";
- this.pnlHeader.Size = new System.Drawing.Size(1100, 41);
+ this.pnlHeader.Size = new System.Drawing.Size(1176, 33);
this.pnlHeader.TabIndex = 50;
//
// spltSourceTarget
@@ -445,7 +443,6 @@
this.spltSourceTarget.Dock = System.Windows.Forms.DockStyle.Fill;
this.spltSourceTarget.IsSplitterFixed = true;
this.spltSourceTarget.Location = new System.Drawing.Point(0, 0);
- this.spltSourceTarget.Margin = new System.Windows.Forms.Padding(4);
this.spltSourceTarget.Name = "spltSourceTarget";
//
// spltSourceTarget.Panel1
@@ -459,18 +456,16 @@
this.spltSourceTarget.Panel2.Controls.Add(this.txtTarget);
this.spltSourceTarget.Panel2.Controls.Add(this.label2);
this.spltSourceTarget.Panel2.RightToLeft = System.Windows.Forms.RightToLeft.No;
- this.spltSourceTarget.Size = new System.Drawing.Size(1100, 41);
- this.spltSourceTarget.SplitterDistance = 557;
- this.spltSourceTarget.SplitterWidth = 5;
+ this.spltSourceTarget.Size = new System.Drawing.Size(1176, 33);
+ this.spltSourceTarget.SplitterDistance = 594;
this.spltSourceTarget.TabIndex = 45;
//
// label1
//
this.label1.AutoSize = true;
- this.label1.Location = new System.Drawing.Point(3, 10);
- this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.label1.Location = new System.Drawing.Point(2, 8);
this.label1.Name = "label1";
- this.label1.Size = new System.Drawing.Size(51, 16);
+ this.label1.Size = new System.Drawing.Size(41, 13);
this.label1.TabIndex = 39;
this.label1.Text = "Source";
//
@@ -480,10 +475,9 @@
| System.Windows.Forms.AnchorStyles.Right)));
this.txtSource.BackColor = System.Drawing.SystemColors.HighlightText;
this.txtSource.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
- this.txtSource.Location = new System.Drawing.Point(65, 7);
- this.txtSource.Margin = new System.Windows.Forms.Padding(4);
+ this.txtSource.Location = new System.Drawing.Point(49, 6);
this.txtSource.Name = "txtSource";
- this.txtSource.Size = new System.Drawing.Size(439, 22);
+ this.txtSource.Size = new System.Drawing.Size(476, 20);
this.txtSource.TabIndex = 41;
//
// txtTarget
@@ -492,10 +486,9 @@
| System.Windows.Forms.AnchorStyles.Right)));
this.txtTarget.BackColor = System.Drawing.SystemColors.HighlightText;
this.txtTarget.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
- this.txtTarget.Location = new System.Drawing.Point(60, 7);
- this.txtTarget.Margin = new System.Windows.Forms.Padding(4);
+ this.txtTarget.Location = new System.Drawing.Point(45, 6);
this.txtTarget.Name = "txtTarget";
- this.txtTarget.Size = new System.Drawing.Size(437, 22);
+ this.txtTarget.Size = new System.Drawing.Size(451, 20);
this.txtTarget.TabIndex = 42;
//
// label2
@@ -503,28 +496,25 @@
this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label2.AutoSize = true;
- this.label2.Location = new System.Drawing.Point(4, 10);
- this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.label2.Location = new System.Drawing.Point(3, 8);
this.label2.Name = "label2";
- this.label2.Size = new System.Drawing.Size(48, 16);
+ this.label2.Size = new System.Drawing.Size(38, 13);
this.label2.TabIndex = 40;
this.label2.Text = "Target";
//
// ComparisonForm
//
- this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(1100, 586);
+ this.ClientSize = new System.Drawing.Size(1176, 832);
this.Controls.Add(this.pnlHeader);
this.Controls.Add(this.StatusBarComparsion);
this.Controls.Add(this.pnlRibbon);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.KeyPreview = true;
- this.Margin = new System.Windows.Forms.Padding(4);
- this.MinimumSize = new System.Drawing.Size(1017, 583);
+ this.MinimumSize = new System.Drawing.Size(767, 481);
this.Name = "ComparisonForm";
this.Text = "ALM Toolkit for Power BI";
- this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
this.Load += new System.EventHandler(this.ComparisonForm_Load);
this.Shown += new System.EventHandler(this.ComparisonForm_Shown);
this.StatusBarComparsion.ResumeLayout(false);
diff --git a/BismNormalizer/AlmToolkit/ComparisonForm.cs b/BismNormalizer/AlmToolkit/ComparisonForm.cs
index f2a08ca..0255939 100644
--- a/BismNormalizer/AlmToolkit/ComparisonForm.cs
+++ b/BismNormalizer/AlmToolkit/ComparisonForm.cs
@@ -338,7 +338,7 @@ namespace AlmToolkit
private void SetAutoComplete()
{
- if (!_comparisonInfo.ConnectionInfoSource.UseProject && !_comparisonInfo.ConnectionInfoSource.UseBimFile)
+ if (!_comparisonInfo.ConnectionInfoSource.UseProject && !_comparisonInfo.ConnectionInfoSource.UseDesktop && !_comparisonInfo.ConnectionInfoSource.UseBimFile)
{
if (Settings.Default.SourceServerAutoCompleteEntries.IndexOf(_comparisonInfo.ConnectionInfoSource.ServerName + "|") > -1)
{
@@ -354,7 +354,7 @@ namespace AlmToolkit
GetFromAutoCompleteSource();
}
- if (!_comparisonInfo.ConnectionInfoTarget.UseProject && !_comparisonInfo.ConnectionInfoTarget.UseBimFile)
+ if (!_comparisonInfo.ConnectionInfoTarget.UseProject && !_comparisonInfo.ConnectionInfoTarget.UseDesktop && !_comparisonInfo.ConnectionInfoTarget.UseBimFile)
{
if (Settings.Default.TargetServerAutoCompleteEntries.IndexOf(_comparisonInfo.ConnectionInfoTarget.ServerName + "|") > -1)
{
@@ -377,8 +377,32 @@ namespace AlmToolkit
private void PopulateSourceTargetTextBoxes()
{
- txtSource.Text = _comparisonInfo.ConnectionInfoSource.ServerName + ";" + _comparisonInfo.ConnectionInfoSource.DatabaseName;
- txtTarget.Text = _comparisonInfo.ConnectionInfoTarget.ServerName + ";" + _comparisonInfo.ConnectionInfoTarget.DatabaseName;
+ if (_comparisonInfo.ConnectionInfoSource.UseDesktop)
+ {
+ txtSource.Text = "PBI Desktop/SSDT: " + _comparisonInfo.ConnectionInfoSource.DesktopName;
+ }
+ else if (_comparisonInfo.ConnectionInfoSource.UseBimFile)
+ {
+ txtSource.Text = "File: " + _comparisonInfo.ConnectionInfoSource.BimFile;
+ }
+ else
+ {
+ txtSource.Text = "Database: " + _comparisonInfo.ConnectionInfoSource.ServerName + ";" + _comparisonInfo.ConnectionInfoSource.DatabaseName;
+ }
+
+ if (_comparisonInfo.ConnectionInfoTarget.UseDesktop)
+ {
+ txtTarget.Text = "PBI Desktop/SSDT: " + _comparisonInfo.ConnectionInfoTarget.DesktopName;
+ }
+ else if (_comparisonInfo.ConnectionInfoTarget.UseBimFile)
+ {
+ txtTarget.Text = "File: " + _comparisonInfo.ConnectionInfoTarget.BimFile;
+ }
+ else
+ {
+ txtTarget.Text = "Database: " + _comparisonInfo.ConnectionInfoTarget.ServerName + ";" + _comparisonInfo.ConnectionInfoTarget.DatabaseName;
+ }
+
}
private void btnGenerateScript_Click(object sender, EventArgs e)
@@ -742,6 +766,8 @@ namespace AlmToolkit
{
try
{
+ CleanUpConnectionInfo();
+
_fileName = fileName;
XmlSerializer writer = new XmlSerializer(typeof(ComparisonInfo));
StreamWriter file = new System.IO.StreamWriter(fileName);
@@ -755,6 +781,21 @@ namespace AlmToolkit
}
}
+ private void CleanUpConnectionInfo()
+ {
+ if (_comparisonInfo.ConnectionInfoSource.UseDesktop)
+ {
+ _comparisonInfo.ConnectionInfoSource.ServerName = null;
+ _comparisonInfo.ConnectionInfoSource.DatabaseName = null;
+ }
+
+ if (_comparisonInfo.ConnectionInfoTarget.UseDesktop)
+ {
+ _comparisonInfo.ConnectionInfoTarget.ServerName = null;
+ _comparisonInfo.ConnectionInfoTarget.DatabaseName = null;
+ }
+ }
+
private void mnuOpen_Click(object sender, EventArgs e)
{
try
diff --git a/BismNormalizer/AlmToolkit/ComparisonForm.resx b/BismNormalizer/AlmToolkit/ComparisonForm.resx
index da1c8c5..cdef54f 100644
--- a/BismNormalizer/AlmToolkit/ComparisonForm.resx
+++ b/BismNormalizer/AlmToolkit/ComparisonForm.resx
@@ -181,6 +181,44 @@
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAh
NwAAITcBM1ifegAAABNJREFUOE9jGAWjYBSMAjBgYAAABBAAAadEfGMAAAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAABGdBTUEAALGPC/xhBQAAAmBJREFUSEvt
+ l01oE0EUx3P0Ll6868FLRb0J4k1a8CCIF0E8KNGDqAepbWw+JQULhsSCJmjcqBgxLUo3myYtfiRNN9m2
+ pmpiZUvTZm0Sk2pBxXOfb9bd0NCdkO7iIeAffvDmzc77zyyzu7OmjpKQEc5leWElOy1MCWnhkJL+t8ql
+ c7sFfmZDmJ7hkTVkXukyLqfTedDhcJxHzAQmyAzh6jbQEFRSr1NFfirza3OOtF0u10V1nM1mO+N2u3cp
+ ZVvLbrcfDQQCP0dHRiESichwLAfjY/G2UMcQYlwMfD5fCWvuUMrThTO1kQHr39abWBKXQFwQWyIVpS3j
+ PB7PDzTer5Sni2asl843Xiwta+Zp6DZO52fhU3FRji89vAkX7tsbfe2g2zj4agQOO0/DldAgdN8yg1Qu
+ Q7X8FZ4yYWD8jzSZy74zbkzwciE45bsKq5VKI5efz1MpFUuN6zp/c22XzjNeWZWgVqvLsT/xDC4z7kZf
+ O+g2Hnzhh54hM9ie34EuywnIFHJy/u1kEia4SU3Ehb+PnyHjen0Nzt7tgwMDJyEnFuQceZwS0QkqZGcb
+ NjbKf2OqWhk/fvMS7JFhzT4auo2HY0+gP3wbwikW9vUeh+RHQc7Lr8f3BU3I5jNsXKlWoQc/DnuudUNi
+ LiXnSGHmXogKn8wYNyYsf5Fg9vOHply7dPbm0sN2jC3x8bhmET3g8fY7ntO7lPJ04eyOBB8Ef7NjLNCI
+ stEmuCi3BXLXCF6vt4aH+p1K+dayWq3HcOW9BJzIdQLGfSrY7idgbCFgfEMF2wMEjK0E/JvYq5TdJJPp
+ D5oiqINNnQHQAAAAAElFTkSuQmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAABGdBTUEAALGPC/xhBQAAAmBJREFUSEvt
+ l01oE0EUx3P0Ll6868FLRb0J4k1a8CCIF0E8KNGDqAepbWw+JQULhsSCJmjcqBgxLUo3myYtfiRNN9m2
+ pmpiZUvTZm0Sk2pBxXOfb9bd0NCdkO7iIeAffvDmzc77zyyzu7OmjpKQEc5leWElOy1MCWnhkJL+t8ql
+ c7sFfmZDmJ7hkTVkXukyLqfTedDhcJxHzAQmyAzh6jbQEFRSr1NFfirza3OOtF0u10V1nM1mO+N2u3cp
+ ZVvLbrcfDQQCP0dHRiESichwLAfjY/G2UMcQYlwMfD5fCWvuUMrThTO1kQHr39abWBKXQFwQWyIVpS3j
+ PB7PDzTer5Sni2asl843Xiwta+Zp6DZO52fhU3FRji89vAkX7tsbfe2g2zj4agQOO0/DldAgdN8yg1Qu
+ Q7X8FZ4yYWD8jzSZy74zbkzwciE45bsKq5VKI5efz1MpFUuN6zp/c22XzjNeWZWgVqvLsT/xDC4z7kZf
+ O+g2Hnzhh54hM9ie34EuywnIFHJy/u1kEia4SU3Ehb+PnyHjen0Nzt7tgwMDJyEnFuQceZwS0QkqZGcb
+ NjbKf2OqWhk/fvMS7JFhzT4auo2HY0+gP3wbwikW9vUeh+RHQc7Lr8f3BU3I5jNsXKlWoQc/DnuudUNi
+ LiXnSGHmXogKn8wYNyYsf5Fg9vOHply7dPbm0sN2jC3x8bhmET3g8fY7ntO7lPJ04eyOBB8Ef7NjLNCI
+ stEmuCi3BXLXCF6vt4aH+p1K+dayWq3HcOW9BJzIdQLGfSrY7idgbCFgfEMF2wMEjK0E/JvYq5TdJJPp
+ D5oiqINNnQHQAAAAAElFTkSuQmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAh
+ NwAAITcBM1ifegAAABNJREFUOE9jGAWjYBSMAjBgYAAABBAAAadEfGMAAAAASUVORK5CYII=
@@ -343,44 +381,6 @@
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAh
NwAAITcBM1ifegAAABNJREFUOE9jGAWjYBSMAjBgYAAABBAAAadEfGMAAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAABGdBTUEAALGPC/xhBQAAAmBJREFUSEvt
- l01oE0EUx3P0Ll6868FLRb0J4k1a8CCIF0E8KNGDqAepbWw+JQULhsSCJmjcqBgxLUo3myYtfiRNN9m2
- pmpiZUvTZm0Sk2pBxXOfb9bd0NCdkO7iIeAffvDmzc77zyyzu7OmjpKQEc5leWElOy1MCWnhkJL+t8ql
- c7sFfmZDmJ7hkTVkXukyLqfTedDhcJxHzAQmyAzh6jbQEFRSr1NFfirza3OOtF0u10V1nM1mO+N2u3cp
- ZVvLbrcfDQQCP0dHRiESichwLAfjY/G2UMcQYlwMfD5fCWvuUMrThTO1kQHr39abWBKXQFwQWyIVpS3j
- PB7PDzTer5Sni2asl843Xiwta+Zp6DZO52fhU3FRji89vAkX7tsbfe2g2zj4agQOO0/DldAgdN8yg1Qu
- Q7X8FZ4yYWD8jzSZy74zbkzwciE45bsKq5VKI5efz1MpFUuN6zp/c22XzjNeWZWgVqvLsT/xDC4z7kZf
- O+g2Hnzhh54hM9ie34EuywnIFHJy/u1kEia4SU3Ehb+PnyHjen0Nzt7tgwMDJyEnFuQceZwS0QkqZGcb
- NjbKf2OqWhk/fvMS7JFhzT4auo2HY0+gP3wbwikW9vUeh+RHQc7Lr8f3BU3I5jNsXKlWoQc/DnuudUNi
- LiXnSGHmXogKn8wYNyYsf5Fg9vOHply7dPbm0sN2jC3x8bhmET3g8fY7ntO7lPJ04eyOBB8Ef7NjLNCI
- stEmuCi3BXLXCF6vt4aH+p1K+dayWq3HcOW9BJzIdQLGfSrY7idgbCFgfEMF2wMEjK0E/JvYq5TdJJPp
- D5oiqINNnQHQAAAAAElFTkSuQmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAABGdBTUEAALGPC/xhBQAAAmBJREFUSEvt
- l01oE0EUx3P0Ll6868FLRb0J4k1a8CCIF0E8KNGDqAepbWw+JQULhsSCJmjcqBgxLUo3myYtfiRNN9m2
- pmpiZUvTZm0Sk2pBxXOfb9bd0NCdkO7iIeAffvDmzc77zyyzu7OmjpKQEc5leWElOy1MCWnhkJL+t8ql
- c7sFfmZDmJ7hkTVkXukyLqfTedDhcJxHzAQmyAzh6jbQEFRSr1NFfirza3OOtF0u10V1nM1mO+N2u3cp
- ZVvLbrcfDQQCP0dHRiESichwLAfjY/G2UMcQYlwMfD5fCWvuUMrThTO1kQHr39abWBKXQFwQWyIVpS3j
- PB7PDzTer5Sni2asl843Xiwta+Zp6DZO52fhU3FRji89vAkX7tsbfe2g2zj4agQOO0/DldAgdN8yg1Qu
- Q7X8FZ4yYWD8jzSZy74zbkzwciE45bsKq5VKI5efz1MpFUuN6zp/c22XzjNeWZWgVqvLsT/xDC4z7kZf
- O+g2Hnzhh54hM9ie34EuywnIFHJy/u1kEia4SU3Ehb+PnyHjen0Nzt7tgwMDJyEnFuQceZwS0QkqZGcb
- NjbKf2OqWhk/fvMS7JFhzT4auo2HY0+gP3wbwikW9vUeh+RHQc7Lr8f3BU3I5jNsXKlWoQc/DnuudUNi
- LiXnSGHmXogKn8wYNyYsf5Fg9vOHply7dPbm0sN2jC3x8bhmET3g8fY7ntO7lPJ04eyOBB8Ef7NjLNCI
- stEmuCi3BXLXCF6vt4aH+p1K+dayWq3HcOW9BJzIdQLGfSrY7idgbCFgfEMF2wMEjK0E/JvYq5TdJJPp
- D5oiqINNnQHQAAAAAElFTkSuQmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAh
- NwAAITcBM1ifegAAABNJREFUOE9jGAWjYBSMAjBgYAAABBAAAadEfGMAAAAASUVORK5CYII=
diff --git a/BismNormalizer/AlmToolkit/Images/BismNorm.ico b/BismNormalizer/AlmToolkit/Images/BismNorm.ico
new file mode 100644
index 0000000..523c7aa
Binary files /dev/null and b/BismNormalizer/AlmToolkit/Images/BismNorm.ico differ
diff --git a/BismNormalizer/AlmToolkit/Images/PBIReportServer.png b/BismNormalizer/AlmToolkit/Images/PBIReportServer.png
new file mode 100644
index 0000000..78898e0
Binary files /dev/null and b/BismNormalizer/AlmToolkit/Images/PBIReportServer.png differ
diff --git a/BismNormalizer/AlmToolkit/Images/devenv.png b/BismNormalizer/AlmToolkit/Images/devenv.png
new file mode 100644
index 0000000..22b714b
Binary files /dev/null and b/BismNormalizer/AlmToolkit/Images/devenv.png differ
diff --git a/BismNormalizer/AlmToolkit/Images/powerBI2.png b/BismNormalizer/AlmToolkit/Images/powerBI2.png
new file mode 100644
index 0000000..63dab84
Binary files /dev/null and b/BismNormalizer/AlmToolkit/Images/powerBI2.png differ
diff --git a/BismNormalizer/AlmToolkit/ManagedIpHelper.cs b/BismNormalizer/AlmToolkit/ManagedIpHelper.cs
new file mode 100644
index 0000000..2e3c913
--- /dev/null
+++ b/BismNormalizer/AlmToolkit/ManagedIpHelper.cs
@@ -0,0 +1,282 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.NetworkInformation;
+using System.Runtime.InteropServices;
+
+namespace AlmToolkit
+{
+
+
+ #region Managed IP Helper API
+
+ public class TcpTable : IEnumerable
+ {
+ #region Private Fields
+
+ private IEnumerable tcpRows;
+
+ #endregion
+
+ #region Constructors
+
+ public TcpTable(IEnumerable tcpRows)
+ {
+ this.tcpRows = tcpRows;
+ }
+
+ #endregion
+
+ #region Public Properties
+
+ public IEnumerable Rows
+ {
+ get { return this.tcpRows; }
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ public IEnumerator GetEnumerator()
+ {
+ return this.tcpRows.GetEnumerator();
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return this.tcpRows.GetEnumerator();
+ }
+
+ #endregion
+ }
+
+ public class TcpRow
+ {
+ #region Private Fields
+
+ private IPEndPoint localEndPoint;
+ private IPEndPoint remoteEndPoint;
+ private TcpState state;
+ private int processId;
+
+ #endregion
+
+ #region Constructors
+
+ public TcpRow(IpHelper.TcpRow tcpRow)
+ {
+ this.state = tcpRow.state;
+ this.processId = tcpRow.owningPid;
+
+ int localPort = (tcpRow.localPort1 << 8) + (tcpRow.localPort2) + (tcpRow.localPort3 << 24) + (tcpRow.localPort4 << 16);
+ long localAddress = tcpRow.localAddr;
+ this.localEndPoint = new IPEndPoint(localAddress, localPort);
+
+ int remotePort = (tcpRow.remotePort1 << 8) + (tcpRow.remotePort2) + (tcpRow.remotePort3 << 24) + (tcpRow.remotePort4 << 16);
+ long remoteAddress = tcpRow.remoteAddr;
+ this.remoteEndPoint = new IPEndPoint(remoteAddress, remotePort);
+ }
+
+ #endregion
+
+ #region Public Properties
+
+ public IPEndPoint LocalEndPoint
+ {
+ get { return this.localEndPoint; }
+ }
+
+ public IPEndPoint RemoteEndPoint
+ {
+ get { return this.remoteEndPoint; }
+ }
+
+ public TcpState State
+ {
+ get { return this.state; }
+ }
+
+ public int ProcessId
+ {
+ get { return this.processId; }
+ }
+
+ #endregion
+ }
+
+ public static class ManagedIpHelper
+ {
+ #region Public Methods
+
+ public static TcpTable GetExtendedTcpTable(bool sorted)
+ {
+ List tcpRows = new List();
+
+ IntPtr tcpTable = IntPtr.Zero;
+ int tcpTableLength = 0;
+
+ if (IpHelper.GetExtendedTcpTable(tcpTable, ref tcpTableLength, sorted, IpHelper.AfInet, IpHelper.TcpTableType.OwnerPidAll, 0) != 0)
+ {
+ try
+ {
+ tcpTable = Marshal.AllocHGlobal(tcpTableLength);
+ if (IpHelper.GetExtendedTcpTable(tcpTable, ref tcpTableLength, true, IpHelper.AfInet, IpHelper.TcpTableType.OwnerPidAll, 0) == 0)
+ {
+ IpHelper.TcpTable table = (IpHelper.TcpTable)Marshal.PtrToStructure(tcpTable, typeof(IpHelper.TcpTable));
+
+ IntPtr rowPtr = (IntPtr)((long)tcpTable + Marshal.SizeOf(table.length));
+ for (int i = 0; i < table.length; ++i)
+ {
+ tcpRows.Add(new TcpRow((IpHelper.TcpRow)Marshal.PtrToStructure(rowPtr, typeof(IpHelper.TcpRow))));
+ rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(typeof(IpHelper.TcpRow)));
+ }
+ }
+ }
+ finally
+ {
+ if (tcpTable != IntPtr.Zero)
+ {
+ Marshal.FreeHGlobal(tcpTable);
+ }
+ }
+ }
+
+ return new TcpTable(tcpRows);
+ }
+
+ public static Dictionary GetExtendedTcpDictionary()
+ {
+ Dictionary tcpRows = new Dictionary();
+
+ IntPtr tcpTable = IntPtr.Zero;
+ int tcpTableLength = 0;
+
+ if (IpHelper.GetExtendedTcpTable(tcpTable, ref tcpTableLength, false, IpHelper.AfInet, IpHelper.TcpTableType.OwnerPidAll, 0) != 0)
+ {
+ try
+ {
+ tcpTable = Marshal.AllocHGlobal(tcpTableLength);
+ if (IpHelper.GetExtendedTcpTable(tcpTable, ref tcpTableLength, true, IpHelper.AfInet, IpHelper.TcpTableType.OwnerPidAll, 0) == 0)
+ {
+ IpHelper.TcpTable table = (IpHelper.TcpTable)Marshal.PtrToStructure(tcpTable, typeof(IpHelper.TcpTable));
+
+ IntPtr rowPtr = (IntPtr)((long)tcpTable + Marshal.SizeOf(table.length));
+ for (int i = 0; i < table.length; ++i)
+ {
+ TcpRow row = new TcpRow((IpHelper.TcpRow)Marshal.PtrToStructure(rowPtr, typeof(IpHelper.TcpRow)));
+ // HACK: only add first row that is in a Listening state
+ if (row.State == TcpState.Listen)
+ {
+ if (!tcpRows.Keys.Contains(row.ProcessId))
+ tcpRows.Add(row.ProcessId, row);
+ }
+ rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(typeof(IpHelper.TcpRow)));
+ }
+ }
+ }
+ finally
+ {
+ if (tcpTable != IntPtr.Zero)
+ {
+ Marshal.FreeHGlobal(tcpTable);
+ }
+ }
+ }
+
+ return tcpRows;
+ }
+
+
+ #endregion
+ }
+
+ #endregion
+
+ #region P/Invoke IP Helper API
+
+ ///
+ ///
+ ///
+ public static class IpHelper
+ {
+ #region Public Fields
+
+ public const string DllName = "iphlpapi.dll";
+ public const int AfInet = 2;
+
+ #endregion
+
+ #region Public Methods
+
+ ///
+ ///
+ ///
+ [DllImport(IpHelper.DllName, SetLastError = true)]
+ public static extern uint GetExtendedTcpTable(IntPtr tcpTable, ref int tcpTableLength, bool sort, int ipVersion, TcpTableType tcpTableType, int reserved);
+
+ #endregion
+
+ #region Public Enums
+
+ ///
+ ///
+ ///
+ public enum TcpTableType
+ {
+ BasicListener,
+ BasicConnections,
+ BasicAll,
+ OwnerPidListener,
+ OwnerPidConnections,
+ OwnerPidAll,
+ OwnerModuleListener,
+ OwnerModuleConnections,
+ OwnerModuleAll,
+ }
+
+ #endregion
+
+ #region Public Structs
+
+ ///
+ ///
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct TcpTable
+ {
+ public uint length;
+ public TcpRow row;
+ }
+
+ ///
+ ///
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct TcpRow
+ {
+ public TcpState state;
+ public uint localAddr;
+ public byte localPort1;
+ public byte localPort2;
+ public byte localPort3;
+ public byte localPort4;
+ public uint remoteAddr;
+ public byte remotePort1;
+ public byte remotePort2;
+ public byte remotePort3;
+ public byte remotePort4;
+ public int owningPid;
+ }
+
+ #endregion
+
+ #endregion
+ }
+}
diff --git a/BismNormalizer/AlmToolkit/PowerBIHelper.cs b/BismNormalizer/AlmToolkit/PowerBIHelper.cs
new file mode 100644
index 0000000..8384ba7
--- /dev/null
+++ b/BismNormalizer/AlmToolkit/PowerBIHelper.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+//using Serilog;
+using System.Security.Principal;
+
+namespace AlmToolkit
+{
+ public enum EmbeddedSSASIcon
+ {
+ PowerBI,
+ Devenv,
+ PowerBIReportServer,
+ Loading
+ }
+ public class PowerBIInstance
+ {
+ public PowerBIInstance(string name, int port, EmbeddedSSASIcon icon)
+ {
+ Port = port;
+ Icon = icon;
+ try
+ {
+ var dashPos = name.LastIndexOf(" - ");
+ if (dashPos >= 0)
+ { Name = name.Substring(0, dashPos); } // Strip "Power BI Designer" or "Power BI Desktop" off the end of the string
+ else
+ {
+ //Log.Warning("{class} {method} {message} {dashPos}", "PowerBIInstance", "ctor", $"Unable to find ' - ' in Power BI title '{name}'", dashPos);
+ Name = name;
+ }
+ }
+ catch (Exception ex)
+ {
+ //Log.Error("{class} {method} {message} {stacktrace}", "PowerBIInstance", "ctor", ex.Message, ex.StackTrace);
+ Name = name;
+ }
+ }
+ public int Port { get; private set; }
+ public string Name { get; private set; }
+
+ public EmbeddedSSASIcon Icon { get; private set; }
+ }
+
+ public class PowerBIHelper
+ {
+
+ public static List GetLocalInstances()
+ {
+ List _instances = new List();
+
+ _instances.Clear();
+
+ var dict = ManagedIpHelper.GetExtendedTcpDictionary();
+ foreach (var proc in Process.GetProcessesByName("msmdsrv"))
+ {
+ int _port = 0;
+ EmbeddedSSASIcon _icon = EmbeddedSSASIcon.PowerBI;
+ var parent = proc.GetParent();
+
+ // exit here if the parent == "services" then this is a SSAS instance
+ if (parent.ProcessName.Equals("services", StringComparison.OrdinalIgnoreCase)) continue;
+
+ // exit here if the parent == "RSHostingService" then this is a SSAS instance
+ if (parent.ProcessName.Equals("RSHostingService", StringComparison.OrdinalIgnoreCase))
+ {
+ // only show PBI Report Server if we are running as admin
+ // otherwise we won't have any access to the models
+ if (IsAdministrator())
+ _icon = EmbeddedSSASIcon.PowerBIReportServer;
+ else
+ continue;
+ }
+
+ // if the process was launched from Visual Studio change the icon
+ if (parent.ProcessName.Equals("devenv", StringComparison.OrdinalIgnoreCase)) _icon = EmbeddedSSASIcon.Devenv;
+
+ // get the window title so that we can parse out the file name
+ var parentTitle = parent.MainWindowTitle;
+ if (parentTitle.Length == 0)
+ {
+ // for minimized windows we need to use some Win32 api calls to get the title
+ //parentTitle = WindowTitle.GetWindowTitleTimeout( parent.Id, 300);
+ parentTitle = WindowTitle.GetWindowTitle(parent.Id);
+ }
+
+ // try and get the tcp port from the Win32 TcpTable API
+ try
+ {
+ TcpRow tcpRow = null;
+ dict.TryGetValue(proc.Id, out tcpRow);
+ if (tcpRow != null)
+ {
+ _port = tcpRow.LocalEndPoint.Port;
+ _instances.Add(new PowerBIInstance(parentTitle, _port, _icon));
+ //Log.Debug("{class} {method} PowerBI found on port: {port}", "PowerBIHelper", "Refresh", _port);
+ }
+ else
+ {
+ //Log.Debug("{class} {method} PowerBI port not found for process: {processName} PID: {pid}", "PowerBIHelper", "Refresh", proc.ProcessName, proc.Id);
+ }
+
+ }
+ catch (Exception ex)
+ {
+ //Log.Error("{class} {Method} {Error} {StackTrace}", "PowerBIHelper", "Refresh", ex.Message, ex.StackTrace);
+ }
+
+ }
+ return _instances;
+ }
+
+ public static bool IsAdministrator()
+ {
+ WindowsIdentity identity = WindowsIdentity.GetCurrent();
+ WindowsPrincipal principal = new WindowsPrincipal(identity);
+ return principal.IsInRole(WindowsBuiltInRole.Administrator);
+ }
+
+
+ }
+}
diff --git a/BismNormalizer/AlmToolkit/ProcessExtensions.cs b/BismNormalizer/AlmToolkit/ProcessExtensions.cs
new file mode 100644
index 0000000..8057c5d
--- /dev/null
+++ b/BismNormalizer/AlmToolkit/ProcessExtensions.cs
@@ -0,0 +1,31 @@
+using System.Diagnostics;
+using System.Linq;
+using System.Management;
+
+namespace AlmToolkit
+{
+ public static class ProcessExtensions
+ {
+ public static Process GetParent(this Process process)
+ {
+ try
+ {
+ using (var query = new ManagementObjectSearcher(
+ "SELECT ParentProcessId " +
+ "FROM Win32_Process " +
+ "WHERE ProcessId=" + process.Id))
+ {
+ return query
+ .Get()
+ .OfType()
+ .Select(p => Process.GetProcessById((int)(uint)p["ParentProcessId"]))
+ .FirstOrDefault();
+ }
+ }
+ catch
+ {
+ return null;
+ }
+ }
+ }
+}
diff --git a/BismNormalizer/AlmToolkit/WindowTitle.cs b/BismNormalizer/AlmToolkit/WindowTitle.cs
new file mode 100644
index 0000000..15de05a
--- /dev/null
+++ b/BismNormalizer/AlmToolkit/WindowTitle.cs
@@ -0,0 +1,161 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AlmToolkit
+{
+ public class WindowTitle
+ {
+
+
+ //static void Main(string[] args)
+ //{
+ // var p = Process.GetProcessById(3484);
+ // var h = p.MainWindowHandle;
+
+ // string s = GetWindowTextTimeout(h, 100 /*msec*/);
+
+ //}
+
+
+
+ #region PInvoke calls to get the window title of a minimize window
+
+ delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);
+
+ [DllImport("user32.dll")]
+ static extern bool IsWindowVisible(IntPtr hWnd);
+
+
+ [DllImport("user32.dll")]
+ static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn,
+ IntPtr lParam);
+
+ [DllImport("User32.dll", SetLastError = true)]
+ public unsafe static extern int SendMessageTimeout(
+ IntPtr hWnd,
+ uint uMsg,
+ uint wParam,
+ StringBuilder lParam,
+ uint fuFlags,
+ uint uTimeout,
+ void* lpdwResult);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
+ static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam,
+ StringBuilder lParam);
+
+ [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ static extern int GetWindowTextLength(IntPtr hWnd);
+
+ [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ static extern long GetWindowText(IntPtr hwnd, StringBuilder lpString, long cch);
+
+ const int WM_GETTEXT = 0x000D;
+ const int WM_GETTEXTLENGTH = 0x000E;
+
+ #endregion
+
+
+ private static IEnumerable EnumerateProcessWindowHandles(int processId)
+ {
+ var handles = new List();
+
+ foreach (ProcessThread thread in Process.GetProcessById(processId).Threads)
+ EnumThreadWindows(thread.Id,
+ (hWnd, lParam) => { handles.Add(hWnd); return true; }, IntPtr.Zero);
+
+ return handles;
+ }
+
+
+ public static string GetWindowTitle(int procId)
+ {
+ foreach (var handle in EnumerateProcessWindowHandles(procId))
+ {
+ StringBuilder message = new StringBuilder(1000);
+ if (IsWindowVisible(handle))
+ {
+ //SendMessage(handle, WM_GETTEXT, message.Capacity, message);
+ //if (message.Length > 0) return message.ToString();
+ return GetCaptionOfWindow(handle);
+ }
+
+ }
+ return "";
+ }
+
+ /* ====================================== */
+
+ public static string GetWindowTitleTimeout(int procId, uint timeout)
+ {
+ string title = "";
+ foreach (var handle in EnumerateProcessWindowHandles(procId))
+ {
+ try
+ {
+ // if there is an issue with the window handle we just
+ // ignore it and skip to the next one in the collection
+ title = GetWindowTextTimeout(handle, timeout);
+ }
+ catch
+ {
+ title = "";
+ }
+ if (title.Length > 0) return title;
+ }
+ return title;
+ }
+
+
+ private static unsafe string GetWindowTextTimeout(IntPtr hWnd, uint timeout)
+ {
+ int length;
+ if (SendMessageTimeout(hWnd, WM_GETTEXTLENGTH, 0, null, 2, timeout, &length) == 0)
+ {
+ return null;
+ }
+ if (length == 0)
+ {
+ return null;
+ }
+
+ StringBuilder sb = new StringBuilder(length + 1); // leave room for null-terminator
+ if (SendMessageTimeout(hWnd, WM_GETTEXT, (uint)sb.Capacity, sb, 2, timeout, null) == 0)
+ {
+ return null;
+ }
+
+ return sb.ToString();
+ }
+
+ private static string GetCaptionOfWindow(IntPtr hwnd)
+ {
+ string caption = "";
+ StringBuilder windowText = null;
+ try
+ {
+ int max_length = GetWindowTextLength(hwnd);
+ windowText = new StringBuilder("", max_length + 5);
+ GetWindowText(hwnd, windowText, max_length + 2);
+
+ if (!String.IsNullOrEmpty(windowText.ToString()) && !String.IsNullOrWhiteSpace(windowText.ToString()))
+ caption = windowText.ToString();
+ }
+ catch (Exception ex)
+ {
+ caption = ex.Message;
+ }
+ finally
+ {
+ windowText = null;
+ }
+ return caption;
+ }
+
+ }
+}
diff --git a/BismNormalizer/BismNormalizer/BismNormalizer.csproj b/BismNormalizer/BismNormalizer/BismNormalizer.csproj
index 3196f54..5a3276a 100644
--- a/BismNormalizer/BismNormalizer/BismNormalizer.csproj
+++ b/BismNormalizer/BismNormalizer/BismNormalizer.csproj
@@ -62,6 +62,7 @@
true
+ true
true
@@ -73,6 +74,7 @@
4
true
true
+ true
@@ -248,6 +250,10 @@
Connections.cs
+
+
+
+
Form
diff --git a/BismNormalizer/BismNormalizer/TabularCompare/ComparisonFactory.cs b/BismNormalizer/BismNormalizer/TabularCompare/ComparisonFactory.cs
index 30d0b45..68f9c26 100644
--- a/BismNormalizer/BismNormalizer/TabularCompare/ComparisonFactory.cs
+++ b/BismNormalizer/BismNormalizer/TabularCompare/ComparisonFactory.cs
@@ -73,6 +73,18 @@ namespace BismNormalizer.TabularCompare
#region Data-source versions check
+ //Check not working with Desktop and not V3
+ if (comparisonInfo.ConnectionInfoSource.ServerName != null && comparisonInfo.ConnectionInfoSource.ServerMode == ServerMode.SharePoint && !_supportedDataSourceVersions.Contains(comparisonInfo.SourceDataSourceVersion))
+ {
+ string message = $"The source is a Power BI Desktop dataset with default data-source version of {comparisonInfo.SourceDataSourceVersion}, which is not supported for comparison. Please ensure you're using the latest version of Power BI Desktop and if necessary enable the preview feature.";
+ throw new ConnectionException(message);
+ }
+ if (comparisonInfo.ConnectionInfoTarget.ServerName != null && comparisonInfo.ConnectionInfoTarget.ServerMode == ServerMode.SharePoint && !_supportedDataSourceVersions.Contains(comparisonInfo.TargetDataSourceVersion))
+ {
+ string message = $"The target is a Power BI Desktop dataset with default data-source version of {comparisonInfo.TargetDataSourceVersion}, which is not supported for comparison. Please ensure you're using the latest version of Power BI Desktop and if necessary enable the preview feature.";
+ throw new ConnectionException(message);
+ }
+
//If Power BI, check the default datasource version
//Source
bool sourceDataSourceVersionRequiresUpgrade = false;
@@ -107,7 +119,7 @@ namespace BismNormalizer.TabularCompare
}
else if (targetDataSourceVersionRequiresUpgrade)
{
- string message = $"The target is a Power BI datasets with default data-source version of {comparisonInfo.TargetDataSourceVersion}, which is not supported for comparison.";
+ string message = $"The target is a Power BI dataset with default data-source version of {comparisonInfo.TargetDataSourceVersion}, which is not supported for comparison.";
if (comparisonInfo.Interactive && System.Windows.Forms.MessageBox.Show(
message += $"\nDo you want to upgrade it to {_supportedDataSourceVersions[0]} and allow the comparison?\n\nNOTE: this is a irreversible operation and you may not be able to download the PBIX file(s) to Power BI Desktop. You should only do this if you have the original PBIX as a backup.", comparisonInfo.AppName, System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question) != System.Windows.Forms.DialogResult.Yes)
{
diff --git a/BismNormalizer/BismNormalizer/TabularCompare/ConnectionInfo.cs b/BismNormalizer/BismNormalizer/TabularCompare/ConnectionInfo.cs
index 3d0a937..12767f0 100644
--- a/BismNormalizer/BismNormalizer/TabularCompare/ConnectionInfo.cs
+++ b/BismNormalizer/BismNormalizer/TabularCompare/ConnectionInfo.cs
@@ -19,15 +19,18 @@ namespace BismNormalizer.TabularCompare
{
#region Private Variables
- private bool _useProject = false;
+ private bool _useProject = false; //Missed the boat to have an enum would break backwards compat with .bism file
private bool _useBimFile = false;
+ private bool _useDesktop = false;
private string _bimFile;
+ private string _desktopName;
private string _serverName;
private string _databaseName;
private string _projectName;
private string _projectFile;
private int _compatibilityLevel;
private string _dataSourceVersion;
+ private ServerMode _serverMode;
private bool _directQuery;
private string _ssdtBimFile;
private EnvDTE.Project _project;
@@ -62,12 +65,33 @@ namespace BismNormalizer.TabularCompare
{
//To late to do an enum would break backwards compat
_useBimFile = false;
+ _useDesktop = false;
_bimFile = null;
}
_useProject = value;
}
}
+ ///
+ /// A Boolean specifying whether the connection represents a Power BI Desktop or SSDT workspace AS instance.
+ ///
+ [XmlIgnore()]
+ public bool UseDesktop
+ {
+ get { return _useDesktop; }
+ set
+ {
+ if (value)
+ {
+ //To late to do an enum would break backwards compat
+ _useProject = false;
+ _useBimFile = false;
+ _bimFile = null;
+ }
+ _useDesktop = value;
+ }
+ }
+
///
/// A Boolean specifying whether the connection represents a BIM file.
///
@@ -87,6 +111,16 @@ namespace BismNormalizer.TabularCompare
}
}
+ ///
+ /// Name of the PBIX or SSDT project to which workspace AS instance connected.
+ ///
+ [XmlIgnore()]
+ public string DesktopName
+ {
+ get { return _desktopName; }
+ set { _desktopName = value; }
+ }
+
///
/// Name of the server on which the tabular model resides.
///
@@ -154,6 +188,12 @@ namespace BismNormalizer.TabularCompare
[XmlIgnore()]
public string DataSourceVersion => _dataSourceVersion;
+ ///
+ /// Server mode of the connection.
+ ///
+ [XmlIgnore()]
+ public ServerMode ServerMode => _serverMode;
+
///
/// A Boolean specifying whether the tabular model for the connection is running in DirectQuery mode.
///
@@ -508,7 +548,20 @@ namespace BismNormalizer.TabularCompare
throw new ConnectionException($"Analysis Server {this.ServerName} is not running in Tabular mode");
}
- Database amoDatabase = amoServer.Databases.FindByName(this.DatabaseName);
+ Database amoDatabase = null;
+ if (this.DatabaseName == "" && this.ServerName.ToUpper().StartsWith("localhost:".ToUpper()))
+ {
+ //PBI Desktop doesn't have db name yet
+ if (amoServer.Databases.Count > 0)
+ {
+ amoDatabase = amoServer.Databases[0];
+ this.DatabaseName = amoDatabase.Name;
+ }
+ }
+ else
+ {
+ amoDatabase = amoServer.Databases.FindByName(this.DatabaseName);
+ }
if (amoDatabase == null)
{
if (!this.UseProject)
@@ -644,6 +697,7 @@ $@"{{
_compatibilityLevel = amoDatabase.CompatibilityLevel;
_dataSourceVersion = amoDatabase.Model.DefaultPowerBIDataSourceVersion.ToString();
+ _serverMode = amoServer.ServerMode;
_directQuery = ((amoDatabase.Model != null && amoDatabase.Model.DefaultMode == Microsoft.AnalysisServices.Tabular.ModeType.DirectQuery) ||
amoDatabase.DirectQueryMode == DirectQueryMode.DirectQuery || amoDatabase.DirectQueryMode == DirectQueryMode.InMemoryWithDirectQuery || amoDatabase.DirectQueryMode == DirectQueryMode.DirectQueryWithInMemory);
}
diff --git a/BismNormalizer/BismNormalizer/TabularCompare/UI/ConnectionsAlmt.Designer.cs b/BismNormalizer/BismNormalizer/TabularCompare/UI/ConnectionsAlmt.Designer.cs
index 516e157..286e448 100644
--- a/BismNormalizer/BismNormalizer/TabularCompare/UI/ConnectionsAlmt.Designer.cs
+++ b/BismNormalizer/BismNormalizer/TabularCompare/UI/ConnectionsAlmt.Designer.cs
@@ -32,25 +32,47 @@
this.cboSourceServer = new System.Windows.Forms.ComboBox();
this.label2 = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
- this.pnlSourceDb = new System.Windows.Forms.Panel();
+ this.pnlSourceDataset = new System.Windows.Forms.Panel();
this.grpSource = new System.Windows.Forms.GroupBox();
+ this.pnlSourceFile = new System.Windows.Forms.Panel();
+ this.btnSourceFileOpen = new System.Windows.Forms.Button();
+ this.txtSourceFile = new System.Windows.Forms.TextBox();
+ this.pnlSourceDesktop = new System.Windows.Forms.Panel();
+ this.cboSourceDesktop = new System.Windows.Forms.ComboBox();
+ this.rdoSourceFile = new System.Windows.Forms.RadioButton();
+ this.rdoSourceDesktop = new System.Windows.Forms.RadioButton();
+ this.rdoSourceDataset = new System.Windows.Forms.RadioButton();
+ this.label5 = new System.Windows.Forms.Label();
this.btnOK = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button();
this.btnSwitch = new System.Windows.Forms.Button();
this.panel2 = new System.Windows.Forms.Panel();
this.panel1 = new System.Windows.Forms.Panel();
this.grpTarget = new System.Windows.Forms.GroupBox();
+ this.pnlTargetFile = new System.Windows.Forms.Panel();
+ this.btnTargetFileOpen = new System.Windows.Forms.Button();
+ this.txtTargetFile = new System.Windows.Forms.TextBox();
+ this.rdoTargetFile = new System.Windows.Forms.RadioButton();
+ this.pnlTargetDesktop = new System.Windows.Forms.Panel();
+ this.cboTargetDesktop = new System.Windows.Forms.ComboBox();
+ this.rdoTargetDesktop = new System.Windows.Forms.RadioButton();
+ this.rdoTargetDataset = new System.Windows.Forms.RadioButton();
+ this.label6 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
- this.pnlTargetDb = new System.Windows.Forms.Panel();
+ this.pnlTargetDataset = new System.Windows.Forms.Panel();
this.cboTargetServer = new System.Windows.Forms.ComboBox();
this.cboTargetDatabase = new System.Windows.Forms.ComboBox();
- this.pnlSourceDb.SuspendLayout();
+ this.pnlSourceDataset.SuspendLayout();
this.grpSource.SuspendLayout();
+ this.pnlSourceFile.SuspendLayout();
+ this.pnlSourceDesktop.SuspendLayout();
this.panel2.SuspendLayout();
this.panel1.SuspendLayout();
this.grpTarget.SuspendLayout();
- this.pnlTargetDb.SuspendLayout();
+ this.pnlTargetFile.SuspendLayout();
+ this.pnlTargetDesktop.SuspendLayout();
+ this.pnlTargetDataset.SuspendLayout();
this.SuspendLayout();
//
// cboSourceDatabase
@@ -59,11 +81,10 @@
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.cboSourceDatabase.FormattingEnabled = true;
- this.cboSourceDatabase.Location = new System.Drawing.Point(26, 87);
- this.cboSourceDatabase.Margin = new System.Windows.Forms.Padding(7);
+ this.cboSourceDatabase.Location = new System.Drawing.Point(11, 39);
this.cboSourceDatabase.MaxDropDownItems = 11;
this.cboSourceDatabase.Name = "cboSourceDatabase";
- this.cboSourceDatabase.Size = new System.Drawing.Size(858, 37);
+ this.cboSourceDatabase.Size = new System.Drawing.Size(396, 21);
this.cboSourceDatabase.TabIndex = 2;
this.cboSourceDatabase.Enter += new System.EventHandler(this.cboSourceDatabase_Enter);
//
@@ -73,69 +94,174 @@
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.cboSourceServer.FormattingEnabled = true;
- this.cboSourceServer.Location = new System.Drawing.Point(26, 16);
- this.cboSourceServer.Margin = new System.Windows.Forms.Padding(7);
+ this.cboSourceServer.Location = new System.Drawing.Point(11, 7);
this.cboSourceServer.MaxDropDownItems = 11;
this.cboSourceServer.Name = "cboSourceServer";
- this.cboSourceServer.Size = new System.Drawing.Size(858, 37);
+ this.cboSourceServer.Size = new System.Drawing.Size(396, 21);
this.cboSourceServer.TabIndex = 1;
this.cboSourceServer.TextChanged += new System.EventHandler(this.cboSourceServer_TextChanged);
//
// label2
//
this.label2.AutoSize = true;
- this.label2.Location = new System.Drawing.Point(18, 154);
- this.label2.Margin = new System.Windows.Forms.Padding(7, 0, 7, 0);
+ this.label2.Location = new System.Drawing.Point(33, 99);
this.label2.Name = "label2";
- this.label2.Size = new System.Drawing.Size(94, 29);
+ this.label2.Size = new System.Drawing.Size(44, 13);
this.label2.TabIndex = 2;
this.label2.Text = "Dataset";
//
// label1
//
this.label1.AutoSize = true;
- this.label1.Location = new System.Drawing.Point(14, 83);
- this.label1.Margin = new System.Windows.Forms.Padding(7, 0, 7, 0);
+ this.label1.Location = new System.Drawing.Point(33, 67);
this.label1.Name = "label1";
- this.label1.Size = new System.Drawing.Size(134, 29);
+ this.label1.Size = new System.Drawing.Size(62, 13);
this.label1.TabIndex = 1;
this.label1.Text = "Workspace";
//
- // pnlSourceDb
+ // pnlSourceDataset
//
- this.pnlSourceDb.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ this.pnlSourceDataset.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
- this.pnlSourceDb.Controls.Add(this.cboSourceServer);
- this.pnlSourceDb.Controls.Add(this.cboSourceDatabase);
- this.pnlSourceDb.Location = new System.Drawing.Point(147, 60);
- this.pnlSourceDb.Margin = new System.Windows.Forms.Padding(7);
- this.pnlSourceDb.Name = "pnlSourceDb";
- this.pnlSourceDb.Size = new System.Drawing.Size(910, 147);
- this.pnlSourceDb.TabIndex = 1;
+ this.pnlSourceDataset.Controls.Add(this.cboSourceServer);
+ this.pnlSourceDataset.Controls.Add(this.cboSourceDatabase);
+ this.pnlSourceDataset.Location = new System.Drawing.Point(100, 57);
+ this.pnlSourceDataset.Name = "pnlSourceDataset";
+ this.pnlSourceDataset.Size = new System.Drawing.Size(416, 66);
+ this.pnlSourceDataset.TabIndex = 1;
//
// grpSource
//
+ this.grpSource.Controls.Add(this.pnlSourceFile);
+ this.grpSource.Controls.Add(this.pnlSourceDesktop);
+ this.grpSource.Controls.Add(this.rdoSourceFile);
+ this.grpSource.Controls.Add(this.rdoSourceDesktop);
+ this.grpSource.Controls.Add(this.rdoSourceDataset);
+ this.grpSource.Controls.Add(this.label5);
this.grpSource.Controls.Add(this.label1);
this.grpSource.Controls.Add(this.label2);
- this.grpSource.Controls.Add(this.pnlSourceDb);
+ this.grpSource.Controls.Add(this.pnlSourceDataset);
this.grpSource.Dock = System.Windows.Forms.DockStyle.Top;
+ this.grpSource.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.grpSource.Location = new System.Drawing.Point(0, 0);
- this.grpSource.Margin = new System.Windows.Forms.Padding(7);
this.grpSource.Name = "grpSource";
- this.grpSource.Padding = new System.Windows.Forms.Padding(7);
- this.grpSource.Size = new System.Drawing.Size(1069, 263);
+ this.grpSource.Size = new System.Drawing.Size(522, 211);
this.grpSource.TabIndex = 16;
this.grpSource.TabStop = false;
- this.grpSource.Text = "Source";
+ //
+ // pnlSourceFile
+ //
+ this.pnlSourceFile.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.pnlSourceFile.Controls.Add(this.btnSourceFileOpen);
+ this.pnlSourceFile.Controls.Add(this.txtSourceFile);
+ this.pnlSourceFile.Enabled = false;
+ this.pnlSourceFile.Location = new System.Drawing.Point(100, 166);
+ this.pnlSourceFile.Name = "pnlSourceFile";
+ this.pnlSourceFile.Size = new System.Drawing.Size(416, 31);
+ this.pnlSourceFile.TabIndex = 21;
+ //
+ // btnSourceFileOpen
+ //
+ this.btnSourceFileOpen.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnSourceFileOpen.Location = new System.Drawing.Point(380, 7);
+ this.btnSourceFileOpen.Margin = new System.Windows.Forms.Padding(2);
+ this.btnSourceFileOpen.Name = "btnSourceFileOpen";
+ this.btnSourceFileOpen.Size = new System.Drawing.Size(27, 20);
+ this.btnSourceFileOpen.TabIndex = 1;
+ this.btnSourceFileOpen.Text = "...";
+ this.btnSourceFileOpen.UseVisualStyleBackColor = true;
+ this.btnSourceFileOpen.Click += new System.EventHandler(this.btnSourceFileOpen_Click);
+ //
+ // txtSourceFile
+ //
+ this.txtSourceFile.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.txtSourceFile.Location = new System.Drawing.Point(11, 7);
+ this.txtSourceFile.Margin = new System.Windows.Forms.Padding(2);
+ this.txtSourceFile.Name = "txtSourceFile";
+ this.txtSourceFile.Size = new System.Drawing.Size(365, 20);
+ this.txtSourceFile.TabIndex = 0;
+ //
+ // pnlSourceDesktop
+ //
+ this.pnlSourceDesktop.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.pnlSourceDesktop.Controls.Add(this.cboSourceDesktop);
+ this.pnlSourceDesktop.Enabled = false;
+ this.pnlSourceDesktop.Location = new System.Drawing.Point(172, 129);
+ this.pnlSourceDesktop.Name = "pnlSourceDesktop";
+ this.pnlSourceDesktop.Size = new System.Drawing.Size(344, 31);
+ this.pnlSourceDesktop.TabIndex = 19;
+ //
+ // cboSourceDesktop
+ //
+ this.cboSourceDesktop.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.cboSourceDesktop.DisplayMember = "Name";
+ this.cboSourceDesktop.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.cboSourceDesktop.FormattingEnabled = true;
+ this.cboSourceDesktop.Location = new System.Drawing.Point(11, 8);
+ this.cboSourceDesktop.MaxDropDownItems = 11;
+ this.cboSourceDesktop.Name = "cboSourceDesktop";
+ this.cboSourceDesktop.Size = new System.Drawing.Size(324, 21);
+ this.cboSourceDesktop.TabIndex = 9;
+ //
+ // rdoSourceFile
+ //
+ this.rdoSourceFile.AutoSize = true;
+ this.rdoSourceFile.Location = new System.Drawing.Point(15, 174);
+ this.rdoSourceFile.Name = "rdoSourceFile";
+ this.rdoSourceFile.Size = new System.Drawing.Size(41, 17);
+ this.rdoSourceFile.TabIndex = 11;
+ this.rdoSourceFile.Text = "File";
+ this.rdoSourceFile.UseVisualStyleBackColor = true;
+ this.rdoSourceFile.CheckedChanged += new System.EventHandler(this.rdoSourceFile_CheckedChanged);
+ //
+ // rdoSourceDesktop
+ //
+ this.rdoSourceDesktop.AutoSize = true;
+ this.rdoSourceDesktop.Location = new System.Drawing.Point(15, 138);
+ this.rdoSourceDesktop.Name = "rdoSourceDesktop";
+ this.rdoSourceDesktop.Size = new System.Drawing.Size(151, 17);
+ this.rdoSourceDesktop.TabIndex = 5;
+ this.rdoSourceDesktop.Text = "Power BI Desktop / SSDT";
+ this.rdoSourceDesktop.UseVisualStyleBackColor = true;
+ this.rdoSourceDesktop.CheckedChanged += new System.EventHandler(this.rdoSourceDesktop_CheckedChanged);
+ //
+ // rdoSourceDataset
+ //
+ this.rdoSourceDataset.AutoSize = true;
+ this.rdoSourceDataset.Checked = true;
+ this.rdoSourceDataset.Location = new System.Drawing.Point(15, 34);
+ this.rdoSourceDataset.Name = "rdoSourceDataset";
+ this.rdoSourceDataset.Size = new System.Drawing.Size(62, 17);
+ this.rdoSourceDataset.TabIndex = 4;
+ this.rdoSourceDataset.TabStop = true;
+ this.rdoSourceDataset.Text = "Dataset";
+ this.rdoSourceDataset.UseVisualStyleBackColor = true;
+ this.rdoSourceDataset.CheckedChanged += new System.EventHandler(this.rdoSourceDataset_CheckedChanged);
+ //
+ // label5
+ //
+ this.label5.AutoSize = true;
+ this.label5.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label5.Location = new System.Drawing.Point(12, 9);
+ this.label5.Name = "label5";
+ this.label5.Size = new System.Drawing.Size(59, 17);
+ this.label5.TabIndex = 3;
+ this.label5.Text = "Source";
//
// btnOK
//
this.btnOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK;
- this.btnOK.Location = new System.Drawing.Point(696, 23);
- this.btnOK.Margin = new System.Windows.Forms.Padding(7);
+ this.btnOK.Location = new System.Drawing.Point(362, 10);
this.btnOK.Name = "btnOK";
- this.btnOK.Size = new System.Drawing.Size(161, 51);
+ this.btnOK.Size = new System.Drawing.Size(69, 23);
this.btnOK.TabIndex = 6;
this.btnOK.Text = "OK";
this.btnOK.UseVisualStyleBackColor = true;
@@ -145,10 +271,9 @@
//
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
- this.btnCancel.Location = new System.Drawing.Point(871, 23);
- this.btnCancel.Margin = new System.Windows.Forms.Padding(7);
+ this.btnCancel.Location = new System.Drawing.Point(437, 10);
this.btnCancel.Name = "btnCancel";
- this.btnCancel.Size = new System.Drawing.Size(166, 51);
+ this.btnCancel.Size = new System.Drawing.Size(71, 23);
this.btnCancel.TabIndex = 7;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
@@ -157,10 +282,9 @@
//
this.btnSwitch.BackgroundImage = global::BismNormalizer.Resources.ButtonSwitch;
this.btnSwitch.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
- this.btnSwitch.Location = new System.Drawing.Point(467, 6);
- this.btnSwitch.Margin = new System.Windows.Forms.Padding(7);
+ this.btnSwitch.Location = new System.Drawing.Point(236, 3);
this.btnSwitch.Name = "btnSwitch";
- this.btnSwitch.Size = new System.Drawing.Size(130, 71);
+ this.btnSwitch.Size = new System.Drawing.Size(56, 32);
this.btnSwitch.TabIndex = 3;
this.btnSwitch.UseVisualStyleBackColor = true;
this.btnSwitch.Click += new System.EventHandler(this.btnSwitch_Click);
@@ -170,66 +294,174 @@
this.panel2.Controls.Add(this.btnCancel);
this.panel2.Controls.Add(this.btnOK);
this.panel2.Dock = System.Windows.Forms.DockStyle.Bottom;
- this.panel2.Location = new System.Drawing.Point(0, 627);
+ this.panel2.Location = new System.Drawing.Point(0, 473);
+ this.panel2.Margin = new System.Windows.Forms.Padding(1);
this.panel2.Name = "panel2";
- this.panel2.Size = new System.Drawing.Size(1069, 100);
+ this.panel2.Size = new System.Drawing.Size(522, 45);
this.panel2.TabIndex = 22;
//
// panel1
//
this.panel1.Controls.Add(this.btnSwitch);
this.panel1.Dock = System.Windows.Forms.DockStyle.Top;
- this.panel1.Location = new System.Drawing.Point(0, 263);
+ this.panel1.Location = new System.Drawing.Point(0, 211);
+ this.panel1.Margin = new System.Windows.Forms.Padding(1);
this.panel1.Name = "panel1";
- this.panel1.Size = new System.Drawing.Size(1069, 84);
+ this.panel1.Size = new System.Drawing.Size(522, 38);
this.panel1.TabIndex = 25;
//
// grpTarget
//
+ this.grpTarget.Controls.Add(this.pnlTargetFile);
+ this.grpTarget.Controls.Add(this.rdoTargetFile);
+ this.grpTarget.Controls.Add(this.pnlTargetDesktop);
+ this.grpTarget.Controls.Add(this.rdoTargetDesktop);
+ this.grpTarget.Controls.Add(this.rdoTargetDataset);
+ this.grpTarget.Controls.Add(this.label6);
this.grpTarget.Controls.Add(this.label3);
this.grpTarget.Controls.Add(this.label4);
- this.grpTarget.Controls.Add(this.pnlTargetDb);
+ this.grpTarget.Controls.Add(this.pnlTargetDataset);
this.grpTarget.Dock = System.Windows.Forms.DockStyle.Top;
- this.grpTarget.Location = new System.Drawing.Point(0, 347);
- this.grpTarget.Margin = new System.Windows.Forms.Padding(7);
+ this.grpTarget.Location = new System.Drawing.Point(0, 249);
this.grpTarget.Name = "grpTarget";
- this.grpTarget.Padding = new System.Windows.Forms.Padding(7);
- this.grpTarget.Size = new System.Drawing.Size(1069, 268);
+ this.grpTarget.Size = new System.Drawing.Size(522, 218);
this.grpTarget.TabIndex = 26;
this.grpTarget.TabStop = false;
- this.grpTarget.Text = "Target";
+ //
+ // pnlTargetFile
+ //
+ this.pnlTargetFile.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.pnlTargetFile.Controls.Add(this.btnTargetFileOpen);
+ this.pnlTargetFile.Controls.Add(this.txtTargetFile);
+ this.pnlTargetFile.Enabled = false;
+ this.pnlTargetFile.Location = new System.Drawing.Point(100, 173);
+ this.pnlTargetFile.Name = "pnlTargetFile";
+ this.pnlTargetFile.Size = new System.Drawing.Size(416, 31);
+ this.pnlTargetFile.TabIndex = 21;
+ //
+ // btnTargetFileOpen
+ //
+ this.btnTargetFileOpen.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnTargetFileOpen.Location = new System.Drawing.Point(380, 3);
+ this.btnTargetFileOpen.Margin = new System.Windows.Forms.Padding(2);
+ this.btnTargetFileOpen.Name = "btnTargetFileOpen";
+ this.btnTargetFileOpen.Size = new System.Drawing.Size(27, 20);
+ this.btnTargetFileOpen.TabIndex = 2;
+ this.btnTargetFileOpen.Text = "...";
+ this.btnTargetFileOpen.UseVisualStyleBackColor = true;
+ this.btnTargetFileOpen.Click += new System.EventHandler(this.btnTargetFileOpen_Click);
+ //
+ // txtTargetFile
+ //
+ this.txtTargetFile.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.txtTargetFile.Location = new System.Drawing.Point(11, 3);
+ this.txtTargetFile.Margin = new System.Windows.Forms.Padding(2);
+ this.txtTargetFile.Name = "txtTargetFile";
+ this.txtTargetFile.Size = new System.Drawing.Size(365, 20);
+ this.txtTargetFile.TabIndex = 1;
+ //
+ // rdoTargetFile
+ //
+ this.rdoTargetFile.AutoSize = true;
+ this.rdoTargetFile.Location = new System.Drawing.Point(15, 178);
+ this.rdoTargetFile.Name = "rdoTargetFile";
+ this.rdoTargetFile.Size = new System.Drawing.Size(41, 17);
+ this.rdoTargetFile.TabIndex = 20;
+ this.rdoTargetFile.Text = "File";
+ this.rdoTargetFile.UseVisualStyleBackColor = true;
+ this.rdoTargetFile.CheckedChanged += new System.EventHandler(this.rdoTargetFile_CheckedChanged);
+ //
+ // pnlTargetDesktop
+ //
+ this.pnlTargetDesktop.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.pnlTargetDesktop.Controls.Add(this.cboTargetDesktop);
+ this.pnlTargetDesktop.Enabled = false;
+ this.pnlTargetDesktop.Location = new System.Drawing.Point(172, 132);
+ this.pnlTargetDesktop.Name = "pnlTargetDesktop";
+ this.pnlTargetDesktop.Size = new System.Drawing.Size(344, 31);
+ this.pnlTargetDesktop.TabIndex = 19;
+ //
+ // cboTargetDesktop
+ //
+ this.cboTargetDesktop.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.cboTargetDesktop.DisplayMember = "Name";
+ this.cboTargetDesktop.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.cboTargetDesktop.FormattingEnabled = true;
+ this.cboTargetDesktop.Location = new System.Drawing.Point(10, 8);
+ this.cboTargetDesktop.MaxDropDownItems = 11;
+ this.cboTargetDesktop.Name = "cboTargetDesktop";
+ this.cboTargetDesktop.Size = new System.Drawing.Size(325, 21);
+ this.cboTargetDesktop.TabIndex = 9;
+ //
+ // rdoTargetDesktop
+ //
+ this.rdoTargetDesktop.AutoSize = true;
+ this.rdoTargetDesktop.Location = new System.Drawing.Point(15, 141);
+ this.rdoTargetDesktop.Name = "rdoTargetDesktop";
+ this.rdoTargetDesktop.Size = new System.Drawing.Size(151, 17);
+ this.rdoTargetDesktop.TabIndex = 18;
+ this.rdoTargetDesktop.Text = "Power BI Desktop / SSDT";
+ this.rdoTargetDesktop.UseVisualStyleBackColor = true;
+ this.rdoTargetDesktop.CheckedChanged += new System.EventHandler(this.rdoTargetDesktop_CheckedChanged);
+ //
+ // rdoTargetDataset
+ //
+ this.rdoTargetDataset.AutoSize = true;
+ this.rdoTargetDataset.Checked = true;
+ this.rdoTargetDataset.Location = new System.Drawing.Point(15, 37);
+ this.rdoTargetDataset.Name = "rdoTargetDataset";
+ this.rdoTargetDataset.Size = new System.Drawing.Size(62, 17);
+ this.rdoTargetDataset.TabIndex = 17;
+ this.rdoTargetDataset.TabStop = true;
+ this.rdoTargetDataset.Text = "Dataset";
+ this.rdoTargetDataset.UseVisualStyleBackColor = true;
+ this.rdoTargetDataset.CheckedChanged += new System.EventHandler(this.rdoTargetDataset_CheckedChanged);
+ //
+ // label6
+ //
+ this.label6.AutoSize = true;
+ this.label6.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label6.Location = new System.Drawing.Point(12, 9);
+ this.label6.Name = "label6";
+ this.label6.Size = new System.Drawing.Size(56, 17);
+ this.label6.TabIndex = 16;
+ this.label6.Text = "Target";
//
// label3
//
this.label3.AutoSize = true;
- this.label3.Location = new System.Drawing.Point(15, 83);
- this.label3.Margin = new System.Windows.Forms.Padding(7, 0, 7, 0);
+ this.label3.Location = new System.Drawing.Point(33, 70);
this.label3.Name = "label3";
- this.label3.Size = new System.Drawing.Size(134, 29);
+ this.label3.Size = new System.Drawing.Size(62, 13);
this.label3.TabIndex = 4;
this.label3.Text = "Workspace";
//
// label4
//
this.label4.AutoSize = true;
- this.label4.Location = new System.Drawing.Point(15, 154);
- this.label4.Margin = new System.Windows.Forms.Padding(7, 0, 7, 0);
+ this.label4.Location = new System.Drawing.Point(33, 102);
this.label4.Name = "label4";
- this.label4.Size = new System.Drawing.Size(94, 29);
+ this.label4.Size = new System.Drawing.Size(44, 13);
this.label4.TabIndex = 5;
this.label4.Text = "Dataset";
//
- // pnlTargetDb
+ // pnlTargetDataset
//
- this.pnlTargetDb.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ this.pnlTargetDataset.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
- this.pnlTargetDb.Controls.Add(this.cboTargetServer);
- this.pnlTargetDb.Controls.Add(this.cboTargetDatabase);
- this.pnlTargetDb.Location = new System.Drawing.Point(144, 60);
- this.pnlTargetDb.Margin = new System.Windows.Forms.Padding(7);
- this.pnlTargetDb.Name = "pnlTargetDb";
- this.pnlTargetDb.Size = new System.Drawing.Size(911, 147);
- this.pnlTargetDb.TabIndex = 15;
+ this.pnlTargetDataset.Controls.Add(this.cboTargetServer);
+ this.pnlTargetDataset.Controls.Add(this.cboTargetDatabase);
+ this.pnlTargetDataset.Location = new System.Drawing.Point(100, 60);
+ this.pnlTargetDataset.Name = "pnlTargetDataset";
+ this.pnlTargetDataset.Size = new System.Drawing.Size(416, 66);
+ this.pnlTargetDataset.TabIndex = 15;
//
// cboTargetServer
//
@@ -237,11 +469,10 @@
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.cboTargetServer.FormattingEnabled = true;
- this.cboTargetServer.Location = new System.Drawing.Point(26, 16);
- this.cboTargetServer.Margin = new System.Windows.Forms.Padding(7);
+ this.cboTargetServer.Location = new System.Drawing.Point(11, 7);
this.cboTargetServer.MaxDropDownItems = 11;
this.cboTargetServer.Name = "cboTargetServer";
- this.cboTargetServer.Size = new System.Drawing.Size(862, 37);
+ this.cboTargetServer.Size = new System.Drawing.Size(396, 21);
this.cboTargetServer.TabIndex = 4;
this.cboTargetServer.TextChanged += new System.EventHandler(this.cboTargetServer_TextChanged);
//
@@ -251,42 +482,46 @@
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.cboTargetDatabase.FormattingEnabled = true;
- this.cboTargetDatabase.Location = new System.Drawing.Point(26, 87);
- this.cboTargetDatabase.Margin = new System.Windows.Forms.Padding(7);
+ this.cboTargetDatabase.Location = new System.Drawing.Point(11, 39);
this.cboTargetDatabase.MaxDropDownItems = 11;
this.cboTargetDatabase.Name = "cboTargetDatabase";
- this.cboTargetDatabase.Size = new System.Drawing.Size(862, 37);
+ this.cboTargetDatabase.Size = new System.Drawing.Size(396, 21);
this.cboTargetDatabase.TabIndex = 5;
this.cboTargetDatabase.Enter += new System.EventHandler(this.cboTargetDatabase_Enter);
//
- // Connections
+ // ConnectionsAlmt
//
this.AcceptButton = this.btnOK;
- this.AutoScaleDimensions = new System.Drawing.SizeF(14F, 29F);
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.btnCancel;
- this.ClientSize = new System.Drawing.Size(1069, 727);
+ this.ClientSize = new System.Drawing.Size(522, 518);
this.Controls.Add(this.grpTarget);
this.Controls.Add(this.panel1);
this.Controls.Add(this.panel2);
this.Controls.Add(this.grpSource);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
- this.Margin = new System.Windows.Forms.Padding(7);
this.MaximizeBox = false;
this.MinimizeBox = false;
- this.Name = "Connections";
+ this.Name = "ConnectionsAlmt";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.Text = "Connections";
this.Load += new System.EventHandler(this.Connections_Load);
- this.pnlSourceDb.ResumeLayout(false);
+ this.pnlSourceDataset.ResumeLayout(false);
this.grpSource.ResumeLayout(false);
this.grpSource.PerformLayout();
+ this.pnlSourceFile.ResumeLayout(false);
+ this.pnlSourceFile.PerformLayout();
+ this.pnlSourceDesktop.ResumeLayout(false);
this.panel2.ResumeLayout(false);
this.panel1.ResumeLayout(false);
this.grpTarget.ResumeLayout(false);
this.grpTarget.PerformLayout();
- this.pnlTargetDb.ResumeLayout(false);
+ this.pnlTargetFile.ResumeLayout(false);
+ this.pnlTargetFile.PerformLayout();
+ this.pnlTargetDesktop.ResumeLayout(false);
+ this.pnlTargetDataset.ResumeLayout(false);
this.ResumeLayout(false);
}
@@ -297,7 +532,7 @@
private System.Windows.Forms.ComboBox cboSourceServer;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label1;
- private System.Windows.Forms.Panel pnlSourceDb;
+ private System.Windows.Forms.Panel pnlSourceDataset;
private System.Windows.Forms.GroupBox grpSource;
private System.Windows.Forms.Button btnOK;
private System.Windows.Forms.Button btnCancel;
@@ -307,8 +542,26 @@
private System.Windows.Forms.GroupBox grpTarget;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label4;
- private System.Windows.Forms.Panel pnlTargetDb;
+ private System.Windows.Forms.Panel pnlTargetDataset;
private System.Windows.Forms.ComboBox cboTargetServer;
private System.Windows.Forms.ComboBox cboTargetDatabase;
+ private System.Windows.Forms.Label label5;
+ private System.Windows.Forms.RadioButton rdoSourceDataset;
+ private System.Windows.Forms.RadioButton rdoSourceDesktop;
+ private System.Windows.Forms.RadioButton rdoTargetDesktop;
+ private System.Windows.Forms.RadioButton rdoTargetDataset;
+ private System.Windows.Forms.Label label6;
+ private System.Windows.Forms.RadioButton rdoSourceFile;
+ private System.Windows.Forms.Panel pnlSourceDesktop;
+ private System.Windows.Forms.ComboBox cboSourceDesktop;
+ private System.Windows.Forms.RadioButton rdoTargetFile;
+ private System.Windows.Forms.Panel pnlTargetDesktop;
+ private System.Windows.Forms.ComboBox cboTargetDesktop;
+ private System.Windows.Forms.Panel pnlTargetFile;
+ private System.Windows.Forms.Button btnTargetFileOpen;
+ private System.Windows.Forms.TextBox txtTargetFile;
+ private System.Windows.Forms.Panel pnlSourceFile;
+ private System.Windows.Forms.Button btnSourceFileOpen;
+ private System.Windows.Forms.TextBox txtSourceFile;
}
}
\ No newline at end of file
diff --git a/BismNormalizer/BismNormalizer/TabularCompare/UI/ConnectionsAlmt.cs b/BismNormalizer/BismNormalizer/TabularCompare/UI/ConnectionsAlmt.cs
index ab9a8a6..4dc83ff 100644
--- a/BismNormalizer/BismNormalizer/TabularCompare/UI/ConnectionsAlmt.cs
+++ b/BismNormalizer/BismNormalizer/TabularCompare/UI/ConnectionsAlmt.cs
@@ -4,15 +4,22 @@ using System.Collections.Generic;
using System.Windows.Forms;
using Microsoft.AnalysisServices;
using System.Drawing;
+using BismNormalizer.TabularCompare.UI.DesktopInstances;
+using System.Linq.Expressions;
namespace BismNormalizer.TabularCompare.UI
{
public partial class ConnectionsAlmt : Form
{
+ #region Private members
+
private ComparisonInfo _comparisonInfo;
private float _dpiScaleFactor;
private bool _sourceDatabaseBound = false;
private bool _targetDatabaseBound = false;
+ private List _powerBIInstances = new List();
+
+ #endregion
public ConnectionsAlmt()
{
@@ -21,7 +28,14 @@ namespace BismNormalizer.TabularCompare.UI
private void Connections_Load(object sender, EventArgs e)
{
- this.Width = Convert.ToInt32(this.Width * 1.3);
+ //Settings.Default.SourceServerAutoCompleteEntries = "localhost|";
+ //Settings.Default.TargetServerAutoCompleteEntries = "localhost|";
+ //Settings.Default.SourceCatalog = "";
+ //Settings.Default.TargetCatalog = "";
+ //Settings.Default.Save();
+
+
+ //this.Width = Convert.ToInt32(this.Width * 1.3);
if (_dpiScaleFactor > 1)
{
@@ -62,87 +76,149 @@ namespace BismNormalizer.TabularCompare.UI
cboSourceDatabase.Text = Settings.Default.SourceCatalog;
cboTargetDatabase.Text = Settings.Default.TargetCatalog;
- bool boundTargetDatabase = false;
- BindSourceConnectionInfo();
- BindTargetConnectionInfo(out boundTargetDatabase);
+ cboSourceDesktop.Items.Clear();
+ cboTargetDesktop.Items.Clear();
+
+ BindingSource desktopBindingSource = new BindingSource();
+ BindingSource desktopBindingTarget = new BindingSource();
+ _powerBIInstances.Clear();
+ try
+ {
+ _powerBIInstances = PowerBIHelper.GetLocalInstances();
+ }
+ catch { }
+
+ if (_powerBIInstances.Count > 1)
+ {
+ desktopBindingSource.DataSource = _powerBIInstances;
+ desktopBindingTarget.DataSource = _powerBIInstances;
+
+ cboSourceDesktop.DataSource = desktopBindingSource;
+ cboSourceDesktop.ValueMember = "Port";
+ cboSourceDesktop.DisplayMember = "Name";
+
+ cboTargetDesktop.DataSource = desktopBindingTarget;
+ cboTargetDesktop.ValueMember = "Port";
+ cboTargetDesktop.DisplayMember = "Name";
+
+ BindSourceConnectionInfo();
+ BindTargetConnectionInfo();
+ }
}
private bool BindSourceConnectionInfo()
{
- bool returnVal = false;
+ bool boundSuccessfully = false;
if (_comparisonInfo?.ConnectionInfoSource != null)
{
- if (!String.IsNullOrEmpty(_comparisonInfo.ConnectionInfoSource.ServerName) && !String.IsNullOrEmpty(_comparisonInfo.ConnectionInfoSource.DatabaseName))
+ if (_comparisonInfo.ConnectionInfoSource.UseBimFile)
{
+ rdoSourceFile.Checked = true;
+
+ pnlSourceDataset.Enabled = false;
+ pnlSourceDesktop.Enabled = false;
+ pnlSourceFile.Enabled = true;
+
+ txtSourceFile.Text = _comparisonInfo.ConnectionInfoSource.BimFile;
+
+ boundSuccessfully = true;
+ }
+ else if (_comparisonInfo.ConnectionInfoSource.UseDesktop)
+ {
+ rdoSourceDesktop.Checked = true;
+
+ pnlSourceDataset.Enabled = false;
+ pnlSourceDesktop.Enabled = true;
+ pnlSourceFile.Enabled = false;
+
+ int portFromConnectionInfo = -1;
+ if (_comparisonInfo.ConnectionInfoSource.ServerName != null &&
+ int.TryParse(_comparisonInfo.ConnectionInfoSource.ServerName.ToUpper().Replace("localhost:".ToUpper(), ""), out portFromConnectionInfo))
+ {
+ for (int i = 0; i < ((BindingSource)cboSourceDesktop.DataSource).Count; i++)
+ {
+ if (((PowerBIInstance)((BindingSource)cboSourceDesktop.DataSource)[i]).Port == portFromConnectionInfo)
+ {
+ cboSourceDesktop.SelectedIndex = i;
+ break;
+ }
+ }
+ }
+ boundSuccessfully = true;
+ }
+ else if (!String.IsNullOrEmpty(_comparisonInfo.ConnectionInfoSource.ServerName) && !String.IsNullOrEmpty(_comparisonInfo.ConnectionInfoSource.DatabaseName))
+ {
+ rdoSourceDataset.Checked = true;
+
+ pnlSourceDataset.Enabled = true;
+ pnlSourceDesktop.Enabled = false;
+ pnlSourceFile.Enabled = false;
+
cboSourceServer.Text = _comparisonInfo.ConnectionInfoSource.ServerName;
cboSourceDatabase.Text = _comparisonInfo.ConnectionInfoSource.DatabaseName;
- returnVal = true;
+ boundSuccessfully = true;
}
}
- return returnVal;
+ return boundSuccessfully;
}
- private bool BindTargetConnectionInfo(out bool boundTargetDatabase)
+ private bool BindTargetConnectionInfo()
{
- bool returnVal = false;
- boundTargetDatabase = false;
+ bool boundSuccessfully = false;
if (_comparisonInfo?.ConnectionInfoTarget != null)
{
- if (!String.IsNullOrEmpty(_comparisonInfo.ConnectionInfoTarget.ServerName) && !String.IsNullOrEmpty(_comparisonInfo.ConnectionInfoTarget.DatabaseName))
+ if (_comparisonInfo.ConnectionInfoTarget.UseBimFile)
{
+ pnlTargetDataset.Enabled = false;
+ pnlTargetDesktop.Enabled = false;
+ rdoTargetFile.Checked = true;
+ pnlTargetFile.Enabled = true;
+ txtTargetFile.Text = _comparisonInfo.ConnectionInfoTarget.BimFile;
+
+ boundSuccessfully = true;
+ }
+ else if (_comparisonInfo.ConnectionInfoTarget.UseDesktop)
+ {
+ rdoTargetDesktop.Checked = true;
+
+ pnlTargetDataset.Enabled = false;
+ pnlTargetDesktop.Enabled = true;
+ pnlTargetFile.Enabled = false;
+
+ int portFromConnectionInfo = -1;
+ if (_comparisonInfo.ConnectionInfoTarget.ServerName != null &&
+ int.TryParse(_comparisonInfo.ConnectionInfoTarget.ServerName.ToUpper().Replace("localhost:".ToUpper(), ""), out portFromConnectionInfo))
+ {
+ for (int i = 0; i < ((BindingSource)cboTargetDesktop.DataSource).Count; i++)
+ {
+ if (((PowerBIInstance)((BindingSource)cboTargetDesktop.DataSource)[i]).Port == portFromConnectionInfo)
+ {
+ cboTargetDesktop.SelectedIndex = i;
+ break;
+ }
+ }
+ }
+ boundSuccessfully = true;
+ }
+ else if (!String.IsNullOrEmpty(_comparisonInfo.ConnectionInfoTarget.ServerName) && !String.IsNullOrEmpty(_comparisonInfo.ConnectionInfoTarget.DatabaseName))
+ {
+ rdoTargetDataset.Checked = true;
+ pnlTargetDataset.Enabled = true;
+ pnlTargetDesktop.Enabled = false;
+ pnlTargetFile.Enabled = false;
+
cboTargetServer.Text = _comparisonInfo.ConnectionInfoTarget.ServerName;
cboTargetDatabase.Text = _comparisonInfo.ConnectionInfoTarget.DatabaseName;
- boundTargetDatabase = true;
- returnVal = true;
+ boundSuccessfully = true;
}
}
- return returnVal;
- }
-
- private static void IterateProject(SortedList projects, EnvDTE.Project project, string derivedProjectName = "")
- {
- if (project.ProjectItems != null) //if project is unloaded, its ProjectItems==null
- {
- derivedProjectName = AppendProjectName(project, derivedProjectName);
- if (project.FileName.EndsWith(".smproj"))
- {
- projects.Add(derivedProjectName, project);
- }
- else if (project.Kind == "{66A26720-8FB5-11D2-AA7E-00C04F688DDE}")
- {
- foreach (EnvDTE.ProjectItem projectItem in project.ProjectItems)
- {
- if (projectItem.SubProject != null)
- {
- IterateProject(projects, projectItem.SubProject, derivedProjectName);
- }
- }
- }
- }
- }
-
- private static string AppendProjectName(EnvDTE.Project project, string derivedProjectName)
- {
- if (derivedProjectName != "")
- {
- derivedProjectName += "\\";
- }
- derivedProjectName += project.Name;
-
- return derivedProjectName;
- }
-
- EnvDTE80.DTE2 _dte; //EnvDTE._DTE _dte;
- public EnvDTE80.DTE2 Dte // EnvDTE._DTE DTE
- {
- get { return _dte; }
- set { _dte = value; }
+ return boundSuccessfully;
}
public ComparisonInfo ComparisonInfo
@@ -157,33 +233,152 @@ namespace BismNormalizer.TabularCompare.UI
set { _dpiScaleFactor = value; }
}
+ private void rdoSourceDataset_CheckedChanged(object sender, EventArgs e)
+ {
+ pnlSourceDataset.Enabled = true;
+ pnlSourceDesktop.Enabled = false;
+ pnlSourceFile.Enabled = false;
+ cboSourceServer.Focus();
+ }
+ private void rdoSourceDesktop_CheckedChanged(object sender, EventArgs e)
+ {
+ pnlSourceDataset.Enabled = false;
+ pnlSourceDesktop.Enabled = true;
+ pnlSourceFile.Enabled = false;
+ cboSourceDesktop.Focus();
+ }
+ private void rdoSourceFile_CheckedChanged(object sender, EventArgs e)
+ {
+ pnlSourceDataset.Enabled = false;
+ pnlSourceDesktop.Enabled = false;
+ pnlSourceFile.Enabled = true;
+ btnSourceFileOpen.Focus();
+ }
+ private void rdoTargetDataset_CheckedChanged(object sender, EventArgs e)
+ {
+ pnlTargetDataset.Enabled = true;
+ pnlTargetDesktop.Enabled = false;
+ pnlTargetFile.Enabled = false;
+ cboTargetServer.Focus();
+ }
+ private void rdoTargetDesktop_CheckedChanged(object sender, EventArgs e)
+ {
+ pnlTargetDataset.Enabled = false;
+ pnlTargetDesktop.Enabled = true;
+ pnlTargetFile.Enabled = false;
+ cboTargetDesktop.Focus();
+ }
+ private void rdoTargetFile_CheckedChanged(object sender, EventArgs e)
+ {
+ pnlTargetDataset.Enabled = false;
+ pnlTargetDesktop.Enabled = false;
+ pnlTargetFile.Enabled = true;
+ btnTargetFileOpen.Focus();
+ }
+
private void btnOK_Click(object sender, EventArgs e)
{
- _comparisonInfo.ConnectionInfoSource.UseProject = false;
- _comparisonInfo.ConnectionInfoSource.ServerName = cboSourceServer.Text;
- _comparisonInfo.ConnectionInfoSource.DatabaseName = cboSourceDatabase.Text;
- _comparisonInfo.ConnectionInfoSource.ProjectName = null;
- _comparisonInfo.ConnectionInfoSource.ProjectFile = null;
+ if (rdoSourceDesktop.Checked)
+ {
+ _comparisonInfo.ConnectionInfoSource.UseProject = false;
+ _comparisonInfo.ConnectionInfoSource.UseBimFile = false;
+ _comparisonInfo.ConnectionInfoSource.UseDesktop = true;
+ _comparisonInfo.ConnectionInfoSource.ServerName = "localhost:" + cboSourceDesktop.SelectedValue.ToString();
+ _comparisonInfo.ConnectionInfoSource.DatabaseName = ""; //For Desktop/SSDT don't have DB name but get first when connect
+ _comparisonInfo.ConnectionInfoSource.DesktopName = cboSourceDesktop.Text;
+ _comparisonInfo.ConnectionInfoSource.ProjectName = null;
+ _comparisonInfo.ConnectionInfoSource.ProjectFile = null;
+ _comparisonInfo.ConnectionInfoSource.BimFile = null;
+ }
+ else if (rdoSourceFile.Checked)
+ {
+ _comparisonInfo.ConnectionInfoSource.UseProject = false;
+ _comparisonInfo.ConnectionInfoSource.UseBimFile = true;
+ _comparisonInfo.ConnectionInfoSource.UseDesktop = false;
+ _comparisonInfo.ConnectionInfoSource.BimFile = txtSourceFile.Text;
+ _comparisonInfo.ConnectionInfoSource.DesktopName = null;
+ _comparisonInfo.ConnectionInfoSource.ProjectName = null;
+ _comparisonInfo.ConnectionInfoSource.ProjectFile = null;
+ }
+ else
+ {
+ _comparisonInfo.ConnectionInfoSource.UseProject = false;
+ _comparisonInfo.ConnectionInfoSource.UseBimFile = false;
+ _comparisonInfo.ConnectionInfoSource.UseDesktop = false;
+ _comparisonInfo.ConnectionInfoSource.ServerName = cboSourceServer.Text;
+ _comparisonInfo.ConnectionInfoSource.DatabaseName = cboSourceDatabase.Text;
+ _comparisonInfo.ConnectionInfoSource.DesktopName = null;
+ _comparisonInfo.ConnectionInfoSource.ProjectName = null;
+ _comparisonInfo.ConnectionInfoSource.ProjectFile = null;
+ _comparisonInfo.ConnectionInfoSource.BimFile = null;
+ }
- _comparisonInfo.ConnectionInfoTarget.UseProject = false;
- _comparisonInfo.ConnectionInfoTarget.ServerName = cboTargetServer.Text;
- _comparisonInfo.ConnectionInfoTarget.DatabaseName = cboTargetDatabase.Text;
- _comparisonInfo.ConnectionInfoTarget.ProjectName = null;
- _comparisonInfo.ConnectionInfoTarget.ProjectFile = null;
+ if (rdoTargetDesktop.Checked)
+ {
+ _comparisonInfo.ConnectionInfoTarget.UseProject = false;
+ _comparisonInfo.ConnectionInfoTarget.UseBimFile = false;
+ _comparisonInfo.ConnectionInfoTarget.UseDesktop = true;
+ _comparisonInfo.ConnectionInfoTarget.ServerName = "localhost:" + cboTargetDesktop.SelectedValue.ToString();
+ _comparisonInfo.ConnectionInfoTarget.DatabaseName = ""; //For Desktop/SSDT don't have DB name but get first when connect
+ _comparisonInfo.ConnectionInfoTarget.DesktopName = cboTargetDesktop.Text;
+ _comparisonInfo.ConnectionInfoTarget.ProjectName = null;
+ _comparisonInfo.ConnectionInfoTarget.ProjectFile = null;
+ _comparisonInfo.ConnectionInfoTarget.BimFile = null;
+ }
+ else if (rdoTargetFile.Checked)
+ {
+ _comparisonInfo.ConnectionInfoTarget.UseProject = false;
+ _comparisonInfo.ConnectionInfoTarget.UseBimFile = true;
+ _comparisonInfo.ConnectionInfoTarget.UseDesktop = false;
+ _comparisonInfo.ConnectionInfoTarget.BimFile = txtTargetFile.Text;
+ _comparisonInfo.ConnectionInfoTarget.DesktopName = null;
+ _comparisonInfo.ConnectionInfoTarget.ProjectName = null;
+ _comparisonInfo.ConnectionInfoTarget.ProjectFile = null;
+ }
+ else
+ {
+ _comparisonInfo.ConnectionInfoTarget.UseProject = false;
+ _comparisonInfo.ConnectionInfoTarget.UseBimFile = false;
+ _comparisonInfo.ConnectionInfoTarget.UseDesktop = false;
+ _comparisonInfo.ConnectionInfoTarget.ServerName = cboTargetServer.Text;
+ _comparisonInfo.ConnectionInfoTarget.DatabaseName = cboTargetDatabase.Text;
+ _comparisonInfo.ConnectionInfoTarget.DesktopName = null;
+ _comparisonInfo.ConnectionInfoTarget.ProjectName = null;
+ _comparisonInfo.ConnectionInfoTarget.ProjectFile = null;
+ _comparisonInfo.ConnectionInfoTarget.BimFile = null;
+ }
}
private void btnSwitch_Click(object sender, EventArgs e)
{
ConnectionInfo infoSourceTemp = new ConnectionInfo();
-
+ infoSourceTemp.UseProject = rdoSourceDesktop.Checked;
+ infoSourceTemp.UseBimFile = rdoSourceFile.Checked;
+ infoSourceTemp.ProjectName = cboSourceDesktop.Text;
+ //infoSourceTemp.Project = (PowerBIInstance)cboSourceDesktop.SelectedValue;
+ int portSourceTemp = (int)cboSourceDesktop.SelectedValue; //Fudge start
infoSourceTemp.ServerName = cboSourceServer.Text;
infoSourceTemp.DatabaseName = cboSourceDatabase.Text;
+ infoSourceTemp.BimFile = txtSourceFile.Text;
+ rdoSourceDesktop.Checked = rdoTargetDesktop.Checked;
+ rdoSourceFile.Checked = rdoTargetFile.Checked;
+ rdoSourceDataset.Checked = rdoTargetDataset.Checked;
+ cboSourceDesktop.Text = cboTargetDesktop.Text;
+ cboSourceDesktop.SelectedValue = cboTargetDesktop.SelectedValue;
cboSourceServer.Text = cboTargetServer.Text;
cboSourceDatabase.Text = cboTargetDatabase.Text;
+ txtSourceFile.Text = txtTargetFile.Text;
+ rdoTargetDesktop.Checked = infoSourceTemp.UseProject;
+ rdoTargetFile.Checked = infoSourceTemp.UseBimFile;
+ rdoTargetDataset.Checked = (!infoSourceTemp.UseProject && !infoSourceTemp.UseBimFile);
+ cboTargetDesktop.Text = infoSourceTemp.ProjectName;
+ //cboTargetDesktop.SelectedValue = infoSourceTemp.Project;
+ cboTargetDesktop.SelectedValue = portSourceTemp; //Fudge end
cboTargetServer.Text = infoSourceTemp.ServerName;
cboTargetDatabase.Text = infoSourceTemp.DatabaseName;
+ txtTargetFile.Text = infoSourceTemp.BimFile;
}
private void cboSourceServer_TextChanged(object sender, EventArgs e)
@@ -214,6 +409,35 @@ namespace BismNormalizer.TabularCompare.UI
}
}
+ private void btnSourceFileOpen_Click(object sender, EventArgs e)
+ {
+ OpenFileDialog ofd = OpenBimFileDialog();
+ if (ofd.ShowDialog() == DialogResult.OK)
+ {
+ txtSourceFile.Text = ofd.FileName;
+ Settings.Default.LastBimFileLocation = ofd.FileName;
+ }
+ }
+
+ private void btnTargetFileOpen_Click(object sender, EventArgs e)
+ {
+ OpenFileDialog ofd = OpenBimFileDialog();
+ if (ofd.ShowDialog() == DialogResult.OK)
+ {
+ txtTargetFile.Text = ofd.FileName;
+ Settings.Default.LastBimFileLocation = ofd.FileName;
+ }
+ }
+
+ private OpenFileDialog OpenBimFileDialog()
+ {
+ OpenFileDialog ofd = new OpenFileDialog();
+ ofd.InitialDirectory = (String.IsNullOrEmpty(Settings.Default.LastBimFileLocation) ? Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) : Settings.Default.LastBimFileLocation);
+ ofd.Filter = "BIM Files (.bim)|*.bim|All files (*.*)|*.*";
+ ofd.Title = "Open";
+ return ofd;
+ }
+
private void BindDatabaseList(string serverName, ComboBox cboCatalog)
{
try
@@ -239,5 +463,6 @@ namespace BismNormalizer.TabularCompare.UI
cboCatalog.DataSource = null;
}
}
+
}
}
diff --git a/BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/ManagedIpHelper.cs b/BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/ManagedIpHelper.cs
new file mode 100644
index 0000000..3bf88fb
--- /dev/null
+++ b/BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/ManagedIpHelper.cs
@@ -0,0 +1,282 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.NetworkInformation;
+using System.Runtime.InteropServices;
+
+namespace BismNormalizer.TabularCompare.UI.DesktopInstances
+{
+
+
+ #region Managed IP Helper API
+
+ public class TcpTable : IEnumerable
+ {
+ #region Private Fields
+
+ private IEnumerable tcpRows;
+
+ #endregion
+
+ #region Constructors
+
+ public TcpTable(IEnumerable tcpRows)
+ {
+ this.tcpRows = tcpRows;
+ }
+
+ #endregion
+
+ #region Public Properties
+
+ public IEnumerable Rows
+ {
+ get { return this.tcpRows; }
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ public IEnumerator GetEnumerator()
+ {
+ return this.tcpRows.GetEnumerator();
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return this.tcpRows.GetEnumerator();
+ }
+
+ #endregion
+ }
+
+ public class TcpRow
+ {
+ #region Private Fields
+
+ private IPEndPoint localEndPoint;
+ private IPEndPoint remoteEndPoint;
+ private TcpState state;
+ private int processId;
+
+ #endregion
+
+ #region Constructors
+
+ public TcpRow(IpHelper.TcpRow tcpRow)
+ {
+ this.state = tcpRow.state;
+ this.processId = tcpRow.owningPid;
+
+ int localPort = (tcpRow.localPort1 << 8) + (tcpRow.localPort2) + (tcpRow.localPort3 << 24) + (tcpRow.localPort4 << 16);
+ long localAddress = tcpRow.localAddr;
+ this.localEndPoint = new IPEndPoint(localAddress, localPort);
+
+ int remotePort = (tcpRow.remotePort1 << 8) + (tcpRow.remotePort2) + (tcpRow.remotePort3 << 24) + (tcpRow.remotePort4 << 16);
+ long remoteAddress = tcpRow.remoteAddr;
+ this.remoteEndPoint = new IPEndPoint(remoteAddress, remotePort);
+ }
+
+ #endregion
+
+ #region Public Properties
+
+ public IPEndPoint LocalEndPoint
+ {
+ get { return this.localEndPoint; }
+ }
+
+ public IPEndPoint RemoteEndPoint
+ {
+ get { return this.remoteEndPoint; }
+ }
+
+ public TcpState State
+ {
+ get { return this.state; }
+ }
+
+ public int ProcessId
+ {
+ get { return this.processId; }
+ }
+
+ #endregion
+ }
+
+ public static class ManagedIpHelper
+ {
+ #region Public Methods
+
+ public static TcpTable GetExtendedTcpTable(bool sorted)
+ {
+ List tcpRows = new List();
+
+ IntPtr tcpTable = IntPtr.Zero;
+ int tcpTableLength = 0;
+
+ if (IpHelper.GetExtendedTcpTable(tcpTable, ref tcpTableLength, sorted, IpHelper.AfInet, IpHelper.TcpTableType.OwnerPidAll, 0) != 0)
+ {
+ try
+ {
+ tcpTable = Marshal.AllocHGlobal(tcpTableLength);
+ if (IpHelper.GetExtendedTcpTable(tcpTable, ref tcpTableLength, true, IpHelper.AfInet, IpHelper.TcpTableType.OwnerPidAll, 0) == 0)
+ {
+ IpHelper.TcpTable table = (IpHelper.TcpTable)Marshal.PtrToStructure(tcpTable, typeof(IpHelper.TcpTable));
+
+ IntPtr rowPtr = (IntPtr)((long)tcpTable + Marshal.SizeOf(table.length));
+ for (int i = 0; i < table.length; ++i)
+ {
+ tcpRows.Add(new TcpRow((IpHelper.TcpRow)Marshal.PtrToStructure(rowPtr, typeof(IpHelper.TcpRow))));
+ rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(typeof(IpHelper.TcpRow)));
+ }
+ }
+ }
+ finally
+ {
+ if (tcpTable != IntPtr.Zero)
+ {
+ Marshal.FreeHGlobal(tcpTable);
+ }
+ }
+ }
+
+ return new TcpTable(tcpRows);
+ }
+
+ public static Dictionary GetExtendedTcpDictionary()
+ {
+ Dictionary tcpRows = new Dictionary();
+
+ IntPtr tcpTable = IntPtr.Zero;
+ int tcpTableLength = 0;
+
+ if (IpHelper.GetExtendedTcpTable(tcpTable, ref tcpTableLength, false, IpHelper.AfInet, IpHelper.TcpTableType.OwnerPidAll, 0) != 0)
+ {
+ try
+ {
+ tcpTable = Marshal.AllocHGlobal(tcpTableLength);
+ if (IpHelper.GetExtendedTcpTable(tcpTable, ref tcpTableLength, true, IpHelper.AfInet, IpHelper.TcpTableType.OwnerPidAll, 0) == 0)
+ {
+ IpHelper.TcpTable table = (IpHelper.TcpTable)Marshal.PtrToStructure(tcpTable, typeof(IpHelper.TcpTable));
+
+ IntPtr rowPtr = (IntPtr)((long)tcpTable + Marshal.SizeOf(table.length));
+ for (int i = 0; i < table.length; ++i)
+ {
+ TcpRow row = new TcpRow((IpHelper.TcpRow)Marshal.PtrToStructure(rowPtr, typeof(IpHelper.TcpRow)));
+ // HACK: only add first row that is in a Listening state
+ if (row.State == TcpState.Listen)
+ {
+ if (!tcpRows.Keys.Contains(row.ProcessId))
+ tcpRows.Add(row.ProcessId, row);
+ }
+ rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(typeof(IpHelper.TcpRow)));
+ }
+ }
+ }
+ finally
+ {
+ if (tcpTable != IntPtr.Zero)
+ {
+ Marshal.FreeHGlobal(tcpTable);
+ }
+ }
+ }
+
+ return tcpRows;
+ }
+
+
+ #endregion
+ }
+
+ #endregion
+
+ #region P/Invoke IP Helper API
+
+ ///
+ ///
+ ///
+ public static class IpHelper
+ {
+ #region Public Fields
+
+ public const string DllName = "iphlpapi.dll";
+ public const int AfInet = 2;
+
+ #endregion
+
+ #region Public Methods
+
+ ///
+ ///
+ ///
+ [DllImport(IpHelper.DllName, SetLastError = true)]
+ public static extern uint GetExtendedTcpTable(IntPtr tcpTable, ref int tcpTableLength, bool sort, int ipVersion, TcpTableType tcpTableType, int reserved);
+
+ #endregion
+
+ #region Public Enums
+
+ ///
+ ///
+ ///
+ public enum TcpTableType
+ {
+ BasicListener,
+ BasicConnections,
+ BasicAll,
+ OwnerPidListener,
+ OwnerPidConnections,
+ OwnerPidAll,
+ OwnerModuleListener,
+ OwnerModuleConnections,
+ OwnerModuleAll,
+ }
+
+ #endregion
+
+ #region Public Structs
+
+ ///
+ ///
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct TcpTable
+ {
+ public uint length;
+ public TcpRow row;
+ }
+
+ ///
+ ///
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct TcpRow
+ {
+ public TcpState state;
+ public uint localAddr;
+ public byte localPort1;
+ public byte localPort2;
+ public byte localPort3;
+ public byte localPort4;
+ public uint remoteAddr;
+ public byte remotePort1;
+ public byte remotePort2;
+ public byte remotePort3;
+ public byte remotePort4;
+ public int owningPid;
+ }
+
+ #endregion
+
+ #endregion
+ }
+}
diff --git a/BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/PowerBIHelper.cs b/BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/PowerBIHelper.cs
new file mode 100644
index 0000000..552e221
--- /dev/null
+++ b/BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/PowerBIHelper.cs
@@ -0,0 +1,110 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+//using Serilog;
+using System.Security.Principal;
+
+namespace BismNormalizer.TabularCompare.UI.DesktopInstances
+{
+ public enum EmbeddedSSASIcon
+ {
+ PowerBI,
+ Devenv,
+ PowerBIReportServer,
+ Loading
+ }
+ public class PowerBIInstance
+ {
+ public PowerBIInstance(string name, int port, EmbeddedSSASIcon icon)
+ {
+ var dashPos = name.LastIndexOf(" - ");
+ if (dashPos >= 0)
+ { Name = name.Substring(0, dashPos); } // Strip "Power BI Designer" or "Power BI Desktop" off the end of the string
+
+ Port = port;
+ Icon = icon;
+ }
+ public string Name { get; private set; }
+ public int Port { get; private set; }
+
+ public EmbeddedSSASIcon Icon { get; private set; }
+ }
+
+ public class PowerBIHelper
+ {
+
+ public static List GetLocalInstances()
+ {
+ List _instances = new List();
+
+ _instances.Clear();
+
+ var dict = ManagedIpHelper.GetExtendedTcpDictionary();
+ foreach (var proc in Process.GetProcessesByName("msmdsrv"))
+ {
+ int _port = 0;
+ EmbeddedSSASIcon _icon = EmbeddedSSASIcon.PowerBI;
+ var parent = proc.GetParent();
+
+ // exit here if the parent == "services" then this is a SSAS instance
+ if (parent.ProcessName.Equals("services", StringComparison.OrdinalIgnoreCase)) continue;
+
+ // exit here if the parent == "RSHostingService" then this is a SSAS instance
+ if (parent.ProcessName.Equals("RSHostingService", StringComparison.OrdinalIgnoreCase))
+ {
+ // only show PBI Report Server if we are running as admin
+ // otherwise we won't have any access to the models
+ if (IsAdministrator())
+ _icon = EmbeddedSSASIcon.PowerBIReportServer;
+ else
+ continue;
+ }
+
+ // if the process was launched from Visual Studio change the icon
+ if (parent.ProcessName.Equals("devenv", StringComparison.OrdinalIgnoreCase)) _icon = EmbeddedSSASIcon.Devenv;
+
+ // get the window title so that we can parse out the file name
+ var parentTitle = parent.MainWindowTitle;
+ if (parentTitle.Length == 0)
+ {
+ // for minimized windows we need to use some Win32 api calls to get the title
+ //parentTitle = WindowTitle.GetWindowTitleTimeout( parent.Id, 300);
+ parentTitle = WindowTitle.GetWindowTitle(parent.Id);
+ }
+
+ // try and get the tcp port from the Win32 TcpTable API
+ //try
+ //{
+ TcpRow tcpRow = null;
+ dict.TryGetValue(proc.Id, out tcpRow);
+ if (tcpRow != null)
+ {
+ _port = tcpRow.LocalEndPoint.Port;
+ _instances.Add(new PowerBIInstance(parentTitle, _port, _icon));
+ //Log.Debug("{class} {method} PowerBI found on port: {port}", "PowerBIHelper", "Refresh", _port);
+ }
+ // else
+ // {
+ // //Log.Debug("{class} {method} PowerBI port not found for process: {processName} PID: {pid}", "PowerBIHelper", "Refresh", proc.ProcessName, proc.Id);
+ // }
+
+ //}
+ //catch (Exception ex)
+ //{
+ // //Log.Error("{class} {Method} {Error} {StackTrace}", "PowerBIHelper", "Refresh", ex.Message, ex.StackTrace);
+ //}
+
+ }
+ return _instances;
+ }
+
+ public static bool IsAdministrator()
+ {
+ WindowsIdentity identity = WindowsIdentity.GetCurrent();
+ WindowsPrincipal principal = new WindowsPrincipal(identity);
+ return principal.IsInRole(WindowsBuiltInRole.Administrator);
+ }
+
+
+ }
+}
diff --git a/BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/ProcessExtensions.cs b/BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/ProcessExtensions.cs
new file mode 100644
index 0000000..8b14a55
--- /dev/null
+++ b/BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/ProcessExtensions.cs
@@ -0,0 +1,31 @@
+using System.Diagnostics;
+using System.Linq;
+using System.Management;
+
+namespace BismNormalizer.TabularCompare.UI.DesktopInstances
+{
+ public static class ProcessExtensions
+ {
+ public static Process GetParent(this Process process)
+ {
+ try
+ {
+ using (var query = new ManagementObjectSearcher(
+ "SELECT ParentProcessId " +
+ "FROM Win32_Process " +
+ "WHERE ProcessId=" + process.Id))
+ {
+ return query
+ .Get()
+ .OfType()
+ .Select(p => Process.GetProcessById((int)(uint)p["ParentProcessId"]))
+ .FirstOrDefault();
+ }
+ }
+ catch
+ {
+ return null;
+ }
+ }
+ }
+}
diff --git a/BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/WindowTitle.cs b/BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/WindowTitle.cs
new file mode 100644
index 0000000..83c1797
--- /dev/null
+++ b/BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/WindowTitle.cs
@@ -0,0 +1,161 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BismNormalizer.TabularCompare.UI.DesktopInstances
+{
+ public class WindowTitle
+ {
+
+
+ //static void Main(string[] args)
+ //{
+ // var p = Process.GetProcessById(3484);
+ // var h = p.MainWindowHandle;
+
+ // string s = GetWindowTextTimeout(h, 100 /*msec*/);
+
+ //}
+
+
+
+ #region PInvoke calls to get the window title of a minimize window
+
+ delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);
+
+ [DllImport("user32.dll")]
+ static extern bool IsWindowVisible(IntPtr hWnd);
+
+
+ [DllImport("user32.dll")]
+ static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn,
+ IntPtr lParam);
+
+ [DllImport("User32.dll", SetLastError = true)]
+ public unsafe static extern int SendMessageTimeout(
+ IntPtr hWnd,
+ uint uMsg,
+ uint wParam,
+ StringBuilder lParam,
+ uint fuFlags,
+ uint uTimeout,
+ void* lpdwResult);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
+ static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam,
+ StringBuilder lParam);
+
+ [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ static extern int GetWindowTextLength(IntPtr hWnd);
+
+ [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ static extern long GetWindowText(IntPtr hwnd, StringBuilder lpString, long cch);
+
+ const int WM_GETTEXT = 0x000D;
+ const int WM_GETTEXTLENGTH = 0x000E;
+
+ #endregion
+
+
+ private static IEnumerable EnumerateProcessWindowHandles(int processId)
+ {
+ var handles = new List();
+
+ foreach (ProcessThread thread in Process.GetProcessById(processId).Threads)
+ EnumThreadWindows(thread.Id,
+ (hWnd, lParam) => { handles.Add(hWnd); return true; }, IntPtr.Zero);
+
+ return handles;
+ }
+
+
+ public static string GetWindowTitle(int procId)
+ {
+ foreach (var handle in EnumerateProcessWindowHandles(procId))
+ {
+ StringBuilder message = new StringBuilder(1000);
+ if (IsWindowVisible(handle))
+ {
+ //SendMessage(handle, WM_GETTEXT, message.Capacity, message);
+ //if (message.Length > 0) return message.ToString();
+ return GetCaptionOfWindow(handle);
+ }
+
+ }
+ return "";
+ }
+
+ /* ====================================== */
+
+ public static string GetWindowTitleTimeout(int procId, uint timeout)
+ {
+ string title = "";
+ foreach (var handle in EnumerateProcessWindowHandles(procId))
+ {
+ try
+ {
+ // if there is an issue with the window handle we just
+ // ignore it and skip to the next one in the collection
+ title = GetWindowTextTimeout(handle, timeout);
+ }
+ catch
+ {
+ title = "";
+ }
+ if (title.Length > 0) return title;
+ }
+ return title;
+ }
+
+
+ private static unsafe string GetWindowTextTimeout(IntPtr hWnd, uint timeout)
+ {
+ int length;
+ if (SendMessageTimeout(hWnd, WM_GETTEXTLENGTH, 0, null, 2, timeout, &length) == 0)
+ {
+ return null;
+ }
+ if (length == 0)
+ {
+ return null;
+ }
+
+ StringBuilder sb = new StringBuilder(length + 1); // leave room for null-terminator
+ if (SendMessageTimeout(hWnd, WM_GETTEXT, (uint)sb.Capacity, sb, 2, timeout, null) == 0)
+ {
+ return null;
+ }
+
+ return sb.ToString();
+ }
+
+ private static string GetCaptionOfWindow(IntPtr hwnd)
+ {
+ string caption = "";
+ StringBuilder windowText = null;
+ try
+ {
+ int max_length = GetWindowTextLength(hwnd);
+ windowText = new StringBuilder("", max_length + 5);
+ GetWindowText(hwnd, windowText, max_length + 2);
+
+ if (!String.IsNullOrEmpty(windowText.ToString()) && !String.IsNullOrWhiteSpace(windowText.ToString()))
+ caption = windowText.ToString();
+ }
+ catch (Exception ex)
+ {
+ caption = ex.Message;
+ }
+ finally
+ {
+ windowText = null;
+ }
+ return caption;
+ }
+
+ }
+}