Showing posts with label CSharp. Show all posts
Showing posts with label CSharp. Show all posts

Wednesday, July 1, 2015

WPF Error: System.Windows.Baml2006.TypeConverterMarkupExtension' threw an exception.

image

This was coming after successful compile but while executing the application.. However, after searching, from one post on StackOverFlow I got know that one of the image in my Resource is not in proper uri. That’s what I corrected and it started working fine.

Initially it was:

<Border.Background>             
      <ImageBrush ImageSource="Resources/BG-horizontal.png" />
</Border.Background>



And when changed to following, it started working fine: See highlighted change.

<Border.Background>             
      <ImageBrush ImageSource="../Resources/BG-horizontal.png" />
</Border.Background>
 

Thursday, July 17, 2014

Console Messaging: Error, Warning, Colored Text etc.

Here are some methods, I used in my Console applications to show Errors, Warnings, or simple colorful Text:

private static void ConsoleWrite(string FormattedString, ConsoleColor TextColor)
{
	ConsoleColor curColor = Console.ForegroundColor;
	Console.ForegroundColor = TextColor;
	Console.WriteLine(FormattedString);
	Console.ForegroundColor = curColor; //Restoring original console foreground color.
}
private static void ShowError(string FormattedString)
{
	ConsoleWrite(FormattedString, ConsoleColor.Red);
}
private static void ShowSuccess(string FormattedString)
{
	ConsoleWrite(FormattedString, ConsoleColor.Green);
}
private static void ShowWarning(string FormattedString)
{
	ConsoleWrite(FormattedString, ConsoleColor.DarkYellow);
}

Try, Catch, Retry with DTE2 interface.

I had a task to create multiple solutions while adding projects into them by parsing a list file containing the path and names of solutions and their related projects. So using C#, I started writing a utility consuming Visual Studio 2013 Automation Interface.

While creating the Com object of EnvDTE80.DTE2 it sometimes throwing exception with message:

The message filter indicated that the application is busy.

However, while debugging, on resuming 1 or 2 times, it went fine. So this makes me to find some Try Catch and Retry solution. After some googling, Here is the most basic way, I used to get rid of this problem:

EnvDTE80.DTE2 dte=null;
Solution4 solutionObject=null;
Console.WriteLine("Creating DTE Object...");
for (int r = 0; r < 5; r++)
{
  try
    {
     Console.WriteLine(string.Format("Tried {0} times", r));
     System.Type type = System.Type.GetTypeFromProgID("VisualStudio.DTE.12.0");
     //DTE2 dte2 = (DTE2)Microsoft.VisualBasic.Interaction.CreateObject("VisualStudio.DTE.12.0", "");
     Object obj = System.Activator.CreateInstance(type, true);
     dte = (EnvDTE80.DTE2)obj;
     solutionObject = (Solution4)dte.Solution;
     ConsoleWrite("Done", ConsoleColor.Cyan);
     break; //reaching here means, it was successful, so get out of loop
    }
    catch (Exception)
    {
	 System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2)); //let give a delay of 2 seconds
     if (r >= 4)
        throw; //So if it is not successful after 4 retries, throw the exception
    }
}

Thursday, July 10, 2014

Wix Bootstrapper: Exit/End during installation.

 


During CacheAcquireProgress Event:
this.model.BootstrapperApplication.CacheAcquireProgress += (sender, args) =>
{
//if ever detected InstallState.Cancelled (which can be set from other event like Exit Button Click)
if (this.State == InstallState.Cancelled)
args.Result =
Result.Cancel;
//this would quit installation process.
.
.
.
};
During ExecuteProgress Event:
this.model.BootstrapperApplication.ExecuteProgress += (sender, args) =>
{
//if ever detected InstallState.Cancelled (which can be set from other event like Exit Button Click)
if (this.State == InstallState.Cancelled)
args.Result =
Result.Cancel; //this would quit installation process.
.
.
.

};

So if InstallState.Cancelled is ever setup, it would set args.Result=Result.Cancel and so it would quit installation.

Wednesday, July 25, 2012

Patching a build which has changed Component Ids (GUIDs)

