Developing For .NET

Real World .NET Methods, Tricks, and Examples

Blend-O-Rama Redux



In case you missed it, July 19-23rd we held the first ever Blend-O-Rama Event.  Hosted by HRNUG, moderated by Kevin Griffin (MVP and HRNUG President), and presented by yours truly, the event was a week of Lunch and Learn webcasts all about Expression Blend and presented over Microsoft Live Meeting.  This was the first event I’ve done of this type and scope, so I wanted to post my review of the event.

Lessons Learned: Live Meeting

This is my first time presenting over Live Meeting (LM), so I’ve definitely learned a few things. The experience itself is a little strange, and I feel disembodied not being able to see the attendees.  As a speaker, I frequently take cues from the audience: I can usually tell whether or not I need to reiterate something, or I can see that they get it and we can move on.  You’d be surprised how much you can get out of a few nodding heads!  Over LM, it’s just me staring at my screen and talking at the microphone, and I really miss the feedback.

We did some testing over LM before the event and intentionally slowed the pace down, but on Day 1 it wasn’t enough.  Day 2 was better and by Day 3 I’d say we had the pace just right.  One side effect is that I can’t cover as much material as I might with a live audience.  I also had to adjust the content I would usually share because Live Meeting has serious issues with things like gradients and animation. 

The hardest thing for me to get comfortable with was Context Switching.  I’m an Alt-Tab fanatic, my left hand is practically deformed from sitting in the Alt-Tab position.  In this case, I couldn’t use it because I took some advice from a friend of mine and did not share my entire desktop over Live Meeting.  This meant that I had to actively select the shared application every time I wanted to switch from one to another.  BTW – if you are a seasoned LM presenter, I’d love to hear how you handle this problem: post them in the comments below.

This also takes time and in the videos you will see a lot of “gray space” while I’m fumbling through the Live Meeting controls.  I found that narrating it helps: letting the attendees know what I’m doing not only helps them understand what they are seeing, it also helps fill the silence which made me feel like I wasn’t just sitting there all alone.

I’m really glad we did a test run using Live Meeting the week before with some unbiased attendees.  We also got some help from David Makogon who gave us some great tips for dealing with Live Meeting and also stepped in a couple of times to moderate when Kevin had other responsibilities.  The biggest lesson here is the Boy Scout Motto: Be Prepared.

Lessons Learned: The Event Itself

I also learned that this sort of commitment is tough.  While the presentations were “only” an hour and a half per day, the event really consumed my entire week.  I’ll admit to underestimating this when we set the event up, mostly because I had given the first 4 presentations many many times: only the last day contained new material.  The pressure I felt to deliver a quality event, however, made me spend all my free time prepping for the next day.

And it really bothered me when something went wrong, as it did nearly every day.  I try to joke about it, but nothing is more frustrating than something not working when other people are watching.  It’s especially tough when it’s something you’ve done a thousand times and for the life of you can’t figure out what’s wrong.  Lesson learned: Expect the Unexpected.

I haven’t done near as much in Silverlight as I have in WPF.  Usually that isn’t an issue, and in Blend it rarely causes a problem, but a few of the issues had to do with my lack of familiarity with Silverlight.  More specifically, I’m accustomed to doing things one way in WPF that I may have to do differently (or can’t do at all) in Silverlight.  In this case the point I was trying to illustrate was that Blend is essentially the same in both platforms, and I do think we succeeded there.

I also learned that I didn’t know as much as I thought I did.  I’ve never been afraid to say “I don’t know” during a presentation: it’s honest and fair.  But I haven’t had to say it so often as I did this week.  Some of the questions really stumped me: in fact, I said several times it was “Stump the Presenter” week.  While I wish I knew all the answers, I also appreciate the tough questions: it means the attendees were really paying attention and thinking about Blend.  What presenter could ask for more?

Day 1 – An Introduction to Blend

I watched the playback and realized I needed to go even slower: there were too many times when the speaking got ahead of the presentation, or when I could have hovered over an item longer to let the Tooltip show through.  I also learned that Gradients are a no-go.  If you watch the video they just show up as huge blocks of color.

Day 2 – Data Binding

