text:
See what I see.The ramblings of Kristopher Makey.http://blogs.msdn.com/b/krimakey/atom.aspxTelligent Evolution Platform Developer Build (Build: 5.6.50428.7875)2008-01-17T22:33:00ZPlaying with Geneticshttp://blogs.msdn.com/b/krimakey/archive/2010/09/03/playing-with-genetics.aspx2010-09-03T18:31:14Z2010-09-03T18:31:14Z
Genetic Algorithms that is:

I've been toying with the ideas related to adaptive "AI".  The basic idea is:  If you could play a game where the content is adaptive, the game would seem "fresh" longer and you would have more incentive to play the game for an extended period of time.  You can use Genetic algorithms to produce "solutions" to problems automatically….can you then apply genetics algorithms to make games that adapt to the players?  (The answer is "yes", this isn't actually a new idea and I've already seen research in this area).  However I want to play with some of this stuff, because you learn best by doing things and sometimes you discover things new when you make mistakes doing things you're trying to learn.

One of the basic requirements of this is to have a "game" that we can control the results of (we want to control the environment and see what the "genetic" aspect will do within it).  So lets define a game where the goal is to "predict" the best move.  One such game we play today is "Rock/Paper/Scissors".  However I want something that can scale to include 5+ players so I've defined the game "Elements".

Elements:  Goal - Choose the element that is opposite of the most popularly chosen element.

Element Choices:

Basic Round Example

5 Players make a choice: E, A, A, F, W

Result:  The players that chose "Air" lose points, the Player that chose "Earth" gains points.

The goal:  Over a "set" of rounds, maintain a positive score.

So given this kind of game:  If we create a genetic algorithm for making choices, can we make "smart" players (players that are able to react to predictable patterns, and then adapt when changes in those patterns occur).

So I developed the game and first produced "dumb" players.  Players that that I could dynamically create, but once created would only choose a predetermined choice.

Then I started working on the Smart players:  I wanted a dynamic command set, so I needed to define the command, which then caused a bunch of refactoring because I realized I didn't just want simple commands like "Choose Fire" but I also wanted complex commands like "Choose the Opposite of the Last Popular Choice".

So Once I hooked up the command system, I started by creating "random" entities.  And then finally I included the work to do mutation, rewrite an reproduction.  As part of this work I had to write a "fitness evaluation system".  Basically you need to know when to stop mutating the genetics because you've found a solution.  For this particular program, I want something dynamic so I came up with a "generalized" fitness check.  You can be in one of 3 states:  Postiive, Negative, Neutral.  Also we don't do full evaluation and mutation every round, but rather at the end of a "set" of rounds.  Due to the nature of the game, in most cases any particular player is more likely to have a negative or neutral score rather than a Positive score…so we really only want to make "incremental" mutations if we're actually keeping neutral.

Mutations and Reproduction:

There's any number of ways to do this, I chose the "lazy" route, I have a minor and major mutation option:  Minor mutation includes adding (1 or 0) new commands to the (front or back of the) List.  Major mutation involves reducing the size of the list or adding multiple elements.

Finally we have a "third" case of mutation which is total replacement.  At the point a command set is replaced, in a genetic sense, those genes "died off".

Hooking up evaluation and mutation:

I decided that I'd track 2 phases of results and during every evaluation phase, I would look at the past results to determine how much to mutate the command set.  If the current and previous results were negative, we have a "dead end" genetic sequence, it dies (replacement).  If either the current or the previous results were negative, we introduce a major mutation.  If we have only neutral and positive results, we introduce a minor mutation and if we only have positive results we don't change (though we may reproduce if we run a reproduction phase).

And finally, if a command set gets too big, we cause a major mutation (which will reduce the size).

The final results from initial testing show that given some time, the genetic algorithm can usually stabilize on a solution if there is a stable solution available (simple solutions like "don't pick Element X or do pick Element X".  If there are multiple "dynamic" entities involved, it's possible that they may extend the length of time or make the system unable to stabilize.

My test app is a bit ugly, but here's a screen shot of what it looks like:

Possible Future investigation:  Can I get a smart player to predict complex patterns (like all of the "dumb" players play the sequence: Earth, Air, Fire, Water.

I hope you enjoyed my story about delving into genetic algorithms, thanks for reading.

-Kris-

Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxThe subtle scent of change still wafting in the air.http://blogs.msdn.com/b/krimakey/archive/2010/05/08/the-subtle-scent-of-change-still-wafting-in-the-air.aspx2010-05-08T09:11:00Z2010-05-08T09:11:00Z
So It's been nearly four years at Microsoft here for me.  I've had a great tenure working on VSTO, but as time moves and things change, so must we.  About a month ago a very interesting opportunity arose that I could not pass up, it has caused me to leave the VSTO team to a different team within the greater Visual Studio umbrella.  My job has changed significantly (I no longer have direct impact on the quality of VSTO) and I'm now under a different title.

But what does it mean?  Most likely for for those who read my blog to hear about VSTO deployment for at least a year or two, not much, VSTO is still a very interesting technology to me, and I maintain contacts with members of that team, so as I have time I will still write about interesting VSTO related information.  I may actually have an easier time blogging because I won't have to try and remember what is "new and secret" and should not be announced yet.

On the other hand, I now also have access to a whole new area of information, and I may occasionally post interesting stuff about what I'm doing there.  So what am I doing now?  I'm not testing products as my main focus today, rather I'm building stuff for those who do test products.  I'm working as part of an internal group that develops and supports the base test automation tools we use for driving Visual Studio.  So while I am no longer a "Tester" I lost the "t" in my title in the transition, in many ways I'm still very much in the test field.  As for what I will write about?  Most likely I'll start talking about interesting experiments, interesting automation related bugs and stuff about the fundamentals of smarter automation design.
Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxLooking to the future, anticipating the next version of VSTO.http://blogs.msdn.com/b/krimakey/archive/2010/01/22/looking-to-the-future-anticipating-the-next-version-of-vsto.aspx2010-01-22T17:00:00Z2010-01-22T17:00:00Z
As we start to see that hazy object that is the "next version" of VSTO coalesce into an actual shippable project, my time and topics of interest have had a chance to increase again.  One of the things current on my mind is "servicing", specifically, what are the "predictive" measures you should take to as reasonably as possible "future-proof" your solution.

Before I get into any interesting code projects, I'm going to share some thoughts about some of the interesting tidbits that have come across my plate:

This section references statements made in the following post:  http://blogs.msdn.com/krimakey/archive/2008/04/18/click-once-forced-updates-in-vsto-ii-a-fuller-solution.aspx

In a previous post I explored what it would take to duplicate some of the functionality that the ClickOnce deployment API provides.  One of the things that was far from my mind at that point was "what happens in the next version".  Well, one of the really big changes that has occurred is the location of VSTOInstaller.exe.  If you were to write a VSTO 3.0 solution using my example today, and your customer were to install the next version of VSTO Runtime, there is a good chance your background updates would be broken.   But all is not lost!

One option is to simply extend the solution to also check for the newest version of VSTOInstaller.  This isn't ideal since you really don't want to update your solution every time a new version of VSTO is released to the world.  Unfortunately I can't provide you with a bulletproof option to handle the next version of VSTO.  What I can do though, is provide enough information that you are more likely to be successful in predicting what the next version is going to look like.

If you install a Beta version of the Visual Studio 2010 Tools for Office Runtime you may note the following installation key:

(x86)

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VSTO Runtime Setup\v4]
"Install"=dword:00000001
"InstallerPath"="C:\\Program Files\\Common Files\\Microsoft Shared\\VSTO\\10.0\\VSTOInstaller.exe"

(x64)

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VSTO Runtime Setup\v4]
"Install"=dword:00000001
"InstallerPath"="C:\\Program Files\\Common Files\\Microsoft Shared\\VSTO\\10.0\\VSTOInstaller.exe"

This key is the key to figuring out which (copy) of VSTOInstaller you should be using to install/update your solution.

[DISCLAIMER] Anything in the next section is based on a "best guess" approach based on observation only.  I make no guarantees to the future validity of the method against future versions of the VSTO Runtime.

It's very likely the next version of the VSTO runtime is likely to follow as similar pattern.  Based on this assumption, you should be able to write a fairly resilient bit of code that might reduce the need to make updates to your solution based on changes in the VSTO runtime installation.

The safest method would be to grab all of the sub keys under [STO Runtime Setup] and iterate through looking for sub keys that contain an InstallerPath value.  Take the highest version you find, and you _probably_ will be safe using that path to invoke VSTOInstaller.

[/DISCLAIMER]