Installer patches are used to patch an already installed product in order to update/add some more features or fixation of errors/bugs etc.
While creation a patch for a product about whom, the build procedure is not known to me, I first tried WIX provided Patch Creation Properties (.pcp file) method, which resulted in a big sized msp file (500+ MB). When I tried to apply the patch, it shows the setup dialogs for Updated build but failed with following message:
"Another version is already installed. You must first uninstall it in order to install this version."
I even changed the Product Code in the 2nd msi (in all tables), but  doesn’t solved any problem.
Then changing attribute value of WholeFilesOnly="no" from ‘yes’  under PatchCreation element reduced the size to 262 MB (I know its not a small size for a patch). But resulted in same error when tried to apply on installed product.
Alternatively, I tried msdn tutorial for using Patch Creation Properties (.pcp) file and that resulted in exactly same problem as that of Wix pcp case.
The I tried Wix Patching which actually supports making a patch by selectively adding Components to be patched on target machine. So I added few components, just to prototype it. And when Pyro.exe complaint about different GUIDs, that makes me to check for Component Ids (GUIDS) in both builds.
If you have installed Microsoft SDK 7.x then there would be a script file installed as C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\sysmgmt\msi\scripts\WiDiffDb.vbs. I used this file to get a difference report between the Updated Msi and Target msi and to my surprise, every Component Id (GUID) was changed in Updated build.
To confirmed my doubt, I then took differences between other versions and found that Component Ids were totally refreshed in every build.
Well, why we should not change the Component Ids without any specific reason,  can be measured from this article. And when to change Component GUIDs, read this.
Anyhow, I’m sure, that there could be some reason behind changing Component GUIDs in every build, but that causes problems in generating patches.
To cope with this situation, I played a small hack with the Upgraded msi.. Guess What.. here is the CSharp source code for that hack Smile.
C# - Update Component Ids
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.IO;
  6. using WindowsInstaller;
  7.  
  8. namespace msitest
  9. {
  10.     class Program
  11.     {
  12.         static void Main(string[] args)
  13.         {
  14.             string OrignalMSI = @"D:\ABD\OriginalBuild_225en1\MyProduct.msi";
  15.             string UpdatedMSI = @"D:\ABD\UpdatedBuild_351en1\MyProduct.msi";
  16.             
  17.             string strFileMsiNameOnly = Path.GetFileNameWithoutExtension(OrignalMSI);
  18.             string strDirectory = Path.GetDirectoryName(OrignalMSI);
  19.  
  20.             // Create an Installer instance
  21.             Type classType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
  22.             Installer inst = (Installer)Activator.CreateInstance(classType);
  23.  
  24.             Database OriginalMSIdb = inst.OpenDatabase(OrignalMSI, MsiOpenDatabaseMode.msiOpenDatabaseModeReadOnly);
  25.             Database UpdatedMSIdb = inst.OpenDatabase(UpdatedMSI, MsiOpenDatabaseMode.msiOpenDatabaseModeTransact);
  26.             
  27.             
  28.             View OrgMsiView = OriginalMSIdb.OpenView("Select `Component`,`ComponentId` From Component");
  29.             View UpdMsiView = null;
  30.             
  31.             OrgMsiView.Execute(null);
  32.             
  33.             Dictionary<string,string> OrgMsiComponents=new Dictionary<string,string>();
  34.             Record OrgMsiRecord = OrgMsiView.Fetch();
  35.             
  36.             string updQuery="";
  37.  
  38.             while (OrgMsiRecord != null)
  39.             {
  40.                 Console.WriteLine(OrgMsiRecord.get_StringData(1) + " " + OrgMsiRecord.get_StringData(2));
  41.                 updQuery = "Update `Component` SET `Component`.`ComponentId`=" + "'" + OrgMsiRecord.get_StringData(2) + "'" + " WHERE `Component`.`Component`=" + "'" + OrgMsiRecord.get_StringData(1) + "'";
  42.                 UpdMsiView=UpdatedMSIdb.OpenView(updQuery);
  43.                 UpdMsiView.Execute(null);
  44.                 
  45.     
  46.                 //consolestring result = r.get_StringData(1);
  47.                 OrgMsiRecord = OrgMsiView.Fetch();
  48.             }
  49.  
  50.             UpdatedMSIdb.Commit();
  51.             // close the database
  52.             OrgMsiView.Close();
  53.             UpdMsiView.Close();
  54.         }
  55.     }
  56. }
Yes, reading Component Ids from Original MSI and replacing in Updated msi while comparing Component Names and making Component GUIDs same in both msi.
And now when I tried to create patch using Wix Patching … O Yes, it worked.. and I’ve working patch and when I tested, it worked as expected. Smile.Star
And then I tried to use Patch Creation Properties (*.pcp) methods again with this modified Updated msi, but in vain. Problem never changed Sad smile.
The only difference is that, this method needs a selection of Component manually, while in Patch Creation Properties (*.pcp) methods, it took whole builds differences and generates a patch upon these.
Although, Wix Patching is the only working solution I have in this situation, but Product owners are not happy with this Sad smile. Because now they have to select files manually.
Anyhow, I’m still looking for some other solutions. And you have some better solution/correction/Tutorial etc etc. you are most welcome to share it..

Saturday, July 21, 2012

How to send AutoCAD commands via C#?

I’m working on an AutoCAD plugin in .Net (C#) and  was trying to insert Blocks from multiple DWG files into drawing area via C#.  Initially I was trying to write routines for Drag & Drop, Rotating, Scaling etc. However, AutoCAD’s built-in command “INSERT” is doing all such tasks. So I started looking for the method to Execute AutoCAD’s built-in commands.

I tried INSERT command and here is a code segment from  my C# Project initiated with AutoCAD.Net Wizards (Download from Autodesk Developer Network).

AutoCAD Command Method (C#)
  1.       [CommandMethod("InsertDWG")]
  2.         static public void SendINSERTCmd()
  3.         {
  4.             string DWG = @"D:\MYDWGs\1047.DWG";
  5.             string InsertCmd = @"_.-INSERT " + DWG + '\r' + '\n';
  6.             Document doc = Application.DocumentManager.MdiActiveDocument;
  7.             doc.SendStringToExecute(InsertCmd, true, false, false);
  8.         }

After compiling your code, use “NetLoad” to load your .net DLL and issue “InsertDWG”. You  will see the command line in AutoCAD’s command window. Drawing Block would be attached to your mouse pointer and you would be able to Drag, Drop, Scale, Rotate and all perform all functions that are provided in AutoCAD normally.