Infosys Microsoft Alliance and Solutions blog

« June 2007 | Main | August 2007 »

July 26, 2007

WPF - Finding Control Location

Recently for a sample application I was building in WPF, I had to find the location of a button control on the window. Playing around with Button.Margin didn't help much since it gave the position with reference to the immediate parent. So if the button was inside a Grid and the grid itself inside say a StackPanel, the values were incorrect.

Searching on the forums, I got some ideas and following is what worked for me

            GeneralTransform transform = button1.TransformToAncestor(this);

            Point rootPoint = transform.Transform(new Point(0, 0));

button1 is the control for whom I wanted to find the location. The this represents the top level window. The value obtained in rootPoint is the Left and Top cordinates of the button with respect to the top level window. Adding button's height and width will give the complete location details.

 

July 17, 2007

Handling AppDomain's AssemblyLoad Event

In my earlier blog I had discussed about creating a new AppDomain. You may have a need to track the loading of assemblies in this newly created AppDomain. AppDomain class provides an event for this purpose called AssemblyLoad. However when I tried to work with it, I never got the event to fire up.

The catch is that the event handler needs to be static. When I had added the event handler via VS 2005 by using the tip that appears once you type "+=" after an event, it added the event handler as private void and missed the "static" qualifier. Due to this the event handler was not getting called. Once I added this, it started to work like a breeze. The handler signature will look something like the following

        static void domain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)

        {

            //add code to handle assembly load event here

        }

July 10, 2007

Windows Workflow Foundation Web Workflow Approvals Starter Kit – A Review

As you might be aware Microsoft had released the WF web workflow approvals starter kit which is a Visual Studio 2005 project that demonstrates using Windows Workflow Foundation for simple task-oriented workflow in an ASP.NET Web application.

I decided to review the starter kit so as to understand how efficiently and easily this starter kit could be used to develop simple task-oriented workflows in ASP.NET web applications. Let me list down my viewpoints on the same.

  • For starters, I personally think that the starter kit code is a little complicated to understand for even a developer who has sufficient coding experience on the .Net platform and has basic knowledge of WF. The implementation needs to be simplified, if possible, so that a developer can easily understand the logic. I saw similar concerns being raised on other forums as well.
  • To worsen things, the 8 page documentation that comes with the starter kit gives just an overview about the project structure and its contents and doesn’t really help much in understanding the sample and its architecture in detail. A better documentation would really help. But the good news is that the WF team at Microsoft is soon going to release a whitepaper on the starter kit that describes the sample in more detail.
  • Another thing which I found interesting is the usage of a custom activity called “User activity”, when I think the out of the box HandleExternalEvent activity could have been used to achieve the same functionality and it would have made the sample look a little more simpler as well. Again this is another question which I found many people raising on different forums.
  • The workflow image viewer component that is part of the application is a component that would generate the workflow image at runtime with the currently executing activity highlighted; in PNG format. This I thought was really a cool feature and was something that caught my eye. But was something as advanced as this required in a starter kit? I am really not very sure.
  • From a core workflow perspective, things looked very simple and easy to understand; apart from the custom activity which I think could have been done away with.
All in all I feel that the starter kit could have been much simpler than what it actually is. But again if you are an experienced developer you would surely know what to take from these kits and what not Laughing. But I guess when the whitepaper on this starter kit comes out, some or all of these questions could get answered and we would get a much clearer picture. But I would encourage you to try the sample out. The starter kit can be downloaded from here. Try it out and let me know your viewpoints and opinions on the same.

Hello People!!!

This is my first post on this blog and I am elated to have been given the opportunity to write on this blog, where I think the best of technical experts at Infosys on various Microsoft products and technologies express their views and opinions. Let me first introduce myself. I am E.Krishna Kumar, working as a Technical Specialist with the Microsoft Technology Center at Infosys Technologies Ltd., Bangalore. I have been with Infosys for more than 3 years now and have been primarily working on the Microsoft .Net platform. I have had the experience of developing applications on .Net Framework 1.0, 1.1, 2.0 and 3.0. My current area of interest is .Net 3.0 and especially the Workflow Foundation part which I am presently trying to build up some expertise on.

I have always believed in sharing information and knowledge with the larger lot and getting to know what their views and opinions are on the same. It’s so much of a learning exercise and believe me you get lot of interesting and thought provoking viewpoints when it comes to technology. I have already got a taste of that on my blog, where I usually discuss about technologies that interest me. I have been a little busy of late and need to do a lot catching up on my blogging. Hope to share my experience, problems, solutions, viewpoints and information on the latest Microsoft technologies. I would also encourage you to let us know your experience and viewpoints on the same.

Good Day!!! Laughing

July 09, 2007

Software Factory: Behavior based Meta-Models

There was one quote I remember from somewhere: “Code as if the guy who is going to maintain your code is a manic serial killer who knows where you live”. Scary thought, but I swear by it.

When a software moves into production and on to the maintenance mode, that’s when the real fun begins. It starts with a tiny change to the UI to reduce the color contrast of the OK button. Then it moves onto a tiny change in some rule and then a brand new version of an embedded component arrives making the developer upgrade the application. And a few weeks later, the software is nothing close to what its design documents claimed it to be.

What we notice here is a systematic degeneration of the application as incremental changes are made to it over a period of time. The looming threat is that of an application that changes too much that the original developer himself finds it hard to figure out what has changed and what has not.

This applies to the world of Software Factories and Domain-Specific Modeling as well. As we saw in the previous posts, the Meta-Models form the basic building blocks for the Software Factories as they provide the modeling vocabulary. From the created models, Code generation tools begin to operate to generate a number of source code and other artifacts. But every generated artifact is only as good as the developer who would work on it at a late point in time. The developer could start making incremental changes to such an extent that the generated artifacts would no more remain as a representation of the models.

