Friday, April 24, 2009

Use WPF Themes and styles


WPF, the future of Window Forms and Programming, has some fantastic flexibility to create excellent styles and apply with an immense ease. Here is an example, we can apply the themes to our WPF UIs, and the theme will take care of styles of the components used in the window. See the following link:

WPF Themes Home. Samantha is great :)

Hope this helps!

Thanks,
Vikas

Monday, April 6, 2009

Ghost Instance Problem in office application

Hi All,

A number of office programmers face the Ghost Instance issue while developing office applications. The ghost instance is an instance of office application which is not closed properly. In this scenario, you will be able to see the application entry in the Porcess list of task manager but it will not be visible for the user. I will explain the context by using an example of powerpoint Addin(Obviously in dot net).

Q. How does it occur?

Ans. I create a PowerPoint(aka, PP)Addin, and in that PP Addin I try to create an excel(aka, XL) Application object. Now if I do extensive programming using XL objects(like Range, Shapes, Worksheet etc), these InterOP variables stay in Memory and not handled by the CLR. You will need to explicitly release every COM Object by using System.Runtime.InteropServices.Marshal.ReleaseCOMObject(theObjectToBeReleased) method. But, even after releasing the objects few of the instances keep on running in memory. So if the variables are running in the memory, and I try to close the excel, the excel gets closed but its process keeps on running in the task Manager List. When we hit close button(the cross button in TopLeftHand corner) in Excel, the CLR first closes all the AddIns opened, and then closes the excel window. If there is any COM running in the memory the AddIns get removed but the CLR is unable to close the Excel properly. The result is Ghost Instance. In case of Ghost Instance running in the task manager, if we open any Excel File by double clicking the file, it will open the file but it will Not load any Addins. Reason is barely simple, the Addins were already closed by CLR but not the Excel Application Instance. So the file is actually opened in the previous Excel Ghost Instance.

Q. What is the solution?
Ans. One solution to the problem is: Go to task Manager, Process Tab, and kill the Excel.EXE instance.
The other solution is to include the following approach in AddInShutDown event of your code. This work around uses the Process Class.

1. Try to get the list of Processes by GetProcessByName method :
Process[] processes = Process.GetProcessesByName("EXCEL")
2. Run through Each Process in the processes Array and check if process.MainWindowHandle.ToInt64() is equal to 0. If this is 0 then you will need to kill the process right away.
3. The only thing you will need to take care is, to create a time Lag so that all the AddIns should shut down first then you will need to call the above steps.
4. Creating a Time lag means, you can use a separate EXE, which will run the above steps say 5 seconds after the Excel Closing event was fired.

Hope this helps :)

Thanks,
Vikas

Friday, April 3, 2009

Problem in using Information.TypeName Property

Hi All,

Whenever we debug the code in Dot Net while using InterOP, it is very frequent to notice a proxy object rather than the actual InterOP object. When you try to get the properties of an InterOP Variable, it shows you some proxy object, and not the actual InterOP object. For example, if I declare a variable like following :

Dim xlApp as XL.Application (The excel Application object)
set xlApp = ME.Globals.ThisAddin.Application

Now, in the debug mode, after executing the above line, if I want to see what values are stored in xlApp variable, the dot net editor will show the variable as a Runtime.Proxy object most of the times. The reason is, that normally, the InterOP layer creates a wrapper object to avoid any problems running in non EN-US locales.

Due to this behavior, I faced one problem. I was not able to obtain the Type Name of application' selection object because the selection object was coming as a proxy wrapper. I tried something like this :

Dim selectionType as string

selectionType = Information.TypeName(xlApp.Selection)

The above line was giving a System.Reflection.TargetInvocationException. I had to change my project's setting to ensure that the InterOp variables are not proxy objects. For that, I went to MyProject folder in my solution, opened the AssemblyInfo.vb file, change the attribute < Assembly: ExcelLocale1033(True) > set to < Assembly: ExcelLocale1033(False) > and saved the file. And see the difference, it didn't give me a proxy object :)

See the following thread For the example:
MSDN VSTO Thread Link.