They say every presentation has a glitch, and this one was no exception.  I ran into a problem near the end trying to bind a Grid’s DataContext to the SelectedItem of a ListBox.  I can’t tell you how many times I’ve done this, hundreds at least.  It is simple and straightforward… until today.  It just didn’t work and I tried it several times in different ways.  I finally cleared all the DataContexts and Bindings out of the details within the Grid and rebound the DataContext and finally everything worked.  I’m still not sure what the cause was, but I’m starting to think there was something left over from when I tested the Solution earlier that day.

Day 3 – Styling and Templating

I really think on this day we finally nailed the speed and delivery.  The only glitch that stands out in my mind was trying to get Smooth Scrolling to work in Silverlight.  Turns out this is one of those areas that just isn’t the same as WPF. The downside for me is that I feel I spent too much time trying to get it to work.

BTW, the solution is to go to the ItemsPanel Style and add a FluidMoveBehavior to the VirtualizingStackPanel.  Nifty trick!

Attendees: 98

Day 4 – Animations

So understanding that Gradients and things like that don’t work well over LM, I really wasn’t expecting much out of this session.  That being said, it turned out very well.  The Live Meeting video has some odd happenings between minutes 40 and 48, but the WMV file is just fine, so be sure to watch that.

Day 5 – Advanced Topics

By and far this was my favorite day.  As I said in the presentation, this stuff is just plain fun!  I think overall I was happiest with this presentation.  I’m sure some of that has to do with my growing familiarity with Live Meeting, but naturally just as I’m getting comfortable with the format we finish!  Based on the feedback, this one was as much a hit with the audience as it was with me, so  you can expect to see me presenting this one out on the road.

Conclusions

Overall, this was a great event.  I’ll admit, I was drained by the end of it, but the steady stream of thanks and nice messages from attendees tells me we did something worthwhile here.  So much so, in fact, that I think I’d like to have one session a month on different topics. 

