Dynamic Host Object Model

Latest post 03-29-2008 11:40 AM by Melody. 14 replies.
  • 03-26-2008 4:22 PM

    • Terry
    • Top 10 Contributor
    • Joined on 05-10-2006
    • Posts 90

    Dynamic Host Object Model

    We are in the process of evaluating VSTA 2.0 and a key part of it's viability is the option to extend the host object model on the fly as users add new items in the host application.  We've managed to make a good deal of progress through repeated application of head to wall with force.  Unfortunately the breakthroughs are steadily becoming more difficult and the time has come to get some help.

    So far we have the host app opening the IDE, creating a new project from a template and once that project is modified and saved it will load the add-in and events from the host fire as expected (he said as though it didn't take a week to get that far).

    We are now trying to manipulate the host object model.  The issue at hand is the HostObjects.Add() method.  It's of the rather consistent opinion that my type identifier (see code below) isn't "valid".  Unfortunately I have no idea what consitutes a valid identifier.  It's definately keyed correctly and it's in my proxy OM.xml and Proxy.cs.  I've also checked the .xml and .cs syntax against the ShapeApp.IShape in the sample .xml and .cs and the declarations are identical, except for the name of course.

    item.HostObjects.Add("bunny", "PGT.Win.Component.ProductConfiguration.Customization.IPricingRule", "Customization" & "$" & "bunny")

    Once I get the code to work, I'll need to understand how the Addin Developer is supposed to access objects that are added.  I'm assuming they could go through the GetHostObject() method and pull by name, but that's gonna be ugly unless I find  way to insert property wrappers to make it more user-friendly.

    Thanks in advance for your input.

  • 03-27-2008 10:17 AM In reply to

    • Terry
    • Top 10 Contributor
    • Joined on 05-10-2006
    • Posts 90

    Re: Dynamic Host Object Model

    Some minor progress last night.  I was able to make it "work" by passing in "System.Text.StringBuilder" instead of my object, but that doesn't really answer the question.  Rather, it re-inforced my curiosity about how to access these little monsters once they've been added to the collection.  I tried to get my String Builder usig the following code, but it won't let me cast it into a string builder and the following code throws an error on the last line talking about being unable to cast from a transparent type:

    Dim o As Object = Me.GetHostObject("System.Text.StringBuilder", "bunny")

    'This line passes "StringBuilder" to my test method

    Me.TestMethod(o.GetType.ToString)

    'This line throws a cast error:

    '"Unable to cast transparent proxy to type 'System.Text.StringBuilder'."

    Dim s As System.Text.StringBuilder = CType(o, System.Text.StringBuilder)

    It seems that I'm still lacking a fundamental understanding of how these host objects are supposed to work.

  • 03-27-2008 12:51 PM In reply to

    Re: Dynamic Host Object Model

    Hi Terry!

    Well, you're making great progress!

    Regarding your first post, do you get an error for an "invalid type identifier" when you call item.HostObjects.Add() or somewhere else in the code? I tweaked the DPM sample changing the type IShape to IShapeXX and the Add still worked. The item (ex. Circle1) appears in the intellisense, but the IDE can't resolve its type to show its methods and properties and the compile fails with an unknown type. So, I need a little more information to understand why there's an error when you add "bunny": what is the exact error, when does it occur, maybe a bigger code snip? 

    When you make an object a host object, the person writing VSTA code can use the name of the host object in his or her code - something like Circle1.Color = Blue. The item appears in the intellisense and makes it really easy for customizers. When the compiled add-in is loaded, VSTA resolves that item (Circle1) to the object in the application using the type and the cookie in the call to GetHostObject.

    Have you looked at the DPM sample? It allows you to add new shapes to the drawing and then you can look in the VSTA IDE and that shape appears in intellisense for that drawing and you can use the shape in the code. Also, I found it enlightening to set a break point in GetHostObject and watch it get called when you load the add-in to the application.

    I think DPM is really exciting technology. I'm glad you are digging into it!

    Best regards,
    Rebecca 

  • 03-27-2008 1:14 PM In reply to

    • Terry
    • Top 10 Contributor
    • Joined on 05-10-2006
    • Posts 90

    Re: Dynamic Host Object Model

    As fate would have it, I notied this key sentence in the documentation just about the same time you were writing your post:

    "When you add a host object, a field is automatically added to the host item class."

    Of course I can see that once I went looking for it.  Normally my strange names (like bunny) make those types of things easier to notice, even if you aren't looking for them but not this time I guess.

    After a solid day of experimenting, I've resolved the issues with using my own type for the HostObjects.Add (see below).  For now, I'll assume the StringBuilder is based on something that just won't work with the pipeline.  Anyhow, on to my big discovery about the "Invalid Type" error...

    So, what's in a name?  Evidently a lot if you pick the wrong one.  Come to find out that name of your AddIn (i.e. the class file name) which in my case was "Customization" cannot appear as a namespace element ANYWHERE in your Type that is passed in the HostObjects.Add() method.  Go Figure!

    For example, these didn't error:

    -------------------------------------------

    Dim item As IVstaHostItem = hostAdapter.ProjectHostItems("Customization").ProgrammingModelHostItem

    item.HostObjects.Add("bunny", "PGT.Win.Component.ProductConfiguration.Custom", "Customization" & "$" & "bunny")

    item.HostObjects.Add("bunny", "PGT.Win.Component.ProductConfiguration.Customizatio", "Customization" & "$" & "bunny")

    item.HostObjects.Add("bunny", "PGT.Win.Component.ProductConfiguration.Customizationbad", "Customization" & "$" & "bunny")

    --------------------------------------------

    Notice they all avoid using a namespace element called "Customization".  Then i tried this, which is just one character off one of the examples above, and it threw the error:

    ------------------------------------------

    Dim item As IVstaHostItem = hostAdapter.ProjectHostItems("Customization").ProgrammingModelHostItem

    item.HostObjects.Add("bunny", "PGT.Win.Component.ProductConfiguration.Customization", "Customization" & "$" & "bunny")

    ERROR--> "The following is not a valid identifier: PGT.Win.Component.ProductConfiguration.Customization. Parameter name: type"

    --------------------------------------------

    Now comes the interesting part.  Since I have nothing better to do, I started trying things.  Eventually I changed the base name of my Addin from "Customization" to "BaseCustomization".  BTW, also had to change that hidden Cookie setting in the ProjectGen.exe Template.xml file.  After I changed all the appropriate places in code that were looking for this cookie and re-compiled / registered / blah / blah.  It worked just fine.

    Maybe the real issue is the Cookie name, or something else, but I can easily re-produce the error by passing a namespace like this:

    item.HostObjects.Add("bunny", "Choke.On.This.BaseCustomization.Anything", "BaseCustomization" & "$" & "bunny")

    Notice that nothing matters except that I used my new Addin "Name" (BaseCustomization) as a namespace element.  I'm sure there's some code in the runtime that's doing some sort of funky check that catches this and throws that valid identifier error... just wish it had been a little smarter then doing a simple .inString type check for the name.

    Oh well, as an aside, I was able to work around this behavior by passing in a Bogus Namespace (not using the Addin Name as an element) and then manually going into the DTE's designer.vb file and changing the namespace back by hand.  Once that's all done you can compile and run just fine.  Of course that wasn't an acceptible solution but it really honed in on where the true issue is ---> HostObjects.Add().

    Until next time...

     

  • 03-27-2008 10:08 PM In reply to

    Re: Dynamic Host Object Model

    In my test, I tweaked the DPM sample and changed the type to nonsense just to see what would happen and in those tests, the HostObjects.Add() worked with no error message. (the phony type was a problem further down the road, but the Add worked) So, I agree, it is very strange that we are seeing such different results.

    I'm working with a C# sample and using VS 2008 with the beta version of VSTA. It looks like you've got a VB .NET application - what version of VSTA are you using?

    I can reproduce the "Unable to cast transparent proxy to type 'System.Text.StringBuilder" error pretty easily. I return a StringBuilder from GetHostObject and I add a "StringBuilder" host object to the project item. However, StringBuilder it is not in the proxy at all. I'm pretty sure that is the problem. I'll tweak the test to see what happens when StringBuilder is part of the proxy - more on that shortly. 

    Rebecca

  • 03-27-2008 11:01 PM In reply to

    Re: Dynamic Host Object Model

    Hi Terry,

    Interesting sleuthing! Something very odd is going on...

    Again, I tweaked the DPM sample to test. I made the cookie include a segment in the namespace. Is this the scenario that consistently produces an error in your application?

    item.HostObjects.Add(s.Name, "Microsoft.VisualStudio.Tools.Applications.Samples.ShapeApp.IShape", "Samples" + "$" + s.Name);

    Naturally, it just works. So, I tried this to see if there was something magical/cursed about the word "Customization":

    item.HostObjects.Add(s.Name, "Microsoft.VisualStudio.Tools.Applications.Customization.IShape", "Customization" + "$" + s.Name);

    That works, too. Hmmm.

    Are you using the CTP or the beta VSTA? I'm using the beta.

    Rebecca

  • 03-28-2008 8:30 AM In reply to

    • Terry
    • Top 10 Contributor
    • Joined on 05-10-2006
    • Posts 90

    Re: Dynamic Host Object Model

    I'm running the 2.0 Beta (I think).  I do have the 1.0 release version installed also.  Not sure if that's a risky situation or not.

    Now on to bigger and better things!  For organizational purposes, I'm going to start a new thread for my next questions about manipulating the addin code files.

    Thanks.

     

     

  • 03-28-2008 9:08 AM In reply to

    • Melody
    • Top 10 Contributor
    • Joined on 04-26-2007
    • Syracuse, NY
    • Posts 248

    Re: Dynamic Host Object Model

    Terry,

       Having both VSTA v 1 and v 2 installed isn't a problem but there are a few things to keep in mind.

    1. Command prompts- when using command prompts to run vsta commands (such as setup, to launch the IDE, or use ProxyGen or ProjectGen) change directories to ensure that the correct version is used.
    2. Add-in Organization- if a host is being/has been used with both VSTA v 1 and v 2, use different values for the AppName or UserFileFolder registry entries between VSTA v 1 and v 2 to ensure that VSTA v 1 add-ins aren't loaded by VSTA v 2 and vice versa.
    3. If you are using Visual Studio 2005, here is a link to concerning using Visual Studio 2005 with VSTA v 2.

    Thanks,

       -Melody

     

  • 03-28-2008 9:17 AM In reply to

    • Terry
    • Top 10 Contributor
    • Joined on 05-10-2006
    • Posts 90

    Re: Dynamic Host Object Model

    Thanks.  I'll keep that in mind.  I'm sure I've stumbled over some pathing issues but now that I've refined my batch files for repeating the build / registration process things are ok.

    Is it safe to uninstall 1.0 and expect the 2.0 BETA to continue working?

  • 03-28-2008 9:32 AM In reply to

    • Melody
    • Top 10 Contributor
    • Joined on 04-26-2007
    • Syracuse, NY
    • Posts 248

    Re: Dynamic Host Object Model

    Uninstalling VSTA v 1 doesn't affect VSTA v 2. 

    To completely expung VSTA v 1, here's what you want to do:

    1)  Remove project templates registered with VSTA v 1 and Visual Studio 2005 (here's a how to unregister project templates).

    2)  Use Add and Remove Programs to remove VSTA and the VSTA SDK.

    3)  Remove the folder hive %Program Files%\Visual Studio 2005 Tools for Applicaitons SDK if Add\Remove Programs didn't.

    4)  Remove any host files from %My Documents%, for example if you used the VSTA v 1 samples remove the ShapeAppCSharp and ShapeAppMFC files from %My Documents% along with any other host files.

    5)  Remove the samples if you used them, these should be located at %SystemDrive%\ShapeAppSamples.

    6)  Remove registry entries for VSTA v 1 hosts under HKey_Local_Machine\Software\Microsoft\VSTAHost and VSTAHostConfig.

    7)  Remove any host's proxy assememblies from the GAC.

    8)  Remove any environmental variables for VSTA v 1 or replace them with variables for VSTA v 2.

    *Here's a link for more info on Expunging VSTA*

    Please let me know if you have any questions.

    Thanks,

       -Melody

  • 03-28-2008 9:33 AM In reply to

    • Gary
    • Top 10 Contributor
    • Joined on 07-13-2006
    • Posts 320

    Re: Dynamic Host Object Model

    Abstract:

    In Side-bySide install, VSTA v 2, ShapeAppCSharp sample add-in projects reference the VSTA v 1 proxy assembly

     

    Symptom:

     

    When ISV compiles the ShapeAppCSharpAppAddIn in the basic shapes sample add-in project they get this error:

    Error 1 The type or namespace name 'ApplicationEntryPoint' does not exist in the namespace 'Microsoft.VisualStudio.Tools.Applications.Samples.ShapeApp' (are you missing an assembly reference?) C:\ShapeAppSamples\ShapeAppBasicCSharp\sample addIns\CSharp\AppLevel\SampleAppAddIn.Designer.cs 16 103 ShapeAppCSharpAppAddIn

    There is similar problem in other samples, ie: Dynamic shapes sample ('DocumentEntryPoint')

     

    Repro Steps:

     

    1.          Create machine with VSTA 1.0 and VSTA 2.0 installed side by side.

    2.          Install VSTA v 2, ShapeAppCSharp sample

    3.          Open v2 ShapeAppCSharp sample add-in project and build.

    4.          Build fails due to incorrect proxy assembly reference in the add-in project.

     

    Diagnosis:

     

    ProjectGen creates the project templates with an indeterminate  reference to the proxy like this in shapeappcsharpappaddin.csproj:

     

            <Reference Include="ShapeAppCSharpProxy" />

     

    As a result, VSTA v 2 add-ins projects resolve the ShapeAppCSharpProxy reference to the VSTA v 1 reference if it is available.

     

    The VSTA v 1 sample add-ins and new projects resolve to the right reference

    VSTA v 2 sample add-in resolves the ShapeAppCSharpProxy reference to the VSTA v 1 sample proxy

    Apparently the projects are both just grabbing the first reference encountered  with the name ShapeAppCSharpProxy from the GAC.  The proxy reference is ambiguous.

     

    Impact:

     

    ISVs must properly create vNext proxy assemblies and project templates so that the end users of their application/VSTA do not encounter a problem building their add-in projects, new and existing, due to the project referencing the wrong version of a proxy assembly.

    Renaming the proxy assembly for each version is not a desireable solution, from a maintenance perspective, but versioning the assembly is.

     

     

    Possible resolution:

     

    Using the SDK sample addin project shapeappcsharpappaddin.csproj  as an determinate example, we'll add Version attribute to the assembly reference:

     

    shapeappcsharpappaddin.csproj, version 1 proxy assembly:

    <Reference Include="ShapeAppCSharpProxy, Version=1.0.0.0 />

    shapeappcsharpappaddin.csproj, version 2 proxy assembly

    <Reference Include="ShapeAppCSharpProxy, Version=2.0.0.0 />

     

    SDK sample addin projects ought to include more of the assembly attributes.  At least the version number.  The sample project templates can be altered manually and re-installed:

     

    To remove project templates for VSTA v 1:

    1)      Open the HKey_Local_Machine\Software\Microsoft registry hive and locate the VSTAHost and VSTAHostConfig keys.  Expand these hives and locate the <HostID> key.  (Right click and select export to save a copy of the original registry settings for the host.)

    2)      In the VSTAHostConfig\<HostID> key, remove the values for the entries ProjectTemplatesLocation, VSCSProjectTemplatesLocation, and VSVBProjectTemplatesLocation.

    3)      Delete the VSTAHost\<HostID>\8.0 registry key.

    4)      From a command prompt, change the directory to %Program Files%\Microsoft Visual Studio 8\Common7\IDE and run the vsta setup command for the host.

    cd "C:\Program Files\Microsoft Visual Studio 8\Common7\IDE"

    vsta /hostID <hostID> /setup

    Further information:

     

    Even without a new version number, the ShapeAppCSharpProxy  reference in the exsiting shapeappcsharpappaddin.csproj  can be distinct enough by specifying the unique PublicKeyToken

    <Reference Include="ShapeAppCSharpProxy, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3c3c0c46dd27dbcf" />

     

    There are two other attributes that ISVs might wish use to reference proper proxy assembly in their projects:

     

    1.  If version-specific proxy assemblies are installed SxS in the GAC, they could use the FusionName.

    2.  For a SxS proxy assembly installed to a known ISV/product location, they can provide a HintPath to the correct assembly location.

     

    For example:

    <Reference Include="ShapeAppCSharpProxy">

      <Name>ShapeAppCSharpProxy</Name>

      <Aliases>ShapeApp Automation Library</Aliases>

      <HintPath>C:\Program Files\ISVName\ShapeAppCSharpProxy\Common\VSTA\ShapeAppCSharpProxy.dll</HintPath>

      <FusionName>ShapeAppCSharpProxy, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3c3c0c46dd27dbcf</FusionName>

      <SpecificVersion>True</SpecificVersion>

      <RequiredTargetFramework>3.5</RequiredTargetFramework>

    </Reference>

     

  • 03-28-2008 12:54 PM In reply to

    • Terry
    • Top 10 Contributor
    • Joined on 05-10-2006
    • Posts 90

    Re: Dynamic Host Object Model

     

    Thanks.  Since we won't be using the 1.0 for anything, I'm going to clean it all out before moving ahead on my actual production design and development.

     

  • 03-28-2008 2:10 PM In reply to

    Re: Dynamic Host Object Model

    I think you're wise to uninstall VSTA 1.0 - especially since you're not using it.

    I had an idea about the bizarre behavior of HostObjects.Add() that you're seeing. I'm trying to reproduce the error using the C# sample, but your application is VB. NET. So, I am wondering if proxygen did something "different" (ie wrong) when creating the proxy from your VB .NET application. This is just a wild guess, but definitely something we need to look into; proxygen had trouble with VB in earlier versions. However, given that we can use completely bogus type names for the type argument, I'm not sure that Add even uses the proxy to type check. Very bizarre. Would you be willing to send us your proxy .xml and .cs files - maybe there is a clue in there??

    Thanks!
    Rebecca

  • 03-29-2008 8:57 AM In reply to

    • Terry
    • Top 10 Contributor
    • Joined on 05-10-2006
    • Posts 90

    Re: Dynamic Host Object Model

    Sure thing.  That same thought did occur to me at a more basic level and I carefully compared a couple class elements between my proxy and one of the Sample Apps and didn't see anything, but then I didn't really look at the file in total.  Let me know where to forward them...

     

    Thx.

  • 03-29-2008 11:40 AM In reply to

    • Melody
    • Top 10 Contributor
    • Joined on 04-26-2007
    • Syracuse, NY
    • Posts 248

    Re: Dynamic Host Object Model

    Terry,
       You can submitt files to vstasupport@summsoft.com.

    Thanks!
       -Melody