This leads us to another classification of Meta-Models which will be based on their Behavior.

1. Well-Formed Meta-Models
2. Valid Meta-Models

A Well-Formed Meta-Model is one which adheres to all the vocabulary as dictated by the problem domain. All business rules, events, validations are captured and handled as required by the Software Factory. A Well-Formed Meta-Model is Self-Explanatory and lets one create models which is easy enough for Code Generation tools to parse and generate artifacts.

A Valid meta-Model is one which is Well-Formed and synchronous with every artifact generated by its models. For example, if a number of source code files are generated, and changes are made to the source code, then those changes must be reflected back into the Meta-Model.

In the Software Factory Scheme of things, you should always strive to keep your models Valid and not just Well-Formed. But the process of reverse synchronization is certainly not a simple one. I’ll deal with this subject in detail in a later post.

Now what we have discussed about Meta-Models and their role, in the next post I’ll discuss some ideas on creating Models from Meta-Models.

July 06, 2007

WPF Application Default Assembly Version

If you have worked with .NET 2.0 and VS 2005 and then move onto .NET 3.0 and WPF, be careful of the default assembly version. From .NET 1.1 to .NET 2.0, a change was made to default the assembly version to 1.0.0.0 in the AssemblyInfo.cs file, since the C# compiler would otherwise keep incrementing these values everytime you hit "build".

Seems like with for WPF in .NET 3.0, this change has been reversed, if you are working with the WPF Extensions running with VS 2005. The WCF and WF extensions still use 1.0.0.0 as the default version. So if you are working with WPF extensions, be careful, else you will end up having always changing version numbers.

However this seems to have been fixed in Orcas. I checked with Orcas Beta 1 and the version number for WPF apps has again been defaulted to 1.0.0.0.

July 05, 2007

Creating and Working with Applications in AppDomains

We all have read that AppDomains are light weight processes that .net uses to run applications, but I hardly ever played with AppDomains directly. Recently I decided to give this a try and following are my findings. If you want to get more information on AppDomains, check this excellent blog by Chris Brumme.

To create a new AppDomain, you use the static method CreateAppDomain and can give a friendly name to the AppDomain at this time. Once the domain is created, you can call ExecuteAssembly to load and run an assembly from its entry point. The code will look something like the following. For my testing, I worked with an application that can execute on its own.

            AppDomain ad = AppDomain.CreateDomain("test");

            ad.ExecuteAssembly("DummyApp.exe");

Note that the above assumes that the DummyApp.exe is in the same path is the calling application, else complete path will need to be specified.

In .net 2.0 a new method ExecuteAssemblyByName has been added and is the preferred method to use. As documented, these methods execute the entry point, but not on a different thread. This means that while the loaded assembly is executing, the application that started it, will not execute further, since the primary thread is busy executing the assembly loaded in the new AppDomain. You will have to close the assembly (in case of applications) or unload the AppDomain to continue ahead with your main application.

In case you want to work with both the applications, you can create the AppDomain on a different thread. The code will look something like the following

        {

            Thread th = new Thread(new ThreadStart(func1));

            th.Start();

        }

 

        private void func1()

        {

            AppDomain ad = AppDomain.CreateDomain("test");

            ad.ExecuteAssembly("DummyApp.exe");

        }

To close the newly created AppDomain in this case, you can do a thread abort or upload the AppDomain. In my code, when working with .net Winform applications, i had issues in unloading the AppDomains and hence I had to work with thread abort. However thread abort it abrut and brute force method to kill that AppDomain and the executing assembly may not close gracefully.

If that assembly is an application, you will have multiple options to handle this thread abort and try and exit gracefully. The various event handlers that you can handle are as below. First place to write handlers is in the MainForm and handle deactivation and handledestroyed events.

        protected override void OnDeactivate(EventArgs e)

        {

            //do your clean up logic here

            base.OnDeactivate(e);

        }

 

        protected override void OnHandleDestroyed(EventArgs e)

        {

            //handle already destroyed. be careful of what you want to clean up here

            base.OnHandleDestroyed(e);

        }

The other option is to handle the ThreadAbortException in the Program.cs file from where the application has been started.  

        static void Main()

        {

            Application.EnableVisualStyles();

            Application.SetCompatibleTextRenderingDefault(false);

            Form1 frm = new Form1();

            try

            {

                Application.Run(frm);

            }

            catch (ThreadAbortException ex)

            {

                //form is Inaccessible by this time and is disposed

                MessageBox.Show(ex.Message);

            }

        }

I also tried the same with WPF applications. A few issues with WPF and AppDomains are listed here. I could get things working with WPF applications as well. I am not sure at this time if all will work well or not, since I haven't done any extensive testing.

A key thing to note with WPF however is setting the correct thread apartment state, else while trying to execute a WPF application in a new AppDomain, you will get an error which reads something like following

"Cannot create instance of 'Window1' defined in assembly 'DummyApp, Version=1.0.2739.17241, Culture=neutral, PublicKeyToken=null'. Exception has been thrown by the target of an invocation.  Error in markup file 'Window1.xaml'."

This may sound tricky since the WPF application on its own runs without issues. It turns out that finding the solution to this issue is also fairly simple since the inner exception states this - "{"The calling thread must be STA, because many UI components require this."}". Hence prior to starting the thread, we need to set the apartment state of the thread as shown below

            Thread th = new Thread(new ThreadStart(func1));

            th.SetApartmentState(ApartmentState.STA);

            th.Start();

With this in place, I found that the WPF application loaded in the AppDomain worked fine. Surprisingly, the AppDomain.Unload method also worked, which had thrown error when working with Winform applications.

As I mentioned earlier, I haven't done extensive testing on this. If you have any other experience or comment to make, do write back.