What are your thoughts?  Your suggestions and comments will determine what shape this takes going forward, so comment below, email, or Twitter (tag #BlendORama) and let us know what you think.

Thanks again to everyone who took part, and watch out soon for the launch of www.blend-o-rama.com.






No comments    

Sending Email From This Site



Hi folks, this is just a house cleaning message.

I just wanted to let you know that apparently the email service from this server has been non-functional for quite a while and no one knew it.  It appears to have been corrected and I am receiving email submitted from this site again as of last week sometime.

On the off chance that you submitted an email to me through this site over the last couple of months and I never responded, then it means your message was never delivered.  I pride myself on responding to every message a reader sends me, so I don’t want anyone to think I’m ignoring their messages.

Just a reminder that you can also contact me on Twitter.






No comments    

Holy Cow, what a week!



This last week has been awesome, probably the best week of my professional career, and I’m just bursting to share.

Wednesday, June 30th

If you follow me on Twitter you may have seen me mention that I took and passed the .NET 3.5 Windows Forms certification exam.  While I already had an MCTS for WPF, I needed this one to qualify for the MCPD (Windows Developer).  If you check out the requirements, you’ll see only the Windows Forms exam counts.  I would go on a rant about how little sense this makes given that WPF is the future of Desktop development and WinForms is on it’s last legs, but this is a happy post so I’ll skip it this time.

I had debated about whether or not I was going to pursue MCPD, but then Microsoft sent me a voucher for a free exam, so I figured why not?  I won’t lie to you: I was surprised I passed.  It’s been 2 years and 2 versions of VS since I last developed for WinForms, and on top of that I barely had time to review.  Still, I did pretty well on the exam and so now I have another MCTS.

Thursday, July 1st

I posted last week about being awarded Expression Blend MVP: I am ecstatic, honored, and humbled.  I spent the next few days in a haze just trying to adjust, it really is a great honor.  A friend asked me at lunch the other day if I was going to slow down the crazy community schedule now.  Naturally I informed him that it would be quite the contrary!  I expect things will get even more intense and I can’t wait!

Monday, July 5th

Pathetic though it may be, I was in the office working yesterday while everyone else was out frolicking for the holiday weekend. It was near the end of the day and I was about to go home when an interesting email arrived informing me that I had been selected as an INETA Community Champion!  Looking at the past winners shows me I’m in pretty good company.  Again I am honored and humbled.

The accolades are certainly nice, everyone likes a little recognition once in a while.  I want to thank Microsoft and INETA, and specifically those who nominated me for these awards: I hope I can live up to your expectations.

However, while it may sound cliche, the truth is that being part of this community is its own reward: I wouldn’t change a thing.  Thanks everyone, and I’ll see you in the community!






1 comment    

Expression Blend MVP



Hi Folks!

I wanted to share a bit of good news with you all: I just received the official announcement that I am a 2010 Microsoft Expression Blend MVP!  You can tell by my overuse of exclamation marks!!!!

I am truly honored, there aren’t a lot of Blend MVPs and it means the world to me that I’m now on that list.  I’ve got a great year planned and some big announcements coming up, so if you are interested in Expression Blend, watch this space!

In the meantime, make sure you attend Blend-O-Rama! Only 18 days left!






2 comments    

Processing Command Line Arguments in an Offline ClickOnce Application



Several years ago when ClickOnce first emerged I thought it was a great idea.  Unfortunately at the time, I found it so difficult and tedious that I didn’t play with it for long.  My buddy Stuart was at my office recently and I was lamenting some distribution issues I was having with one of our WPF apps. 

One of our deployed apps changes frequently, and I don’t send out updates as often as I should because our users environments typical limit their install rights (not to mention many of them don’t even have IT staffs).  This means they rarely have the latest and greatest because it can be a serious ordeal to deploy the changes.  Stuart brought up ClickOnce, and the discussion quickly came to the question “what happens when the user doesn’t have administrator rights?”  Naturally, we had to put this to the test!

What I love about ClickOnce

I love how easy it is to setup and use – We spent about an hour playing with ClickOnce and I was amazed to find how far the tooling has come since I last checked it out.  The setup is pretty straight forward, so I’m not going to cover that right now.  If you specifically want me to write a post or do a video about it, respond in the comments below.

I love the control that I have – The options are pretty sophisticated: you can make an application available online only or online and offline.  When you make one available offline it creates a Start Menu option for you.  You can select Prerequisites, like the .NET Framework version, and where to download them if they aren’t present at install time. NOTE: Some caveats may apply to that, like needing administrator rights to install the Framework.

I love Automatic Updates – You can configure the application to automatically check for updates, the exact feature I needed.  You can configure when to check for updates, how often, etc.  You can even configure it NOT to check for updates.  I set mine to check for updates every time the application starts, which will prompt the user to install the new version before the software executes.

I love that users without administrator rights can install apps – This is a huge win for us.  We did a little testing and found that a user without Administrator rights can install these applications.  I presume this is because they operate in some kind of a sandbox, but I don’t actually know.  Pssst: if this is a bug, please don’t tell Microsoft – I love this feature!

Again, I was struck by how easy all this was to setup and configure, and once again I’m beating myself up for all the time I spent NOT using a supplied feature.

What I don’t love about ClickOnce

So far I have discovered two things I don’t like about ClickOnce: the first is that while I can easily create a desktop shortcut, I don’t seem to have any control over the Icon that gets displayed.  Even more strange is that the icon that is being displayed is a Blend icon of some sort.  It seems to me that this would be a pretty common requirement, so I’m surprised there isn’t a readily apparent way to assign an icon.

But far worse than that is the fact that conventional wisdom says that ClickOnce applications can’t handle command line arguments.  This was a deal breaker for me: virtually all of our desktop apps need to be executed from AS/400 sessions.  These sessions pass arguments into the applications via the command line, and losing that capability would negate most of the value of the software.  While I’m sure I’ll figure out the Icon issue, the command line arguments problem needed addressing immediately.

Command Line Arguments

So it is not entirely true that ClickOnce applications can’t handle command line arguments, but until .NET 3.5 SP1, they could only handle them as query string parameters.  This underscores the fact that ClickOnce is a heavily network dependent technology.  You may get an application that installs on your machine with a Desktop Shortcut, but this is still a network deployed application, and as such it relies on some URI scheming.  For me, this isn’t going to help much, so what I was after was the ability to pass in arguments in offline mode using a more traditional approach, like C:\> MyApp.exe arg1 arg2 arg3

I want to get to the nitty gritty of the blog post, so I won’t go into all the details, but here are a few things you need to know:

  • You have no idea where the app is actually installed.  If you do manage to find it, it will have a user-unfriendly name
  • The Shortcut name is the same as the “Product Name” field in the Publish Options Description in the ClickOnce configuration
  • The Shortcut on the Desktop has a special extension: .appref-ms
  • The easiest way to execute the application from the command line is like so: C:\> %userprofile%\Desktop\AppName.appref-ms
  • If your “Product Name” has spaces, you will need to wrap that in double quotes: C:\> “%userprofile%\Desktop\My App Name.appref-ms”

What would be perfect is if I could just append the Command Line Arguments to the end of that call, so it would look like this: C:\> “%userprofile%\Desktop\My App Name.appref-ms” arg1 arg2 arg3

Try it out, though, and you’ll quickly find that this does nothing: the standard args string array is empty.

Not A New Problem

Naturally I hit the Interwebs in search of a solution, I mean, it has to be out there, right?  I was quickly discouraged though to find hundreds of references all saying the same thing: you cannot pass command line arguments to an offline ClickOnce application.

Go ahead, go search for yourself, I’ll wait.

See what I mean?  The question has been asked a million times all with a resounding NO as the answer.  I was about to give up when I spotted something that gave me hope.  An article on MSDN entitled How to: Retrieve Query String Information in an Online ClickOnce Application has a note block with the following text:

Starting in .NET Framework 3.5 SP1, it is possible to pass command-line arguments to an offline ClickOnce application. If you want to supply arguments to the application, you can pass in parameters to the shortcut file with the .APPREF-MS extension.

That sounds like exactly what I want!  Problem is, I’ve already tried that and it doesn’t work.  And naturally, there is no related article on MSDN telling me how to do it, just that it can be done.  Finally, something to give me a little hope!

Finally, I hit the mother lode: an article by RobinDotNet explaining How to pass arguments to an offline ClickOnce application.  Robin’s blog is all about ClickOnce, and interestingly enough I found plenty of earlier posts and forum entries by Robin stating this couldn’t be done, even as late as January 2010, long after .NET 3.5 SP1 was released.  I’m not criticizing, but I am pointing out that even to those “in the know” it would appear this is a non-documented feature.

A Simple Solution

So I read through RobinDotNet’s post and it seemed like a lot of stinking work, and I try to avoid that as much as possible!  She explains a bunch of stuff I didn’t need, like how to locate the shortcut using SpecialFolders, and how to programmatically execute the application.  She even discusses how to create and pass the arguments.  Good stuff, but overkill for me.

There is one key line of code I found in her post that was exactly what I needed:

//Get the ActivationArguments from the SetupInformation property of the domain.
string[] activationData =
  AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData;

What I found is that this will return the arguments provided on the command line.  Well, sort of …

From the code above you can see that ActivationData is a string[].  At first, I assumed I would be able to simply replace the old e.Args with this value, but I found that only the first argument is available in ActivationData.  I don’t know why this is, and it doesn’t make sense, but all my testing proved this out.

To solve this, I changed the way the arguments are passed in by making them comma delimited.  It doesn’t seem to matter what delimiter you use, as long as it isn’t a space.  Then, I parse ActivationData[0] using Split.  In the code sample below, I am also checking to see if this is a ClickOnce application and checking for NULL, the default value of ActivationData if no arguments are passed.

string[] args = null;
if (ApplicationDeployment.IsNetworkDeployed)
{
    var inputArgs = AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData;
    if (inputArgs != null && inputArgs.Length > 0)
    {
        args = inputArgs[0].Split(new char[] { ‘,’ });
    }
}
else
{
    args = e.Args;
}

I assume if I wanted I could still deploy this with a traditional MSI, so doing it this way supports compatibility with a traditional command line execution. In this case, I am parsing it to build another string[] because I have existing code that works with Command Line Arguments.  This example is executing inside my WPF application’s App.xaml.cs file’s Application_Startup event handler.

Getting it to work in .NET 3.5 SP1

In order to get the code above to compile, you will need to add a reference to System.Deployment.Application, which is in System.Deployment.dll.  If you are coding against .NET 4.0, this DLL is available in the “Add Reference -> .NET” dialog.  When I tried to add the reference to an existing .NET 3.5 application, the DLL was not available in the list.  I thought this was a little strange, since the documentation claims it is supported as far back as 2.0.

I did a little digging and found the DLL location.  I was then able to Browse for the DLL and add a reference to it manually and everything seems to work:

C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Deployment.dll

The Results

The results are just what the doctor ordered: I can now call my application from the command line and pass it arguments like so: C:\> “%userprofile%\Desktop\My App Name.appref-ms” arg1,arg2,arg3

It’s not perfect, but it is easy.  The biggest change is sending all the arguments as a single string, but that is easily handled.  Now if I can just figure out that Icon …






2 comments    

Next Page »