The reason you would want to do this is simple:  VSTO 4.0 was designed to replace the functionality provided by VSTO 3.0.  If you install VSTO 4.0, and then attempt to install VSTO 3.0, VSTO 3.0 will detect that it does not need to be installed.  This means you can no longer make the assumption that your customization will be running only against the VSTO 3.0 runtime.  Additionally, even if your customer installed VSTO 3.0 and then installed VSTO 4.0, installing with the older VSTOInstaller may produce unexpected effects (you may incur some extra processing on the first run (post update) of your customization as some new meta-data that VSTO needs won't be written).

[Correction 2/3/2010]  After a bit of investigation, it turns out I was incorrect in stating VSTO 4.0 prevents VSTO 3.0 from being installed.  You can install VSTO 3.0 on a machine with VSTO 4.0.  This doesn't change the basic fact that once VSTO 4.0 ships, you should "plan" for your customizations to be installed on VSTO 4.0 only machines also.  While the Bootstrapper will always cover installation of prerequisites (such as VSTO 3.0) there isn't a guarantee that it will get run on machines that have VSTO 4.0 on them.  VSTO 4.0 does install the mime handler that makes .vsto files "installable", depending on the situation, it's reasonable for a customer to skip running setup.exe program and go right to installation of the customization.
Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxWhere did my permission set controls go?http://blogs.msdn.com/b/krimakey/archive/2009/05/20/where-did-my-permission-set-controls-go.aspx2009-05-20T15:00:00Z2009-05-20T15:00:00Z
I'm going to diverge a bit off the VSTO path and talk about a more generic ClickOnce story. If you have used ClickOnce in VS 2008 or VS 2005 you may be somewhat familiar with partial trust scenarios and the idea of permission sets. If you do not care about partial trust but instead live in the world of using full-trust (such as VSTO requires) then you can skip this post as it may be irrelevant to you.

The Setup

If you haven't heard yet, we are in the midst of shipping the Beta for VS 2010. You can read more about it here:

http://blogs.msdn.com/somasegar/archive/2009/05/18/visual-studio-2010-and-net-fx-4-beta-1-ships.aspx

There are many exciting new features and changes occurring in this cycle. As a product of some of these changes I've been seeing a lot of questions about some of the changes being made. I'd like to answer at least one of them now.

The Question

"I went to customize my zone permissions and noticed that the control that lists the zone permissions is missing! Is this a bug or is this control moved somewhere else? I need to know how to customized the internet zone so my application will work. How do I do this in VS 2010?"

Here is a screenshot of said control in VS 2008 (on Vista):

Here is a screenshot from VS2010 Beta 1 (on Server 2008):

The Short Answer

This is not a bug, we intentionally removed this control within VS 2010.

The Long Answer

So the question itself is just one of the reasons that this control was removed. As it turns out there is an implied functionality/design in this control that confuses developers about how the security model works. Conceptually it is easy to look at this control and assume that you can set a "zone" and then customize the permissions that should work within that zone. But this is not the case and this is where the confusion comes into play.

What this control essentially does is create a Custom Permission Set and compare it to the permission set of a "well known" zone. If you change the setting element to anything other than Zone Default, you've defined a "custom" permission set and that is what your application will request. In VS 2008 and VS 2010, this same functionality can be achieved by adding the individual permissions to the <TrustInfo> element in the app.manifest file. In VS 2010, this will be the only way to define a "custom" permission set. You can find an older MSDN article on how to do this here: http://msdn.microsoft.com/en-us/library/6ad1fshk(VS.80).aspx.

Our belief is that most customers that use this control are under the impression they get some benefit from using the custom sets, but in most cases they are not getting the benefit they believe they are getting. The misconception comes about because the impact of changing things in this control are non-obvious. So let's break this down into 3 scenarios and describe what happens, why, and alternatives that get the same effect.

Target Internet Zone: Do not change anything.

If your application really does need only the internet permission set, it will work without a trust prompt as long as you run it from the following zones: Internet, Local Intranet, My Computer. You do not see a trust prompt (assuming your application is signed with a "known" certificate that chains to a Trusted Root Authority) because you have provided "evidence" (the permissions you requested,where it is run from, and a "known" certificate signature) saying your application will only execute within the confines of the functionality allowed for applications that execute within that zone. If your application needs any permissions outside of this zone, it will fail with a "trust/security" error.

In VS 2010, we support this scenario with the current UI, the "Zone your application will be install from:" control is what determines the permissions set.

Target Internet Zone: Remove a Permission.

You are no longer targeting the "Internet" Permission set but rather a custom set. If your application is published on the internet, local intranet, or my computer zones, it will function without a trust prompt exactly like targeting the internet zone. There is a caveat here, but I will come back to it (See Caveat: Least Permissions).

In VS2010, there are 2 options to achieve this: You could have simply targeted the internet zone or you can define the custom set your application needs in the app.manifest file manually. Our general recommendation is to target the well-known-zone that your application runs from rather than defining custom permission sets.

Target Internet Zone: Add a Permission.

In this scenario, your customers will get the ClickOnce trust prompt. We believe users of the permission set control fall into this bucket. The reality of the security model is that at this point once you have incurred a trust prompt of any kind you might as well be targeting "full trust" since your end user will not see a difference.

In VS2010, if you cannot run under the permission set of the zone you are targeting, we recommend that you switch your application to requesting full trust. Functionally to the end user, this is exactly the same as if you had targeted a custom set that exceeds the permissions of the zone your application is installed or run from. You can manually configure the custom set using the app.manifest xml file within the project.

Caveat: Least Permissions

Our team is aware there is a segment of our developer customers that prefers to target the "least" number of permissions required in which to run their application. While we do understand this UI made it much easier to do this, we believe that this segment is familiar enough with permission sets that they are capable of achieving the appropriate settings using the app.manifest xml file. Please continue reading if you would like to understand the other justifications for why this UI was removed.

How we came to this final decision (or rather "other aspects involved"):

Generally we don't remove UI or features without good reasons. In this case, we discussed at length with the Security Team about this specific piece of UI. They have indicated to us that they believe the general focus of their customers should be to move away from "custom" permission sets and more to targeting only the well-known permission sets or fully trust.

Beyond the general "this is the direction we want to take this feature," VS 2010 includes some changes that made removing this UI desirable from a technical perspective. If you have not noticed yet, VS 2010 allows you to target/build and debug solutions against both CLR 2.0 (.NET version 2.0, 3.0 and 3.5) and CLR 4.0 (.NET version 4.0). Visual Studio itself runs against CLR 4.0. In previous cycles, the assumption was that VS would only run against the CLR version it targets, but that assumption is no longer true. As a result, many elements of VS have had to change because VS cannot always rely on the CLR it is running against to provide the correct information for the project (if it targets a different CLR). Our permission set control falls under the bucket of things that functioned on this basic assumption. When we looked at what the cost of changing the design was and how it would impact the overall user story, we determined that it was better for our customers that we removed the UI and focused on improving the other aspects of the product. We feel that the loss of improved functionality (how easy it is to setup custom permissions) did not outweigh the gains we could apply elsewhere.

Thank You for reading.

Kris
Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxEnterprise Level Deployment of VSTO Solutions: Deployment Designhttp://blogs.msdn.com/b/krimakey/archive/2009/04/08/enterprise-level-deployment-of-vsto-solutions-deployment-design.aspx2009-04-08T16:00:00Z2009-04-08T16:00:00Z
It's been a while, I'm not really interested in going to the details of why at the moment, lets dig right into the topic.

Generally I focus on more of the technical aspects of what you can do without really talking much about some of the other considerations that should go into make your deployment design decisions.  This post is going to be a little different.  I won't have any nuggets of deployment code or advice on how to achieve specific deployment actions, rather I'm going to cover some of the details that you might want to include into your evaluation before you decide "how" you will deploy your solution.  Essentially this post will be about how to go about designing your deployment (what factors you may have to consider and how they will impact your deployment implementation).

First, some terminology:  I have been known to throw around the following terms and haven't really defined them in any consistent way, so I'm going do so now.

Customer level solution (customer solutions, customer deployments):  Solutions in this class of products that are released to the general public.  Generally as far as deployment goes, Customer solutions are deployed by some kind of opt-in methodology.  Customer solutions have constraints unique to not always having control of the system in which the solution is installed into.

Small Business level solution (smb solutions, smb  deployments) :  Solutions in this class of products that target user bases encompassing 10 - 200 clients.  Deployment and installation state may be controlled by a central organization or individual.  SMB solutions generally have some moderate to low-level infrastructure such as an intranet and UNC servers.

Enterprise level solution (enterprise solutions, enterprise deployments):  Solutions in this class of products will target a set user base of 200-100,000 clients.  Heavy infrastructure is available and both deployment and installation state are controlled by a central organization (IT department) with dedicated resources for management and support.  Constraints on this level are often defined by such issues as infrastructure constraints, machine state preservation and maintenance impact.

I'm going to focus on the enterprise solutions and some of the specific details that an IT department may impose on deployment configuration and maintenance decisions.  Enterprise solutions should have 4 specific phases of a solution's lifetime that should be considered before making deployment design decisions.  These phases are initial rollout, solution maintenance (updating), emergency response and uninstall.

Initial Rollout:

When considering Initial Rollout, there are a number of factors that should be considered.  One of which is the bandwidth-to-client metric (versus solution size) and the window of opportunity for rollout.  Simply put, how long is it going to take to for every client to download the solution the first time.  Here are some numbers and math.

First, assumptions and caveats:

All numbers here are idealized, actual networking is never as nice as this idealized form.  The assumption for the following graphs is that you are hosting all of the data at 1 machine and the network bandwidth is the idealized out-bandwidth of the publish server.  VSTO solutions may range in size from 100KB to 50MB or more depending on any number of factors involved.  As a reasonable medium point I'm choosing 5MB with the assumption that most solutions will sit somewhere within this upper bound.

Next, the formula:

Rollout Time = Amount of Data / Speed of Data

Rollout Time (minutes)  = ([number of installs] x [Installation Size]) / ([Bandwidth] x 0.125  x 60)

Bandwidth is generally stated in megabits per second (mb/s), but we need to calculated based on megabytes (MB) and minutes thus the multiplication by 1/8 and by 60.

Finally, Data:

Solution only installation (no prerequisites)

100 megabit network

<colgroup><col style="width: 99pt; mso-width-source: userset; mso-width-alt: 4827" width="132" /><col style="width: 145pt; mso-width-source: userset; mso-width-alt: 7058" width="193" /><col style="width: 118pt; mso-width-source: userset; mso-width-alt: 5741" width="157" /><col style="width: 126pt; mso-width-source: userset; mso-width-alt: 6144" width="168" /></colgroup>

Client Machines

Network Bandwidth (mb/s)

Installation Size (MB)

Approximate Rollout Time (minutes)

 200	 100	 5	 2

 500	 100	 5	 4

 1000	 100	 5	 7

 5000	 100	 5	 34

 10000	 100	 5	 67

1 gigabit network

<colgroup><col style="width: 99pt; mso-width-source: userset; mso-width-alt: 4827" width="132" /><col style="width: 145pt; mso-width-source: userset; mso-width-alt: 7058" width="193" /><col style="width: 118pt; mso-width-source: userset; mso-width-alt: 5741" width="157" /><col style="width: 126pt; mso-width-source: userset; mso-width-alt: 6144" width="168" /></colgroup>

Client Machines

Network Bandwidth (mb/s)

Installation Size (MB)

Approximate Rollout Time (minutes)

 5000	 1000	 5	 4

 10000	 1000	 5	 7

 50000	 1000	 5	 34

 100000	 1000	 5	 67

However these are the "best case" roll out scenarios give that you may not have all of the prerequisites.  Consider that the following are common prerequisites that you may have to also install:

Office 2007 PIA redist:  6.82 Mb

VSTOR 3.0 SP1 redist: 3.27 Mb

Solution, Runtime and PIAs

100 megabit network

<colgroup><col style="width: 99pt; mso-width-source: userset; mso-width-alt: 4827" width="132" /><col style="width: 145pt; mso-width-source: userset; mso-width-alt: 7058" width="193" /><col style="width: 118pt; mso-width-source: userset; mso-width-alt: 5741" width="157" /><col style="width: 126pt; mso-width-source: userset; mso-width-alt: 6144" width="168" /></colgroup>

Client Machines

Network Bandwidth (mb/s)

Installation Size (MB)

Approximate Rollout Time (minutes)

 200	 100	 15	 4

 500	 100	 15	 10

 1000	 100	 15	 20

 5000	 100	 15	 100

 10000	 100	 15	 200

1 gigabit network

<colgroup><col style="width: 99pt; mso-width-source: userset; mso-width-alt: 4827" width="132" /><col style="width: 145pt; mso-width-source: userset; mso-width-alt: 7058" width="193" /><col style="width: 118pt; mso-width-source: userset; mso-width-alt: 5741" width="157" /><col style="width: 126pt; mso-width-source: userset; mso-width-alt: 6144" width="168" /></colgroup>

Client Machines

Network Bandwidth (mb/s)

Installation Size (MB)

Approximate Rollout Time (minutes)

 5000	 1000	 15	 10

 10000	 1000	 15	 20

 50000	 1000	 15	 100

 100000	 1000	 15	 200

What we can draw from these numbers? Nothing specific, these values are based on idealized networking and don't take into consideration a lot of factors that may have a greater impact on your deployment design.  What they do give us though is a basic framework to use as a basis for further discussion.

Specifically, as your organization is bigger or has less infrastructure, there may be value in breaking up the initial roll out into waves or separate deployment sites.  If you have an organization of 10k or more employees, there is a pretty high chance you can use geographic based division to save a lot of pain and allow you to handle the initial rollout in a controlled manner.

Let's move on and talk about some of the other factors that should influence the rollout.  One things that comes to mind in particular is the prerequisites.  By default VSTO publishes a Setup.exe file that is meant to be used to pull prerequisites down to client machines that don't have them installed.  If the prerequisites are not present you may want to roll them out first and possibly even rollout a "dummy" solution that allows you to track the number of successful prerequisite setups.  When you then push out the "real" solution, you only need to worry about the solution itself and not the problems that would be caused by failures in the prerequisites.

Work habits is another factor you have to consider for initial rollout.  You may consider pre-registration of an Add-in as possible Rollout mechanism, but if you do you should be aware of the impact this specific factor may incur.  Specifically if your clients all connect at the same time or if it is staggered over a period of time there may be a much higher bandwidth cost.  An example graph below compares relative network usage versus Initial connection of clients (the data is made up but it demonstrates the basic idea).

In this example:

In this example we have a case where the bandwidth usage of installing the solution on all clients exceeds the capacity of the network infrastructure.  In both "scenarios"  the bandwidth speed and data served is the same, but the final results (and subsequent customer impact)  differ because of usage patterns.

Scenario A is where a natural Bell curve occurs between 8:00 and 8:30.  Initially only a couple of clients start the installation process at 8:00, at 8:05 more connect, at 8:10 the highest number of clients are connecting (about 50% of the total) and then as time progress fewer clients are connecting.

Scenario B is where All clients connect at the same moment (at 8:00)

The key take-away from this example should be the effect that spreading out the install step can have.  In both cases the network usage peaking is causing a delay, but in one case the delay is at least 15 minutes in length for some clients.  If you're in a situation where your clients have common peak times (specifically around startup) you will want to reduce the amount of potential impact your rollout will have.

Now that we've established some of the factors, lets talk about some specific design choices you might make based on how these factors impact your specific deployment story. If you're in an enterprise that is just beginning to rollout .NET 3.5 (or 3.5 SP1) and the VSTO prerequisites, you probably specifically want to roll out the prerequisites ahead of time to ensure that when you finally do roll out your specific solution code there are fewer kinks to work out in both steps.  Using a "test" add-in (specifically on the Application you plan to customize) may help flush out any issues related to initial prerequisite installations.

There are 2 basic paths you might take to propagate the solution out to your clients.

The ClickOnce method may be used by forcibly installing the prerequisites (which are machine level and require administrative access) and then pushing a ClickOnce registration (of and Add-in) to all user accounts  (for documents, simply making the documents available is the same as registering the add-in).  The first time your solution consumers login on a client machine and start the customized application (or open a customized document) Clickonce will pull down the solution (from the location you specific in the registration) and store in the cache on that machine.  Depending on your user statistics this can result in a installation really bad peaks.  If you find that you might have this kind of peaking behavior there are some specific options you might employ to reduce the rollout impact.  One option is to stagger the registration step.  By introducing the registration in waves you can reduce the "height" of the peaks to something that doesn't significantly impact your user base.  Another option with particularly large rollouts might be to host the solution on different servers.  Doing this breaks up the load but keep in Mind VSTO ClickOnce doesn't really have a good mechanism to allow you to load balance these solution.  Once an installation points to a specific deployment (publish) server, it will always point to that server.  An uninstall and reinstall (on each client) would be necessary to migrate client installations.

The vstolocal method would be the alternative.  Similar to (or possibly using) MSI installations you would copy the customization contents to a specific location on the machine and then push down a registration with the |vstolocal tag.  Using this method would allow you to be more specific about "when" the solution is installed.  With the vstolocal method, the "hard" work is all in getting the client computer properly configured once you've achieved that, the subsequent rollout should just be a matter of "when".

On trusting the solution:

In both cases, you may want to use certificate trust since it allows you to trust the solution for all users on that machine.  If you do not use a trusted publisher certificate approach, each of your users will incur a trust prompt on the initial execution of the solution on each client (example: Joe would see it on Client A and Client B but Bill who only uses Client B for the customized app only sees the prompt on Client B (though both will see it on Client B)).

Solution Maintenance:

Depending on the nature of your solution you may be planning regular updates, infrequent updates or no updates at all.  When considering the design of your deployment story, you should consider how updating is going to impact your usage scenarios.

When using "vstolocal", updates are entirely based on a push model where you have to push a new version of the manifests and  executable files to each client machine.  Every update in this model will pretty much have the same impact as incurring a solution only initial rollout.

If you use ClickOnce, there are several options for managing updating.  ClickOnce itself allows for determining the frequency of update checks but there are scenarios with this that you may want to consider.  Generally the cost of checking shouldn't be significant issue, when a check is made, only the deployment manifest is downloaded to the client.  Most manifests should be in the 6k - 10k size which means even with a 100 mb/s connection, a 7 second delay would only occur if around 9000 clients attempted to check at the same moment.  It's not really the update check that is likely to cause problems, its those times when an update actually exists to be downloaded (the amount of data and subsequently bandwidth is a magnitude larger).  The same basic network metrics and usage patterns in the initial rollout may have similar impacts on your usage experience so it's a factor you should consider in your design.

One possible method of reducing spiking on "update days" is to stagger when the update checks occur.  This prevents spiking but it also delays when all clients will have the update and can be problematic if older clients can cause problems with newer clients when they share data sources (ex:  your solution access a Database and an update includes a Database Schema change that causes issues when older clients attempt to manipulate data).

Another potential flaw with staggering updates is relating to a natural tendency for "bunching".  This is best explained as an example: let us just assume for the sake of this example, profiling indicated that having every client download updates on the same day would over-tax the resources available.  So to mitigate the problem the initial rollout occurred over the course of a week (5 days) and the each client was set to check for updates every 7 days.  So each day of the week, 20% of your clients check for updates first thing in the morning (an assumption that every client opens the application at least 1 time every  (work)day is made here).

The problem occurs whenever vacations or Holidays occur.  Each day that users are not logged into client machines the scheduled checks (for the missed day) to check on the next day.  What this ends up doing is causing bunching up (most likely around the middle of the week).  Here is little example graphic to demonstrate what this might look like:

Initially in the first week all clients are checking in a consistent pattern and no spike in usage occurs.  However on the second week, Monday and Friday are both Holidays.  On Tuesday 40% of the clients are checking for updates since the 20% from Monday were unable to check on their "designated" day.  Additionally on the third week, due to Monday and the previous Friday being holidays, now 60% of the users are checking for updates on Tuesday (and 0% are checking on Friday and Monday).

One mitigation for this is to delay checking for updates by a larger chunk of time (3 weeks for example) and providing a bigger buffer between each "wave" of updates.  There are other methods you might work around this behavior (rather than using automatic checking, using the ClickOnce API and controlling when update checks occur similar to an earlier blog post I had about creating a "check for updates" button).

Emergency Response:

While no one wants to ship a bug or have cases when a solution has been compromised by a virus or hacker, it is important to be aware of what you can do to mitigate the impact when these things occur.  By having a clearly designed response ahead of time, it may be possible to reduce the severity of the impact on your business operations by reducing the response time and window of opportunity for damage.

If you use vstolocal there are 2 specific methods you can take to mitigate a bad customization.  The first option is to disable the solution.  There are 2 methods:  force an uninstall on user startup or an alternative is to simply push the solution certificate into the Untrusted Certificates Store.  One of the subtle behaviors of vstolocal is that trust of the solution is always evaluated at startup.  This works from an administrative (machine) level and doesn't require pushing out any action to specific users.

The other option is to for a registry disable of the customization (set the load behavior to 2).  This works to shut down the solution from automatically starting up and causing further harm but it doesn't prevent users from re-enabling the solution via the com-add-ins dialog in office.  Additionally, disabling the add-in in this method requires pushing the change to every user on every client.

The second method for vstolocal solutions you might take is to simply force an uninstall of the solution, this prevents the solution from being re-enabled by the user but again incurs a user level action.  This depends on good authoring of your deployment mechanism (I'm assuming this to be an MSI).

If you deployed using ClickOnce, you can't use the Untrusted Certificates store to block/disable existing installs (of the bad update) since security for ClickOnce solutions is only evaluated when we copy the solution contents into the cache.  However you can push out commands to VSTOInstaller to force an install or alter the user level registry to disable the solution (same as described for vstolocal).

If your solution checks for updates on every run though, you can push out a rollback by simply replacing the "bad" version with the version published previous to it.  Any users who had not updates will not see any effect (they will not have pulled down the "bad" update) and any users who installed the bad version will be rolled back to a working version.

The last option may be to write some code in the initialization of the customization to check for a "halt" registry key in the hklm registry hive.  This allows you to push out a single key to every client machine disabling the solution for every user on that machine...but it does require designing this functionality into the solution immediately.

Uninstall:

Preparing for the end of life for your solution is part of proper deployment design.  When you are looking at Enterprise level solutions, you need to determine how responsive you want the uninstall process to be.  If you use vstolocal deployment, the work for uninstall is achieved by removing the solution files and then further forcing an deletion of the registration of the add-in for each and every user.

With ClickOnce Installation, there isn't a specific mechanism built-in for pushing an uninstall out to every user, however VSTOInstaller does support a command line only uninstall.  The command would be something of the format:

%commonprogramfiles%\microsoft shared\VSTO\9.0\VSTOInstaller.exe /Silent /U "{publishlocation...Addin.vsto}"

You probably want to use the silent flag specifically to prevent your users from blocking the uninstall process.

Similar to handling an "emergency response" situation, you may simply want to bake a registry check to cause the solution to uninstall itself.  The problem with this method though is the registry key is left around (assuming it is in the hklm registry hive).

Another possible method for handling the final uninstall:  publish an update that calls VSTOInstaller to uninstall at add-in shutdown.  This this should work because fusion copies the solution executables into a shadow cache during execution (although you may want to ensure no references to (data) files exist at the moment (in execution) you call uninstall).

Thanks for Reading (and being patient enough to stay with me over a long break)

Kris
Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxVS 2008 SP1 and VSTO, why you should be seriously considering installation.http://blogs.msdn.com/b/krimakey/archive/2008/10/03/vs-2008-sp1-and-vsto-why-you-should-be-seriously-considering-installation.aspx2008-10-03T19:15:29Z2008-10-03T19:15:29Z
I'm not going to go into detail about everything in the VS 2008 SP1 package, but what I would like to point out some key deployment features that were added and why you would want to consider installing even if you have a large user base using a base VS 2008 customization.  In this discussion I will refer to things as being RTM (meaning VS 2008 and VSTOR 3.0 Pre SP1) and SP1.

Adding VSTOR 3.0 and .NET 3.5 SP1 Patch Redistributable's:

We've added some additional functionality to the base VSTOR 3.0 Runtime that you can actually take advantage with RTM Applications.  As such, if you install the SP1 patch on your development machine, you should be able to include the SP1 patches for both .NET 3.5 and VSTO Runtime 3.0. Adding these patches to the bootstrapper will not upgrade your existing customers but any new customers you have will be able to take advantage of the new functionality without any changes on your end.  Any previously existing customers could re-run the Setup.exe file to receive the upgraded functionality.

One thing to keep in mind for these changes I'm describing is that the customization itself is not being upgraded, just the runtime it runs on is.  If you have to recompile your customization against the SP1 Runtime to take advantage of a new feature, your customization will not work for your customers who don't install the SP1 patches.

Additional Redistributable Package, the Office 2007 PIAS:

We've authored an Office 2007 PIA installer for general consumption.  In general, Office 2007 will install the PIAs by default, specifically it will install them if you have a .NET Framework installed on your machine at the time you install Office.  The problem with this is that it turns out a lot of you out there still use XP and clean installs of XP do not come with .NET installed.  As such we've included a PIA redist package that you should be able to include.  This package looks for a previous instance of an Office PIA existing on the machine before it does anything that might require elevation.

Event Logging:

Specifically any deployment errors that occur on your client machines will by default log the error directly into the windows event log.  The functionality here isn't particularly rich, we've basically taken the same information that we display in the "alert dialog" that turning off VSTO_SUPPRESSDISPLAYALERTS enables.  The key here is that you should now be able to excavate what the actual cause of error was even if the issue is resolved before you get a chance to investigate.

Update Cancellation:

In RTM the timeframe in which an update can be "successfully" canceled is very small.  If the user cancels the updated outside of that particular window the VSTO Runtime sees it as an error case and blocks further execution of the customization.  Based on your feedback, we changed this behavior in SP1 such that you should now be able to cancel an update and continue running the previously installed version.   There are still cases where an error will occur (an example would be if you are installing the customization for the first time) but in general this should be a lot closer to what you guys told us you wanted.

Thank You for Reading.

Kris.
Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxA day at the movies.http://blogs.msdn.com/b/krimakey/archive/2008/09/02/a-day-at-the-movies.aspx2008-09-02T21:00:40Z2008-09-02T21:00:40Z
It's been quiet.  I've been super busy with a lot of things.  Some things I can talk about and mostly things I can't.  What I can talk about:  I went to PAX this last weekend.  PAX (also known as Penny Arcade Expo) is a big convention for us "gaming" enthusiasts.  When I say "gaming" I mean computer games, board games and of course the run of the old school pen and paper role-playing games (ala Dungeons and Dragons).

PAX is one of those things that helps me recharge once a year, get a bit of a look into what is coming down the pipeline and occasionally just see what other interesting things are going on in the entertainment industries of my choice.  At PAX I tend to focus more on seeing things rather than playing (I usually try a couple of game) there were some very interesting videos of the new stuff coming up and some very compelling demos also.  One thing in particular leapt out at me:  Popfly might be a very inspiring way of easing some of those non-programmer folks into understanding how things are put together.  I completely recommend taking a moment to look at this, especially if you have children you want to get interesting into the whole software industry.  At one point a 12 year old (I think he was 12, may have been younger) was demonstrating his game "apple eater".  Pretty much a Pac-man clone that he put together.

So enough with the games, I know most of you are probably more interested in VSTO.  So here is something related to VSTO.   I have to admit that for me this is kind of an ego boost.  I don't generally put together videos since I feel like I don't have anything worth saving to a camera but when given the opportunity to create one focused on some of the VS 2008 Sp1 features, I couldn't pass it up.  It's pretty short, but there you go.

Thanks for Reading

Kris
Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxIn the Before of the Beginning: Custom Prerequisites for VSTO ClickOnce (part II).http://blogs.msdn.com/b/krimakey/archive/2008/07/30/in-the-before-of-the-beginning-custom-prerequisites-for-vsto-clickonce-part-ii.aspx2008-07-30T17:00:17Z2008-07-30T17:00:17Z
In my last post I talked about the first steps to building my Customer Prerequisite.  In it, I built an MSI that would display a message box during the install phase. Here is what Setup1looks like when you run it:

It's nothing too ingenious but it gets the job done.

So...here we are with an MSI but I want to be able to somehow integrate this into the setup.exe file that gets created for my VSTO customization.  The first step to doing this is to author some bootstrapper manifests.  Specifically a package.xml file and a product.xml (for each supported language) needs to be created.  Thankfully the is a powertool that will help you do this.

David Guyer has produced an exellent simple to use UI Tool to help with creating the bootstrapper manifest.  You can get the VS 2008 version of the tool here: http://www.codeplex.com/bmg/Release/ProjectReleases.aspx?ReleaseId=10652 .  This tool is currently listed as being in Beta and I still had to do some manual work to get everything lined up.  Here are the steps I took:

Open BMG for VS 2008 (installed it should show up under the Visual Studio 2008 folder).

Create a new "Package Manifest" Project.

Right Click on the left pane and select [Add Install File]

Select the MSI file via the [Browse] button

Set the Display Name (this will show up in VS)

You can include a text License Agreement file (this will be displayed before the MSI is ran).

Make sure to include a "Success" Exit Code on the Exit Codes tab.

By Default the Hashing method is used under the Security, I did not change this, but you should be aware of it since it means that any changes to MSI after creating the Package Manifests may cause errors.

Click Build.

As you can see, I get this warning about the Product Code.  I talked to David Guyer about this and here was his comment:

I think once you enter a display name, I try to autogenerate a product code.  Just to help clarify, the bootstrapper's product code is not the same as the MSI's product code… so you don't need to enter the MSI's product code…  a bootstrapper product code is something typically like "Microsoft.VisualBasic.Powertoys.1.0"

You can manually add this to the files.  If you go to the build output folder you will see all of the files

So the Product.xml file should look something like this:

<?xml version="1.0" encoding="utf-8"?> <Product ProductCode="" xmlns="http://schemas.microsoft.com/developer/2004/01/bootstrapper"> <PackageFiles CopyAllPackageFiles="false"> <PackageFile Name="setup1.msi" Hash="DD8BF9497F8447128E4F6C72C8D30D8E2871E9BE" /> </PackageFiles> <Commands Reboot="Defer"> <Command PackageFile="setup1.msi"> <ExitCodes> <ExitCode Value="0" Result="Success" /> <DefaultExitCode Result="Fail" String="Anunexpectedexitcodewasr" FormatMessageFromSystem="true" /> </ExitCodes> </Command> </Commands> </Product>

The last steps are to add a Product code to this file and then copy the files in the Build Output folder to the prerequisites directory.

The path shown here would be: C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages\My Custom Prerequisite\

Once you've done that you should be able to include your custom prerequisite step as if it was just another standard part of your setup.

I'm going to end with that, it should be enough to get you started on deploying even more powerful and interesting VSTO solutions.

Thank You for reading.

Kris
Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxIn the Before of the Beginning: Custom Prerequisites for VSTO ClickOnce (part I).http://blogs.msdn.com/b/krimakey/archive/2008/07/18/in-the-before-of-the-beginning-custom-prerequisites-for-vsto-clickonce-part-i.aspx2008-07-18T23:06:53Z2008-07-18T23:06:53Z
In January I talked about using Custom Prerequisites to add a little more specialization to the VSTO ClickOnce experience.  I didn't go too much in depth into this and I've since seen a few comments crop up about them in some of the VSTO community spaces I watch.  So I'm going to go through a basic walk through of how you might go about doing this.

So first you need to create your custom prerequisite installer.  I believe any executable can be used but for this post I'm going to cover a method where instead of using an "executable" I'm going to build an MSI (Windows Installer).  I might come back to the executable option in another post, but with that lets move on.

Creating a Custom Prerequisite MSI that does something:

For my first try I actually created a custom .NET DLL that did my prerequisite step (in which I just to display an Message Box to ensure it was working).  To do this I created a C# class library project and added a new "Installer Class" to the solution.   Here's what the code for that class looks like:

namespace CustomAction1 { [RunInstaller(true)] public partial class Installer1 : Installer { public Installer1() { InitializeComponent(); } public override void Install(IDictionary stateSaver) { base.Install(stateSaver); string messageString = "Message Strings: \n"; messageString = messageString + "Message:"; messageString = messageString + this.Context.Parameters["Message"]; messageString = messageString + "\n" + "OtherMessage:"; messageString = messageString + this.Context.Parameters["OtherMessage"]; System.Windows.Forms.MessageBox.Show(messageString); } } }

I built this action and then created a "standard" Windows Installer Project.  I ripped out all of the steps from the MSI project and then added Custom action.  To do this, I added the "Primary Output" of the dll project to the project and then go to the Custom Actions pane via the view option in Setup Project.

Once there I was able to add the "Primary output from CustomAction1" (the dll) as an install custom action.  In the properties window for the custom action (you have to select it) I set the following values:

CustomActionData = /Message="Message1" /OtherMessage="This is the other Message"

InstallerClass = True

And with that I had my CustomAction MSI (I left it labelled "Setup1" in my example).  This is about as simple as it gets and it doesn't nearly cover everything (I didn't implement Uninstall or Update steps).  I believe the "power" in the MSI method is that you can hook into a standardized setup framework and it handles a lot of details you would otherwise need to implement.  This goes a little outside my particular area of expertise and I haven't had time to do the full degree of experimentation to give a definite reasons beyond that yet though.  If anyone is interested in educating me or clarifying anything on this stuff, please feel free to leave a comment.

In the next installment I'll cover how I authored the package manifest files so VS can include this at publish time.

My post frequency has been a down a bit lately due to being busy with a lot of things but I am responsive to feedback (I've gotten a littler here and there, please feel free to post any comments or questions here so others may also get the benefit of it).  And with that I'm going to wrap up this post.

Thank You for reading.

Kris
Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxMSI VSTO Deployment revealedhttp://blogs.msdn.com/b/krimakey/archive/2008/06/09/msi-vsto-deployment-revealed.aspx2008-06-09T17:30:21Z2008-06-09T17:30:21Z
For the past couple of months I have been avoiding talking too much on this blog about about creating "Windows Installer" deployments of VSTO.  I've been avoiding it because we've been working on writing a well-formed paper on how to do this and I wanted to wait for it to come out.  So here's the link to the announcement (includes links to the paper):

http://blogs.msdn.com/vsto/archive/2008/05/29/deploying-office-solutions-with-a-setup-project.aspx

If you're not convinced the ClickOnce deployment model is for you, this is the method you should consider and I recommend reading this paper and looking at the example before proceeding.

That's all I have for the moment, I'm looking for any interesting stories or questions to answer though, so please feel free to send me some feedback.

Thank You for reading.

-Kris-
Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxTwo years of lessons learned.http://blogs.msdn.com/b/krimakey/archive/2008/05/23/two-years-of-lessons-learned.aspx2008-05-23T19:00:00Z2008-05-23T19:00:00Z
It's been a while since I've posted here, I'm not quite ready to jump back into pushing deployment stuff again, I have had other things on my plate (vacation being one of them) and am finding less time to tackle the interesting questions that are coming through.

That said, I do want to keep up the habit of posting, so I'm going to switch gears a bit and talk about something a little more general than VSTO Deployment.  Yesterday marks 2 years working for Microsoft, working in the software industry and working in the testing field.  Here are some of the things I have learned in those two years that I think may interest you:

On Chocolate:

Having a candy dish full of chocolate is a great way to learn a lot of interesting things with very little effort.  I maintain my candy dish religiously and it's turned out to be very fortuitous.  Every time someone comes to "snatch" a piece I can often engage them long enough to learn something interesting from them.  Sometimes it is programming tips and other times it is just basic information about what they're working on.

Another lesson with this:  don't eat the chocolate yourself, it's just not as good if it's not provided by someone else.

On Testing in General:

When I started working my belief was that a tester's goal was to find bugs.  In some cases this is true, but here at Microsoft, my job is to make the product better.  With this in mind a lot of what I focus on is not so much "finding bugs" but at "understanding" the product (and writing bugs when the understanding reveals deficiencies from what the product does and what we say it does or want it do ).  Part of this understanding is knowing what customers need which is why I am here writing this, hoping that should you be reading you'll drop me feedback on how you're using "my product".

On Automation:

I believe software testing as an industry and automation in particular are still in an infant stage.  What I have seen internally and what I have heard about what happens outside of Microsoft indicates to me there is still a lot of work to be done and learned in this space.  With that in mind, I believe the goals of Automation are often counter to what automation actually provides.  Automation doesn't find bugs during development but rather forms a sort of rigid documented (in code) expectation of what the product is that is easily evaluated and repeated.   I'm not saying that Automation isn't important (quite the opposite) but rather often its value is not fully understood.

Automation is important especially if you want your product to work outside of the context in which it is initially written.  (We will sometimes find bugs around things like localization/globalization, though automation is only one step.)

The more "customer scenario" focused your automation is, the more likely it is to move forward and be understandable.  It is very easy for me to write automation that checks that the value within a file is the same as the value specified in a text box within the product, but the value of that test is much harder to express and the test is more likely to be broken as the product changes. However, if I tell you my test installs an add-in that was published to a web server, it's clear to see how the test is "relevant" to how the product works and it also is more likely to move forward as the product does.

Automation writers may know more about complex problems than product developers:  Automation often must be product, context and language resilient.   If your product is potentially going to have backwards and forwards version resiliency, you might ask your automation writers if they've tackled the problem before and what they've specifically learned about it.

On Development:

Be intentional.  When you are writing something new:  draw a picture or at least tell someone about your design.   Designing something before writing it will always result in something better then something you simply "piece together".

Use intellisense comments when available.

Use comments to give context and meaning to your code.

Avoid using TODO:,  TODO is a form of procrastination that can often cost you more than simply doing the work initially.  If you absolutely can't implement something at that moment, instead of just a "TODO:",  leave a (large) block comment at the entry point for what needs to be done and throw a not-implemented exception (preferably with something to help indicate what needs to be implemented).

Own your code but expect that you may be hit by a bus tomorrow.  This means that when you check code into source control you expect that someone will be able to pick up where you left off and achieve your same (end) goals.

On working in general:

Be open to other people's interests.  It's a lot easier to get cooperation from someone who you've helped than to ask for help from someone with a promise of future help.

Never eat lunch alone.

Be fearless even in the face of failure:  failing is an opportunity to learn and improve (don't forget to grasp it).

Thanks for reading.

Kris

[edited 5/27/08:  Minor typos and sentence clarification]
Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxCorrection!http://blogs.msdn.com/b/krimakey/archive/2008/04/30/correction.aspx2008-04-30T04:18:23Z2008-04-30T04:18:23Z
I got ahead of myself and thought it was one week later than it really is (sort of good because I was beginning to think I was a lot further behind than I was).  I will be out next week.   Unfortunately this week has been super crazy.  I'm going to skip a full post this week but I will point out some posts of interest for those who may be looking at an "All-user" administrative installation.  Misha Shneerson has written some very good posts all about all-user installation in VSTO on his blog.

The posts are here:

http://blogs.msdn.com/mshneer/archive/2007/09/04/deploying-your-vsto-add-in-to-all-users-part-i.aspx

http://blogs.msdn.com/mshneer/archive/2007/09/05/deploying-your-vsto-add-in-to-all-users-part-ii.aspx

http://blogs.msdn.com/mshneer/archive/2008/04/24/deploying-your-vsto-add-in-to-all-users-part-iii.aspx

You should pay specific attention to the third article as it covers VSTO 3.0 specifically.

With that, I'm going to go back to being super-busy until I wrap up this week and then take a week off (there definitely will be no post next week).

Thank You for reading.

Kris
Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxOne-Shot customizations, but we're not VBA.http://blogs.msdn.com/b/krimakey/archive/2008/04/22/one-shot-customizations-but-we-re-not-vba.aspx2008-04-22T16:45:41Z2008-04-22T16:45:41Z
Last week I had the pleasure of getting some very interesting feedback from some of the Microsoft Office development audience (people who develop against office through VSTO/VSTA/VBA/Shared Add-ins/etc ).  If you were at said event and are now reading here because of it, I welcome you and hope you enjoy the time you spend.

One of the more interesting things of note I heard was that VSTO just wasn't as easy and simple to deploy for those one-shot customizations that might be created to solve a small problem, save some time or simply just do something repetitious quicker.

Certainly this is entirely true under the older Security model, CASPOL is not something you just "simply do" and move on, it takes a fairly significant degree of initial investment and understanding of .NET to get to the "working" state.  Click-Once can also seem like it's a little too heavy-weight for a similar reason, there's all this extra stuff to consider:  prerequisites, updating, a publishing location, certificates.

This is why I'm going to talk about the "tricks" you can use for that simple once-off git 'er done solution.  These methods are supported they are not considered our prime scenarios used in this particular context.

First Let's talk about publishing versus building.  If you are creating a customized document, you might consider bypassing publishing, although if you're creating application level customization (something that will impact multiple documents) then I fully recommend publishing even for these quick and dirty solutions.  There are still some things you can do to make things simple and quick with the publishing experience in add-ins.  I will come back to add-ins and publishing after I cover documents.

Documents!

What the Developer needs to do:

Copy (or email) the entire contents of the bin/release folder over to the "user", Zipping the folder is perfectly acceptable.

Inform your user about the "Trust Prompt" (see below)

Inform your user about that moving the document around without moving the customization files can cause the customization to stop working.

What your user needs to do:

Keep folder contents together (document must be in the same folder as .vsto, .dll.manifest and .dll file)

Click the "Install" prompt when the document is opened.  (This is just asking for Trust)
(note:  The right part of image just shows "vstolocal" the user doesn't need to be aware it)

"Un-install" can be achieved by deleting the document and customization files, though you should know that it does leave the trust decision behind (a single registry key).

Incremental improvements towards more "professional" level solutions that you can do:

(Developer Action) Acquire a proper (verifiable by Certificate Authority) code-signing Certificate from a well-known Trusted Root Authority and Sign you manifests with it instead of using VS generated Self-Certificates.  This changes the information in the "Trust Prompt" from 'unknown publisher" to "<YourName on certificate>":

Have your user install your "proper" certificate into their trusted publisher list. By having your user trust you as a publisher, they will no longer be prompted to install the solutions you sign with your certificate.

(Developer Action) Export your Signing Certificate without the Private key (I use Certmgr.msc in windows vista here in this example)

(Developer Action) Send your public-key-containing exported certificate file to your Customer.

(User Action) Double-click the Certificate file to start the install process.

(User Action) Click "Install Certificate"

(User Action) Select "Place all certificates in the following store" and Choose "Trusted Publishers"

Re-Customize the Document to look for the manifest file in a specific location.  If you do this, then the document can be moved around but the .vsto/.dll.manifest/.dll files must stay in one (specific) location.  You can do this with Office my manually editing the custom properties as shown in this image:

Add-ins.

Inherently there is a more work to do since you need to somehow "hook-up" the add-in to the hosting (Office) application.  Fortunately for you, we've thought through this scenario.  Here are the steps to the quickest "simple" setup.

What the developer needs to do:

Set the Publish Location to "publish", this will put the final add-in files in the project/publish folder.

Set the Updates to Never, because you will not be providing and update framework.

Click Publish

Copy the publish folder contents to a zip folder or disk.

Inform your user about the "Trust Prompt" (see document example).

Inform your user that they must un-install using Add-Remove Programs, but can delete the "setup" files after installation.

What the user needs to do:

Run Setup.exe (if you think they may not have the .NET runtime or VSTO Runtime) OR you can have them double-click the vsto file from their end (CD,un-zip folder, etc)

Click the "Install" prompt when it comes up.

Use Add-Remove-Programs if they need to un-install.

Incremental improvements towards more "professional" level solutions that you can do:

(Developer Action) Acquire a "proper" code-signing Certificate from a well-known Trusted Root Authority  and Sign you manifests with it instead.  This changes the information in the "Trust Prompt" from 'unknown publisher" to "<YourName on certificate>" (See the document example of this)

(User Action) Install your "proper" certificate into their trusted publisher list. By having your user trust you as a publisher, they will no longer be prompted to install the solutions you sign with your certificate.  (See the document example of this)

(Developer Action) Deploy the Add-in via CD and as long as it is run from the same drive as the original install on that computer, updates can be achieved in the same manner as a "normal" install.

These are the easiest 2 "throw-away" solution deployment methods that I can think of.  There are so many advantages to using VSTO you shouldn't feel blocked by the belief that deployment must always be Click-Once with large amounts of infrastructure.  There are ways to wrangle it to manage scenarios beyond the initial "deploy via server and provide constant updates" model that Click-Once specifically targets well.

With that I'll wrap this up with a final side-note.  I wrote the bulk of this post a week early because next week I will be on a boat most likely not thinking about anything other than having fun and looking at scenery.  I may or may not have a post due to this trip, but it's possible I might have just enough of a backlog to work something out.

Thank You for Reading.

Kris

[note:  Edited 5-19-2008, Attempting to clarify what is done by user versus developer]
Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxClick-Once forced updates in VSTO II: A fuller solutionhttp://blogs.msdn.com/b/krimakey/archive/2008/04/18/click-once-forced-updates-in-vsto-ii-a-fuller-solution.aspx2008-04-18T16:00:00Z2008-04-18T16:00:00Z

Last Week I talked about user-generated updates and the Click-Once Deployment Management API's.  Based on some internal feedback and a large degree of personal interest, I'm going to come right back around to the same topic, but with a cleaner solution that does the whole kit and caboodle and does it nicely.  While certainly I have put a lot more investigation into this method, the disclaimer still stands.

This scenario is not fully tested and strictly speaking is not supported.

That said, here are the features I am implementing:

A customized document that...

Checks to see if there is and update on the Server

Reports the Current Version

Reports the Version on the Server

Specifies the Click-Once Cache Path (for debugging purposes, I needed to verify information)

Specifies the Document Path (for debugging purposes I needed to see the string result, you'll see why later)

Updates the Solution "on demand"

Restarts the Application and Re-Opens the Document to ensure the most recently installed update is being executed.

Maintains a certain degree of "safety" around debugging (occasionally I forget and hit F5).

So there's the list, pretty lengthy, but I wanted to be clear about what my goals were.  I spent about 6 or so hours working through this, mostly because I wanted to do something a little more robust then my usual fare.  As a result I ran into some issues that are worth noting:

In last week's example, the solution I used I was deploying to a local UNC share; in this example I deploy to a local path.  One of the more "interesting" results was that I ended up dealing with paths that had spaces in it.  This is particularly interesting because... application arguments are split on the space character.  The basic lesson here should be:  If you are dealing with paths in a scenario like this it is probably better to use URI's and enforce absolute URI's so you don't have some of the issues that come from special characters.

I also had to spend to much time determining what using statements I needed to enable the API enabling trust code.  As a result, I will post those statements:

using System.Security; using System.Security.Permissions; using System.Security.Policy; using System.Deployment.Application;

Finally:  Reporting is important, I generally use Message Box because I'm lazy and don't want to write real error-handling code for these investigations.  What I'm finding though is the more complicated stuff I write, the more information I end up packing into the messages to aid in debugging.  I fully recommend if you do any these things out in the wild you ensure you're using really good reporting tools.  The more information you can shove into logging when things go wrong, the more likely you'll be able to figure out what happens.  This is particularly important when you do stuff like spinning out separate processes to do things, those processes are particularly hard to capture during debugging so verbose reporting is likely to save you a lot of time.

That said, let's get back to the actual project, or actually in this case 2 projects.  Last week I mentioned the need of restarting the customization after the update finishes.  I don't personally know of any inherent support for doing so, but that doesn't make it impossible to do.  It is possible there is a better way, but this is what I came up with based upon a week of mulling it over while also being very very busy.  This solution achieves the restart by shipping a executable that handles the re-opening the document.  I call this this tool "Word Restarter" because amazingly enough it restarts word.

Word Restarter

What I did was create a Managed Console app, and then set it to be a Windows Application.  This creates a program that runs very lightweight with no UI (at least not any that I don't explicitly supply) that I can now pass just enough information to be very useful.

Here's the code for this console app:

//used in exception cases and debugging. foreach (string s in args) argAsString = argAsString + "[" + s + "]"; try { //Missing is used because C# does not have optional parameters Object missing = System.Type.Missing; //Check to see if any existing Word Processes exist System.Diagnostics.Process[] currentWordProcesses = System.Diagnostics.Process.GetProcessesByName("WINWORD"); //Empty Case gets ignored, lazy but effective enough foreach (System.Diagnostics.Process p in currentWordProcesses) p.WaitForExit(); //Could be more, but I'm being restrictive because I want to //make sure it fails quickly if (args.Length != 1) throw new Exception("You must Specify a full path to a" + " valid Word Document to use this program."); string path = args[0] as string; //Path Doesn't handle URI's. //if (System.IO.Path.IsPathRooted(path) == false) // throw new Exception("You must Specify a full path to a " + // "valid Word Document to use this program."); Word.ApplicationClass wordApp = new Microsoft.Office.Interop.Word.ApplicationClass(); wordApp.Visible = true; //cast the path to an object (Office PIA's operate on Objects) object docpath = (object)path; wordApp.Documents.Open(ref docpath, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing); } catch (Exception e) { System.Windows.Forms.MessageBox.Show( "The following Exception Occured " + "when trying to restart the Word Process: " + e.Message + "\n\n Stack: \n" + e.StackTrace + "Args("+args.Length+"): \n" + argAsString); }

It could certainly be better, it's not super robust, but it should be just enough to give you an idea on what is necessary to accomplish the task.  There are some pretty serious flaws in this specific implementation, I am basically assuming that all Word Processes will go away, but the code I call in the customization does not explicitly close-all documents.  It's possible to kill all version of the word process but.  I leave it to you to think  about this further I just want to point out that this still isn't production quality.

Once I was fairly confident I had this working I built a retail build of this exe and moved on to the document.

Self Updating Doc

Really this should be "User Updating Document" but it doesn't really matter too much, it's a name.   Anyway, this project is fairly simple and is very similar to the one I created last week.  The key piece of this project is, I'm only using one method to update the document, but I'm doing it in the way I felt last week would be ideal.

So here are some (path obfuscated) images of the Document in action:

"Initial" Run:

Published a "new" update and then Clicked "Check For Update".  The document was still running from the Desktop this entire time:

Clicked Update, watched Word disappear (clicking through my debugging information dialogs) and finally word comes back up with:

While I do obscure the paths for security reasons, I did want to point out that the Cache Path changes.  This is particularly of note because it should help explain why an update can happen while the customization is still executing.  That said, I haven't spent a lot of time investigating the data caching behavior that occurs, so make sure you fully test any side-by-side / error conditions / resource handling scenarios that might occur if you decide to implement this in production code.

So what does the code look like?

Well...during start-up I setup the trust so I can access Click-Once API features.  I would recommend isolating these calls to those times this functionality is called by the user to simply reduce the work that happens during startup, but in my case startup time is effective enough.  Then I check some initial values and fill the information in the labels:

if(ApplicationDeployment.IsNetworkDeployed) { Assembly addinAssembly= Assembly.GetExecutingAssembly(); CachePath = addinAssembly.CodeBase.Substring(0, addinAssembly.CodeBase.Length - System.IO.Path.GetFileName(addinAssembly.CodeBase).Length); CurrentDep = ApplicationDeployment.CurrentDeployment; string deploymentFullName = CurrentDep.UpdatedApplicationFullName; ApplicationIdentity appID = new ApplicationIdentity(deploymentFullName); PermissionSet everything = new PermissionSet(PermissionState.Unrestricted); ApplicationTrust trust = new ApplicationTrust(appID); trust.DefaultGrantSet = new PolicyStatement(everything); trust.IsApplicationTrustedToRun = true; trust.Persist = true; ApplicationSecurityManager.UserApplicationTrusts.Add(trust); }

Here's the "Helper" Function I call after setting the trust statement to check the deployment location.

private void CheckForUpdate() { if (ApplicationDeployment.IsNetworkDeployed) { if (CurrentDep.CheckForUpdate()) { UpdateCheckInfo updateInfo = CurrentDep.CheckForDetailedUpdate(); ClickOnceVersion = updateInfo.AvailableVersion; } else { ClickOnceVersion = CurrentDep.CurrentVersion; } label1.Text = "Current Version: " + CurrentDep.CurrentVersion.ToString(); label2.Text = "Deployed Version: " + ClickOnceVersion.ToString(); label3.Text = "CachePath = " + CachePath; label4.Text = "DocumentPath = " + Globals.ThisDocument.Path + "\\" + Globals.ThisDocument.Name; } else { string notClickOnce = "This Customization is not ClickOnce Installed."; label1.Text = "Current Version: " + notClickOnce; label2.Text = "Deployed Version: " + notClickOnce; label3.Text = "CachePath = " + notClickOnce; label4.Text = "DocumentPath = " + notClickOnce; } }

In "real" Solution I would just have a single button that you click to check for the update and that proceed to download the update only if the version is a new version (You simply need to call "CheckForUpdate" unless you want to report Version info).  In the case of my document, I just call the CheckForUpdate helper function when the Check for Update button as way of helping me validate the state appropriately.

And Finally the updating code:

if (ApplicationDeployment.IsNetworkDeployed) { Uri DocPath = new Uri(Globals.ThisDocument.Path + "\\" + Globals.ThisDocument.Name); Uri InstallerPath = new Uri("C:\\Program Files\\Common Files\\microsoft shared\\VSTO\\9.0\\VSTOINSTALLER.exe"); Uri RestarterPath = new Uri(CachePath + "WordRestarter.exe"); Uri Updatelocation = new Uri(CurrentDep.UpdateLocation.ToString()); DialogResult dResult = MessageBox.Show( "Are you sure you want to continue?\n" + "Updating will require a Restart of Word,\n" + "Cancel now or forever hold your peace", "Update Requested", MessageBoxButtons.OKCancel); if (DialogResult.OK == dResult) { //Call VSTOInstaller Explicitely in "Silent Mode" Process VstoInstallerProc = new System.Diagnostics.Process(); VstoInstallerProc.StartInfo.Arguments = " /S /I " + Updatelocation.AbsoluteUri; VstoInstallerProc.StartInfo.FileName = InstallerPath.AbsoluteUri; VstoInstallerProc.Start(); //Call VSTOInstaller Explicitely in "Silent Mode" Process RestarterProc = new System.Diagnostics.Process(); RestarterProc.StartInfo.Arguments = DocPath.AbsoluteUri; RestarterProc.StartInfo.FileName = RestarterPath.AbsoluteUri; RestarterProc.Start(); VstoInstallerProc.WaitForExit(); if (VstoInstallerProc.ExitCode == 0) MessageBox.Show("Update was succesfull, restarting.."); else MessageBox.Show("Update failed: Exit Code (" + VstoInstallerProc.ExitCode.ToString() + ")"); object save = (object)false; this.Application.Quit(ref save, ref missing, ref missing); } }

Ideally you would determine the Installer Path using Environment Variables or some other more robust method, I just wanted to get this working so I've hard-coded the path.  You'll notice that I am using the Uri class here to handle the paths, this turns out to be a much more robust method for ensuring the paths are well-formed when you pass them off to the Process Class.

Let's go back to the WordRestarter for a second.  You'll notice that I'm using reflection to figure out the location of the cache and then subsequently using that path to get to the executable.  You're probably wondering how it got into the cache.  To put it simply, I shipped it as part of the Click-Once package.  To do this I added the executable file as a content file that is always copied.  Here's what it looks like in VS:

If you are worried about the security implication of using this method, I want to point out a couple of very relevant facts:

The executable hash is injected into the Click-Once Deployment Manifest.

Tampering of the Executable on the server would cause the update to be rejected.

The manifest is signed with a Certificate that helps guarantee that the user trusts either the specific publisher or the user trusts the specific solution at a specific location.

With that I'm going to finish this particular post (that's 2 long ones in 2 weeks).

Thank You for reading.

Kris
Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxClick-Once forced updates in VSTO: Some things we don't recommend using, that you might consider anyway.http://blogs.msdn.com/b/krimakey/archive/2008/04/10/click-once-forced-updates-in-vsto-some-things-we-don-t-recommend-using-that-you-might-consider-anyway.aspx2008-04-10T16:00:00Z2008-04-10T16:00:00Z
Before I go any further in this post I'm going to put a huge disclaimer:

You should be warned what I'm about to cover has not been fully tested, is clearly not supported or recommended and may have significant impact on your application's ability to work.  Additionally there is no guarantee that we will support these scenarios or methods in future versions or patches.  The scenarios I cover are to answer specific questions and should be considered an academic exercise in how VSTO behaves.  Your mileage may vary.

Okay so disclaimer said,  I'm going to talk about is something you can do with a win-forms Click-Once application that you might try to do in VSTO (albeit with some large caveats).  The basic scenario is this:  You develop a customization that periodically checks for updates which contains a button that the user can "force" an update check with.  Click Once provides an API for this that works very well, and you can use this same API with VSTO though you travel from the realm of "it works and we've fully tested it" into the realm of "it might work but will very likely 'break' you anyway".

So lets' get to the point, in previous posts I've mentioned that you can reference System.Deployment and with a little work get access to the "CurrentDeployment" object.  I've used this in the past to demonstrate how to detect if your customization is running from local disk or from the Click-Once Cache.  We're going to use the same API, but now we're going to "force" an update check and install it.  The second method is going to use our friend the "VSTO Installer" executable that ships as part of the VSTO Runtime 3.0.

Here's an example of a customized document in which I have create that demonstrates both methods:

I've dropped some Controls onto this document to demonstrate 2 basic scenarios and additional options for the first scenario.

The basic flow is this, the user clicks the button and the 2 labels beneath it will give some information about the update/version.  The first label will display the current running version and the second will display the version after it the update has run.  As you can see in the example image the version is the same.  I show this now to demonstrate the next point I'm about to make.

When the customer updates the solution in this manner (either through the API or via VSTO Installer) the current running version will not change.  To fully update to the new version the running version of the customization would have to be shut down and the new version loaded up.  Currently neither Office or VSTO have support for doing this at the moment.  I imagine there are ways to do this but I'll leave that for a later time.

So let's talk a little more about the API itself.  I'm going to cover it first because I personally feel it's not the best solution for several reasons and then I'll move to what I feel is in a better direction.

The first issue that comes up is a matter of trust.  In order to use the API to update the customization the developer needs to grant specific permissions to the code in the Click-Once Cache.  My understanding based on the feedback from the developer who provided me with the trust code that this is a case where the differences between the Click-Once Trust Model and the VSTO Trust Model differ.  What happens under the hood here is this:  ultimately in VSTO the VSTO Runtime is what determines the trust for the Addin.  When it creates the Add-in it evaluates everything against the VSTO trust model and (given the Add-in is actually trusted) executes the Add-in code under full trust.  Since the trust is evaluated and stored by the VSTO Runtime the Add-in must set the trust/permissions for the code in the Click-Once cache in order to execute the update, but it is able to do this since VSTO Add-ins always run under the "Full-Trust" Context.

So here's the the trust code for enabling the API:

//Create the appropriate Trust settings so the Application can do //Click-Once Related updating ApplicationDeployment CurrentDep = ApplicationDeployment.CurrentDeployment; String deploymentFullName = CurrentDep.UpdatedApplicationFullName; ApplicationIdentity appID = new ApplicationIdentity(deploymentFullName); PermissionSet everything = new PermissionSet(PermissionState.Unrestricted); ApplicationTrust trust = new ApplicationTrust(appID); trust.DefaultGrantSet = new PolicyStatement(everything); trust.IsApplicationTrustedToRun = true; trust.Persist = true; ApplicationSecurityManager.UserApplicationTrusts.Add(trust);

The reason why I would not use the API for updating is that there are steps that the VSTO runtime must do as a result of the add-in existing within an Add-in Model versus a Stand-alone Executable Model.  Essentially the add-in model is a little more complex than a "standard" Click-Once scenario since not only does the execution code have to be moved onto the user's machine, but also there is a chunk of meta-data that needs to be communicated to the Host-Application for the Customization so that the host process can properly plug-in the customization.

What this turns out to mean is: when the update is done using the API, not every part involved in the customizatoin is correctly updated.  The behavior that I see when I tried this scenario is that the ApplicationDeployment object behaves strangely after the update occurred.  My initial investigation indicates that the solution information store is out of date after the update which then causes the customization to be running in an unexpected context.

I won't show you the code for updating because I can't personally recommend it for your application.  What you might do though is use CurrentDeployment.CheckForDetailedUpdate() which will tell you if an update is available at least.

Anyway.

Let's move on to using VSTOInstaller...

In a previous post I talked about VSTOInstaller, but as a quick rehash, basically it's an thin executable that uses the same functionality in the runtime to update/install the customization.  What it means in this scenario is that we can use System.Diagnostic.Process to call it and force an update.  In the example code that I'm going to post I call it in 2 ways to demonstrate 2 alternative methods to consider.

In the first method you call VSTOInstaller directly (and silently).  The advantage in using this method is that the user does not see any UI.  The VSTOInstaller will return a negative value if the "update" failed.  Unfortunately the return value of 0 is the only "positive" value you will get back and it is not informative of whether or not an update occurred or if the current version is up to date.

Here's the Code for using VSTOInstaller Directly:

label1.Text = "Current Version: " + ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString(); //Call VSTOInstaller Explicitely in "Silent Mode" string installerArgs = " /S /I \\\\GenericServer\\WordDocument2.vsto"; string installerPath = "C:\\Program Files\\Common Files\\microsoft shared\\VSTO\\9.0\\VSTOINSTALLER.exe"; System.Diagnostics.Process VstoInstallerProc = new System.Diagnostics.Process(); VstoInstallerProc.StartInfo.Arguments = installerArgs; VstoInstallerProc.StartInfo.FileName = installerPath; VstoInstallerProc.Start(); VstoInstallerProc.WaitForExit(); //Report Exit Code MessageBox.Show("Exit Code: " + VstoInstallerProc.ExitCode.ToString()); //End "Silent Mode" Scenario

If you want UI the easier method is to simply "shell out" the path to the .vsto file.  Doing so would invoke the mime handler which under the covers calls VSTOInstaller.  This method is less likely to fall prey to issues that come of running on future versions of the runtime(not that I'm saying we support you doing this exactly and I'm not going to go into specifics currently).  The UI will inform the user if the update actually happened or if the version was up-to-date but I don't know what would happen if the path is not available and there may be additional UI that occurs (I have seen specific cases in non-customization managed code where specific security settings on the OS would cause a blocking dialog to occur when the shell handler is invoked in this method).  So your mileage may still vary.

And here's the code for installing using the Shell Handler:

//Call VSTOInstaller Via the Shell (will show UI) assumes the Mime handler works string manifestPath = "\\\\GenericServer\\WordDocument2.vsto"; System.Diagnostics.Process ExplorerInstallProc = new System.Diagnostics.Process(); ExplorerInstallProc.StartInfo.Arguments = manifestPath; ExplorerInstallProc.StartInfo.FileName = "explorer.exe"; ExplorerInstallProc.Start(); label2.Text = "\"NEW\" Current Version: " + ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString();

Here are some items to keep in mind if you are considering this at all:

VSTO Installer is less likely to put you in bad state then calling the API's directly.

Cached Data (in the Click-Once Data Cache) may be impacted (I would recommend thorough  testing/investigation).

You might consider shelling out a process that 'sleeps' until the Office app is closed and then causes the Update.

You might consider forcing a restart of the office application after the update occurred.

Warn your users that they may want to save their data before you start the update process.

Thoroughly Test anything before fully integrating it into any solutions.  Make sure you try it under extreme security situations (IE Protected mode on while running as a normal user).

If you do end up using any of this or have come up with a better solution, feel free to comment, I love open discussion about this stuff.

Thank You for reading.

Kris Makey
Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxLate but live!http://blogs.msdn.com/b/krimakey/archive/2008/03/31/late-but-live.aspx2008-03-31T16:30:52Z2008-03-31T16:30:52Z
I was planning to post something about 3 days ago but things have been a little crazy on the home front (lets just say that 'the games' have been playing me these days) and a lot crazy on the work front (can't talk about it exactly, but it's been good busy mostly).

I have no VSTO tips today, sorry.

However I had a chance to receive some general advice on blogging, display styles etc.  So this should almost be "See What I See Version 2-beta".  On recommendation I've installed Windows Live Writer, and to be honest so far it has been a pretty okay experience.  I had a lot of trouble connecting up the piping initially but it seems to be more of a factor of bits-in-the-piping issues (restrictive network settings) than anything wrong with the software.  Firewalls can be tricky things sometimes.

Anyway, I got everything up and running and with a bit of customization I can now paste "nice" code instead of the ugly black boring notepad code I have been pasting in the past.  An example:  here's some "C++" "Code" that I _may_ have written recently to do a bit of a "refresher" since it's been almost 2 years since I've done anything serious with C++.    Oh how the time flies and the tools rust.

// MyCppIsRusty.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "Widget.h" int _tmain(int argc, _TCHAR* argv[]) { int result = (int)*argv[1]; printf("The Result is: %i \n", result); RustRemoval::Widget *Foo = new RustRemoval::Widget(); result = Foo->SomeFunction(result); printf("The result after manipulation is: %i \n", result); return 0; }

Yes that is real code, it  doesn't do anything interesting and has bugs, I was exploring building static library building and the actual content didn't matter so long as I was getting results from code that wasn't in the project itself.  I do have to say though, going back to C++ after being spoiled by C# for so long, There are some things that .NET just does better.  Building multi-component software using dll's is nicer.  In .NET there are no header files I have to copy around, if you want to use my dll, simply create a reference to it and everything is golden.

One last thing, Here's a random picture to see what Live Writer can do:

If you can see the image, then Live Writer gets 2 thumbs and a pinky up from me.

As always Thank You for reading,

K.
Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxVSTO 3.0 and .NET 3.5 http://blogs.msdn.com/b/krimakey/archive/2008/03/21/vsto-3-0-and-net-3-5.aspx2008-03-21T04:26:00Z2008-03-21T04:26:00Z
From time to time I will come across (via various channels) a question of why VSTO 3.0 requires the 3.5 framework. Usually these questions are prefaced or suffixed with a "in VSTO 2005 SE I was able to use 2.0, why are you making me use 3.5 now?"

Just to clarify, when I talk about VSTO 3.0 I mean only the addins that are build in VS 2008 and are labelled "Office 2007". Office 2003 addins in VS 2008 are essentially the same as addins build in VSTO 2005 SE (which can be loaded in both 2003 and 2007).

The answer is both short and long and simple and complicated. The short and simple answer is that VSTO 3.0 requires .Net 3.5. If I left it at that I imagine I would get a lot more questions so I'll go into the long answer:

In the VS 2008 timeframe we rebuilt the loading model for VSTO. This new loading model consists of 2 major parts, the first being that the VSTO runtime now uses the System.Addin Framework. You can read about the System.Addin framework here: http://msdn2.microsoft.com/en-us/library/bb384200.aspx. I don't know as much about this, but I'm told that it is a good thing all around.

The second major part, the one that I do know about is around "deployment" (ClickOnce). In VS 2008 we integrated the ClickOnce model of trust, installation and loading into the Runtime. The benefits have been that the model is much easier to use for the end user. The associated cost has been that in order to integrate this functionality properly, additional changes to the ClickOnce framework had to be made (some of which is only a part of the 3.5 framework). These changes not only include publishing and installation but it includes the basic security model that the VSTO runtime uses.

So even if you don't use ClickOnce with VSTO 3.0 solutions, the runtime itself relies on functionality that exists only within the 3.5 framework. Hopefully that clarifies the reasoning behind why we require the 3.5 framework.

Until next time, thank you for reading.

Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxIf memory serves me correctly...http://blogs.msdn.com/b/krimakey/archive/2008/03/08/if-memory-serves-me-correctly.aspx2008-03-08T07:43:00Z2008-03-08T07:43:00Z
Memory is king and he who remembers the most rules will rule the most (not a real quote but it sounds interesting). Anyway, it is very easy to create "widget" apps with VSTO that "do" something, but often where the really interesting projects come into play is when the app can "do" something and then save state. Sometimes state can be minor feature like keeping the previous values used in a control or something large like storing associations and actions to allow data manipulation.

In this post I'm only going to cover an example of lightweight state caching and I will leave it up to you to imagine some of the more interesting scenarios this can be applied to. So in this little project I'm working on I have a drop down control on Ribbon Control of a Customized Document. This control contains a list of "Emotive States" that I might want to associate with blocks of text. In typical lazy fashion I could just set the initial on startup and not worry about it from moment to moment but lets say I know that likely the user of the document is most likely going to use one state more often than the others. As a nice "micro-feature" I want to save the state between instances of opening the document. Because this state is more of a "program state" rather then "document state" ideally I will want to store the state with customization and not with the document itself.

So lets consider some of the Data features in VSTO:

Manually created Data Files out to disk on the user's machine but there is a lot of work around things like "where" and potentially permissions issues that might come up. Ideally I don't want to have to think about these things myself.

Binding to a Database seems like overkill. Really all I want is to know what the last stored value for the current user is, I don't want to have to have them deal with databases, etc.

Custom XML in the document is a possible option but this is better for saving state specific to the document rather than things like control settings. Also this feature takes a lot of work to really understand how to hook into the Office Files nicely so I'm not really going to use this approach this time.

VSTO Data Store is also associated with the Document and really is a much nice way of achieving the same results of Custom XML without the pain of the Office object model so while a possibility I still am going to bypass this feature also.

ClickOnce Data Directory is the feature that I really want to use. I can associate Data with the customization code rather than a specific instance of the document. This gives me a nicely protected User space for allowing user specific settings and data.

Okay so that seemed a little forced even to me...basically if you want to store things like application settings and users settings, I think this is the route to take since it provides a "safe" method for producing files and it eliminates a lot of the details of file management that might have to otherwise be create by the developer (or myself in this case).

So lets talk about the ClickOnce Data Directory. Basically it is a folder "somewhere" that code executing under the user's credentials can write to. Additionally since the data folder is managed by ClickOnce, the headache of worrying about things like "un-installation" are simply not something you have to worry about. The data directory is obfuscated just like any other part of the cache. If you add a reference to System.Deployment you can use the ClickOnce API to access the Data Directory.

VSTO supports using the data directory but currently in VS 2008 there isn't any UI around it specifically. If you have much experience with Window Forms you may know that you can set many files as data files. You may can do the same with VSTO but you would have to do so manually in the manifest files (and then you would have to re-sign them). By default though if you include an xml file (must be of the .xml extension) we assume it is a data file and should be copied into the Data Directory on installation. In VS you must set the xml file as a content file that is always copied. Once you have done this step you're already well on your way to having application data settings.

So let us assume you've created an XML settings files, something that might just contain a root node like: <data></data>

The first thing you will want to do is hook it up using the deployment API's and open the file to show you can in fact access the data file. Unfortunately if you do this and hook up to the API then hit F5, you will get an exception. The reason is fairly straight forward, until you install the solution into the Cache it isn't a "real" ClickOnce Solution and there isn't a data directory to get to. So here's a code example on how to hook up to the API such that the data directory is used when the solution is "installed" into the cache and simply expects the file to be side-by-side with the customization dll when it is run in the "local" (|vstolocal) context. If you wrap any calls to the data files in this way you should be able to F5 your solution, create an MSI installer or use ClickOnce without changing the code.

So here's the code i used in my project:

[code]

private EmotiveState LoadEmotiveState() { string xmlfile = ""; XDocument CachedDoc; if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed) xmlfile = System.Deployment.Application.ApplicationDeployment.CurrentDeployment.DataDirectory + "\\EmoTesterSettings.xml"; else xmlfile = ".\\EmoTesterSettings.xml"; CachedDoc = XDocument.Load(xmlfile); XAttribute Oldstate = CachedDoc.Root.Attribute("EmotiveState"); if (Oldstate == null) return EmotiveState.Neutral; else return EmotiveStateHelper.EmotiveStateFromString(Oldstate.Value); } private void SaveEmotiveState(EmotiveState state) { string xmlfile = ""; XDocument CachedDoc; XAttribute Oldstate; XAttribute NewState = new XAttribute("EmotiveState", state.ToString()); if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed) xmlfile = System.Deployment.Application.ApplicationDeployment.CurrentDeployment.DataDirectory + "\\EmoTesterSettings.xml"; else xmlfile = ".\\EmoTesterSettings.xml"; CachedDoc = XDocument.Load(xmlfile); Oldstate = CachedDoc.Root.Attribute(NewState.Name); if (Oldstate == null) CachedDoc.Root.Add(NewState); else Oldstate.Value = NewState.Value; CachedDoc.Save(xmlfile); }

[code]

As you can see, by keying off the "isNetworkDeployed" property I can choose to use the Data directory or (in the case of F5) the bin folder the dll's are in.

In my example above you can see that I expect there to be a root node, in this case the file contains <data></data>. After running the solution the xml looks something like: <data EmotiveState="Happy"></data>. There is no reason why the files have to be published and installed before the first run, it is possible to add files to the directory, but if you do want to have default settings, using a pre-built data file instead of hard-coded values is a much better way to implement it.

So with that said there are some caveats about the Data Directory. If the solution is rolled back the data may or may not be preserved, generally if you store stuff in the data directory it is important to be aware that you shouldn't be putting mission critical information in it. If the user takes an update (usually) the data they have stored into the data directory is kept which means you also have to consider backwards compatibility. Unfortunately I don't know for certain if there is a reliable way to flush the data directory outside of un-installing the solution, I haven't had time to investigate it yet. Certainly there is a lot more documentation on this feature on MSDN under the general ClickOnce stuff and I fully recommend doing a little more investigation before diving any deeper than I have.

Thank You for reading.

Kris

Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxDelaying the inevitable.http://blogs.msdn.com/b/krimakey/archive/2008/03/04/delaying-the-inevitable.aspx2008-03-04T21:00:00Z2008-03-04T21:00:00Z
Just a micro update:

Ade Miller has an excellent post on how to delay sign vsto dll's. You can see his blog entry here. Basically he is talking about building the solution and Signing the dll's and then re-signing the manifests. If you or your company use some automated process for signing and releasing binaries and you're considering VSTO this article may be of specific interest to you.

 Thank You for reading.

 Kris

Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxWords and more words and words... on Word.http://blogs.msdn.com/b/krimakey/archive/2008/02/29/words-and-more-words-and-more-words-on-word.aspx2008-02-29T21:11:00Z2008-02-29T21:11:00Z
Generally I talk about vsto deployment here, this is mainly due to the simple limitation that what I work on and know best is deployment. In my average day when I am "doing my thing" to improve the product I generally am working on stuff around how files get from one place to another and once the files are lined up does the piping fit so that everything works as we want it to. Today though, I'm going to write some words on Word, or more specifically just some of my thoughts and experiences in customizing word.

One of the things that I do when testing is create tools. A significant chunk my coding time is usually around automation but fairly frequently I have to look at scenarios that are simply outside of the realm of automation. Often in dealing with these scenarios I have to do several steps, so it is natural that given enough repetition, I'd rather have a tool that stream lines information. Usually I create Winform Applications when I'm creating tools. Generally I am working in a situation where I can't assume a working VSTO install so it makes sense to not build my tools around it too much.

There are however cases when I stray from the path of deployment (and even VSTO) and have to look at other things. In one project that I'm working on, I've had to do a lot of cracking into binary storage files. The amount of tooling around this is pretty vast but usually there is a pretty big gaping hole I come across frequently, and that is taking the raw byte hex and "color parsing" it to help visually break down the file. In the current project I'm working, the file uses a fairly standard patterning that is fairly easy to program. So I hacked together a tool to do this (did I say I was going to talk about Word? I really should get back on track....).

One of the limitations of winforms is that working with Text takes a lot more work to add coloring, formatting and dynamic font changing. Additionally it's fairly complicated to annotate text without touching it in a way that is detrimental an irreversible. Frankly I don't want to have to worry about any of those details. So if I have to do something visually with Text (something more than simple spacing/line breaking format) I create a Word add-in or a customized Word doc (aha! I wasn't off track, just taking the circuitous route).

So In this project I was working on, I created a fairly simple word add-in that allowed me to do some quick parsing/coloring of selected text. I think I spent about 45 minutes to an hour writing it (though I re-used another 30 or 40 minutes of previous work I wrote around parsing hex text). This tool has already saved me about 7 hours (I've had it for about a week now). Here's a (slightly doctored image) example of this tool in action:

I doctored up the image a little bit to because I don't want to reveal specific information about the project, but the basic gist is there (the text coloring is valid for example). With a little more knowledge and time, this tool could be expanded into a generic pattern matching program. Additionally there are some very cool features that I'm not even scratching the surface on (reviewer comments for example, if you don't know what they are you should spend some time with Office 2007 in the review pane).

So what does the code look like? I warn you now, this is the ugliest raw code I write. No sane human should have to read it but....here it is:

[Code]

public static void ColorTagRange(Word.Range inputRange) { System.Object missing = global::System.Type.Missing; /* * We're going to Color the Range with the following Pattern: * Tag ID (4 Hex characters) Color 1 * Tag Size (8 Hex characters) Color 2 * Tag Value (2*TagSize value Hex characters)no color change */ string IDSizeValue = ""; int TagStart = 0; int TagSize = 0; int tagIDcount = 0; int tagSizecount = 0; int tagValuecount = 0; Word.Range TagIDRange = null; Word.Range TagSizeRange = null; Word.WdColor IDColor = Word.WdColor.wdColorBrightGreen; Word.WdColor SizeColor = Word.WdColor.wdColorAqua; string inputText = inputRange.Text; char[] inputCharArray = inputText.ToCharArray(); //Set the Tag stat to "ID" TagState currentState = TagState.TagID; //offset from Range start. int offset = 0; Word.Document Doc = Globals.ThisAddIn.Application.ActiveDocument; while(offset < inputCharArray.Length) { switch(currentState) { case TagState.TagID: if (isHexChar(inputCharArray[offset])) { TagIDRange = Doc.Range(ref missing, ref missing); TagIDRange.Start = inputRange.Start + offset; TagIDRange.End = inputRange.Start + offset +1; TagIDRange.Shading.BackgroundPatternColor = IDColor; tagIDcount++; } if (tagIDcount == 4) { currentState = TagState.TagSize; } offset++; break; case TagState.TagSize: if (isHexChar(inputCharArray[offset])) { IDSizeValue = IDSizeValue + inputCharArray[offset].ToString(); TagSizeRange = Doc.Range(ref missing, ref missing); TagSizeRange.Start = inputRange.Start + offset; TagSizeRange.End = inputRange.Start + offset + 1; TagSizeRange.Shading.BackgroundPatternColor = SizeColor; tagSizecount++; } if (tagSizecount == 8) { try{ TagSize = Convert.ToInt32(HEXStringEndianChanger(IDSizeValue), 16)*2; } catch { System.Windows.Forms.MessageBox.Show("Invalid Size Conversion @: " + TagSizeRange.Start.ToString()); } currentState = TagState.TagValue; } offset++; break; case TagState.TagValue: if (tagValuecount == TagSize) { tagIDcount = 0; tagSizecount = 0; tagValuecount = 0; IDSizeValue = ""; TagSize = 0; currentState = TagState.TagID; } else { if (isHexChar(inputCharArray[offset])) tagValuecount++; offset++; } break; } } }

[EndCode]

So yeah.... sorry about the ugly code, I did say I wrote it in less than an hour.

Anyway, I'm going to wrap this up with a quick summary on my thoughts of this:

Word is an awesome platform for doing relatively complex tasks with simple easy to write code. Even if you're not a developer who creates Super Cool Customized Office Projects for a living, you might still want to spend a little time getting to know some of the basic stuff. Being able to write these simple little tools may just make your life a little easier.

Thanks for reading.

Kris

Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxPower to the People.http://blogs.msdn.com/b/krimakey/archive/2008/02/22/power-to-the-people.aspx2008-02-22T06:43:00Z2008-02-22T06:43:00Z
I have some excellent news for any VSTO developers out there. We've released the first set of Power Tools. You can read more about them here and you can get them from here. Andrew Whitechapel's blog entry covers the tools at pretty good length. If you develop VSTO customizations, go there now, you won't regret it. Additionally I would like to take a moment to (gloat) bask in the fact that I had a direct hand in developing one of the tools. If you can guess which one accurately I'll tip my hat to you.

With some respect to that. If you're not reading Andrew's blog, you should be. He's one of those super smart people that really truly understands how VSTO works.

So, Power to the People!

With that I'm going to have to cut this entry short. I have been really really busy on super top secret stuff.

Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxDelayed.http://blogs.msdn.com/b/krimakey/archive/2008/02/10/delayed.aspx2008-02-10T04:39:00Z2008-02-10T04:39:00Z
I'm not prepared to talk about anything interesting this week. I've been busy with several things going on and haven't had time to do the neccasary thought and investigation. On a side note though, my team is hiring looking for new Testers and Developers. You can see a listing of relevant jobs at http://members.microsoft.com/careers/search/results.aspx?FromCP=Y&JobCategoryCodeID=&JobLocationCodeID=&JobProductCodeID=10019&JobTitleCodeID=10296,10299&Divisions=&TargetLevels=&Keywords=Business%20Apps&JobCode=&ManagerAlias=&Interval=50 if you are interested.

That's about all I have for now.

Thank you for reading.

Kris Makey

Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxBeing Pushy with VSTO ClickOncehttp://blogs.msdn.com/b/krimakey/archive/2008/02/02/being-pushy-with-vsto-clickonce.aspx2008-02-02T06:26:00Z2008-02-02T06:26:00Z
The other day I was in a meeting and it was mentioned that the new VSTO Deployment model didn't really support a "push" model. I've thought about this for a while and I have to disagree and agree. In software development "supporting" is really more of a Grey scale of difficulty. With enough effort any developer could reverse engineer something enough to replace, alter or extend any piece of software. It comes down to what degree of difficulty are you willing to go through (and how many assets you can use to implement something).

 So today I'm going to talk about how a crafty developer may implement a push model with ClickOnce. So lets get pushy:

First of all, a quick blurb about what a "push model" is: the basic idea is is that the central server pushes installation/updates out to a network of clients. In a simple push model we ignore factors such as offline status and assume all clients are always connected.

So we'll begin with the easiest "fakey" push model, Forced Update Checking.

How it's done: Set 'update interval' to 'always'

Advantages:

Because we're just sticking with "vanilla" VSTO ClickOnce here, it's very easy to change to a different update frequency, there is still a lot of flexibility to change the model in the future. Don't incur a large usage bubble by having all machines getting the bits at the same time. Offline status can be ignored, ClickOnce supports Offline running out of the box. It's super easy.

Disadvantages:

The performance implication of always checking for updates may not be appropriate to the solution (slower deployment servers, slower network connections or simply being unable to reach the server frequently can negatively impact load times). There is no way to enforce a non-working status if the solution can't check for updates (VSTO doesn't currently support the 'online only' style of ClickOnce deployment).

The next closest technique is sms enforced updating without update checking.

How it's done: Set 'update interval' to 'never' and use SMS to enforce an update installation via VSTO Installer.

Assumptions:

Obviously SMS access to all client machines is necessary, but also the administrator should ensure that all machines within the network have the prerequisites before forcing them to attempt installing the customization.

Advantages:

Reduced performance impact in between updates (because updates are set to never the clients don't incur the security and update check "penalty" at application startup). Allows for resource management (only pushing updates during off hours for example). Still relatively simple to implement (given availability of SMS control).

Disadvantages:

Large bubble of activity could potentially cause issues (high network traffic may cause errors if the the connection for individual clients degrades too much). Requires SMS (for smaller networks this may be overkill). May not be possible to enforce updates (if a machine can be taken offline such that SMS cannot guarantee it gets the update command).

My final idea for creating a push system involves creating an update enforcer.

How it's done: Set 'update interval' to 'never' and build/install a service to enforce update installation via VSTO Installer. The basic idea is that the enforcer service would either listen on a port or check occasionally for updates. Ideally in both cases updates would be delayed on the client machine if the customized application is actually currently running. It would be possible to disable any non-updated customizations with the update enforcer.

Assumptions:

Users will install update enforcer as a prerequisite. Developer has resources to build the update enforcer service mechanism.

Advantages:

Same reduced performance hit. Re-usability (given a generic enough implementation). Allows for update enforcement with a hard shutdown and allows for control of the offline scenario.

Disadvantages:

A developer has to implement the service.

As I said before, I believe VSTO ClickOnce does and doesn't support the push deployment model. Depending on the degree of closeness to an actual push model and the number of factors involved it is very possible to address many of scenarios that may require a push model. I think it would be very doable to create a generic 2 project solution that contains both the end client service and administrative controller for the update enforcer, i would be interested to know how many people are interested in such a technology.

I think that's about all I want to talk about today, I've been super busy this week with projects that I can't talk about and with Burnout:Paradise in my spare time. As always, I do respond to questions and comments posted.

Thank you for reading,

Kris

Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxStarting and Puttinghttp://blogs.msdn.com/b/krimakey/archive/2008/01/25/starting-and-putting.aspx2008-01-25T03:57:00Z2008-01-25T03:57:00Z
Because of the complexity and depth that installation stories can have it seems like it is very easy to get a little confused with terminology and how it maps to actual real world things. Additionally it seems like the varied nature of installation and setup stories has produced some excellent environment for confusion.

Today I'm going to talk a bit about the different between installers and bootstrappers and what it means specifically to our VSTO installation story. In previous posts I've mentioned basically 2 major methods for handling installation for VSTO objects. For the sake of clarity I will talk of these as the MSI method and the ClickOnce method.

In the ClickOnce method I clearly notate the 2 pieces: the published customization and the bootstrapper (the Setup.exe File). Specifically of interest is the Bootstrapper. The Bootstrapper handles pre-requisites for the customization. Basically the bootstrapper created in publishing a ClickOnce application is almost a stand-alone component. Without the customization it would in fact install all of the prerequisites, only failing when finally getting to the last step where it tries to install the customization itself.

In the past I've also talk a briefly about using Visual Studio's Windows Installer project to install customizations. The Windows Installer project will actually product a setup.exe file and an MSI file. The MSI file is essentially the same functional part as the published ClickOnce Customization. The setup.exe file is also a bootstrapper and is created in the same manner and essentially works the same way as with a ClickOnce Setup bootstrapper. For a VSTO developer this should be relatively good news since it means any work you do creating prerequisites for one is work that is directly applicable to the other.

So for future clarity: when I talk about bootstrappers I mean the Setup.exe file and when I talk about installers I will generally be talking about either VSTOInstaller.exe (executed against ClickOnce Manifests) or the MSI/Windows Installer file. You can think of the Bootstrapper as the piece that starts the process and the installer as putting the part into place.

In most cases my interests lie in the Installer world since that is where the "magic" of VSTO is. The bootstrapper technology is definitely good, but it's not as interesting of a topic for me.

On a side note, I suspect my topics for the next couple of weeks will be fairly short. I may break one of my bigger topics into multiple entries. I'm about to start on a project that isn't as directly related to VSTO or ClickOnce and as such the amount of mental bandwidth I will have to delve into the depths will be much lower.

For more "exciting" and strange ramblings, tune in next week.

Thank you for reading,

Kris

Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashxSearching for that special thing and some other hints.http://blogs.msdn.com/b/krimakey/archive/2008/01/17/searching-for-that-special-thing-and-some-other-hints.aspx2008-01-18T01:33:00Z2008-01-18T01:33:00Z
I haven't talked much about what I do here at Microsoft. To be honest I'm not going to go too far into any details about what I am doing but I think it'll be okay to talk about what I did do (up until we shipped VSTO 2008).

I am and SDET which basically means I test the product. Really I spend a lot of time trying to make the product better. Sometimes I'm testing the product and sometimes I'm doing other things (such as reviewing documentation). But it also means I tend to spend a lot of time "thinking like a customer". That is, I make a great deal of effort to do things and see things from the perspective of an outsider. An example is that I often try to find things out via our external communication methods before I go and ask someone here who actually built the thing I'm trying to use. So we're back to what I was talking about in the post title... I always have a hard time finding the articles (many that I know exist) about the product features I'm working with. I'm always looking for that special something. After talking with one of our insiders who works on MSDN I learned an interesting piece of advice when searching for VSTO related articles:

Start with Visual Studio Tools for Office or Visual Studio Tools for the Office System avoid using VSTO when searching for MSDN articles.

My biggest mistake is that I often start with VSTO. I believe it's a product of working on VSTO so completely that I often get searches that look like this:

When really what I want are searches that look like this:

You'll notice that the highlighted Article from the first Search is much lower than the one from the second search. Another particular thing about this is that you'll get more relavant hits this way (all of the ones listed in the second search image are very relevant articles).

Certainly I feel this was a hugely helpful thing to know, and I hope it helps you reduce your knowledge searching times also.

Now to completely switch gears....

There have been questions (there always are questions, I like questions, feel free to send me your relevant questions) around how to change the friendly name of a VSTO customization and how to change the name that gets displayed in the Add/Remove Programs dialog.

To be honest, there currently isn't UI to set either of these directly, however both of these values are created by using the Assembly name (the Main VSTO customization Assembly). You can set the Assembly name in the VSTO Project Properties (Right Clicking the Project).

The limitations imposed by the file system are evaluated against this value so you should be okay with whatever value VS lets you put here. There is a minor Caveat though. If you use spaces in the name you have to use a cannonicalized URI for the file path. Example: my I publish "My Project" to C:\foo. to install the customization with VSTOInstaller (using the command line) I would have to use the following command:

"C:\Program Files\Common Files\Microsoft Shared\VSTO\9.0\VSTOInstaller.exe" /i file:///C:\foo\My%20Project.vsto

The need to use URI's occurs for any case in which the path to the deployment manifest uses spaces. For most user scenarios this is a complete non-issue since (I believe) most users will be using the bootstrapper or the Shell Handler (Clicking the .vsto files) to install VSTO customizations. In both of these scenarios the Mechanisms that eventually call into VSTOInstaller are using properly cannonicalized URI's. The main cases this might be a problem is when the developer has created a custom bootstrapper that calls VSTOInstaller in order to kick off the customization installation.

So the lesson is: If you're going to build custom bootstrappers that use VSTO ClickOnce installation, use URI's.

I think that will be all I cover today. Feel free to contact me with question or to post them directly to the relate entry.

Thank you for reading.

Kris

Kris Makey - MSFThttp://blogs.msdn.com/krimakey/ProfileUrlRedirect.ashx