locked
Visual Studio 2010 variables not recognized when using ITextTemplating ProcessTemplate from within an AddIn RRS feed

  • Question

  • I've created a Visual Studio 2010 AddIn (C#) to automate processing several T4 templates within a solution.  The problem I'm seeing is that if I manually Run Custom Tool from within the IDE on any of the templates they work fine, BUT if I run them programmatically from within an AddIn then my assembly references that are using Visual Studio variables such as $(SolutionDir) fail with an Exception.  The Exception is:

    The host threw an exception while trying to resolve the assembly reference 'S(SolutionDir)\bin\Debug\myassembly.dll'. The transformation will not be run.  The following Exception was thrown: System.IO.FileLoadException: The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047) at System.Reflection.AssemblyName.nInit(RuntimeAssembly& assembly, Boolean forIntrospection, Boolean raiseResolveEvent)
       at System.Reflection.AssemblyName..ctor(String assemblyName)
       at Microsoft.VisualStudio.TextTemplating.GlobalAssemblyCacheHelper.GetLocation(String strongName)
       at Microsoft.VisualStudio.TextTemplating.VSHost.TextTemplatingService.ResolveAssemblyReference(String assemblyReference)
       at Microsoft.VisualStudio.TextTemplating.Engine.ResolveAssemblyReferences(ITextTemplatingEngineHost host, TemplateProcessingSession session)

    The code I'm using within the AddIn to programatically process the templates is (m_applicationObject is the application object passed into OnConnection and solutionName and ttGenerationFile are variables I pass in):

     

    m_applicationObject.Solution.Open(solutionName);

    TextReader tr = new StreamReader(ttGenerationFile);

     

     

    string content = tr.ReadToEnd();

     

     

    IServiceProvider serviceProvider = new ServiceProvider((Microsoft.VisualStudio.OLE.Interop.IServiceProvider)m_applicationObject.DTE);

     

     

    ITextTemplating tt = serviceProvider.GetService(typeof(STextTemplating)) as ITextTemplating;

    tt.ProcessTemplate(ttGenerationFile, content,

     

    this, null);

    If I hardcode the paths in the assemble reference within the template like so it works:

    <#@

     

    assembly name="c:\library\bin\Debug\myassembly.dll" #>

    So my Question is why does this work manuall from within the IDE/Solution, but not programatically?

    Thanks

    Tuesday, February 22, 2011 10:05 PM

All replies

  • Hi LightningStrikes,

    Thanks for your post.

    It seems that this issue happens when you try to load the assembly,

    I just wonder if it is a typo in your post?

    The host threw an exception while trying to resolve the assembly reference 'S(SolutionDir)\bin\Debug\myassembly.dll'. The transformation will not be run. The following Exception was thrown: System.IO.FileLoadException: The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047) at System.Reflection.AssemblyName.nInit(RuntimeAssembly& assembly, Boolean forIntrospection, Boolean raiseResolveEvent)

    The place where I highlighted should be a "$" but not "S",

    If it is just a typo, please let me know, and I will look into this issue again.

     

     

    Best Regards,

    Ziwei Chen

     

     


    Ziwei Chen [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, February 24, 2011 7:01 AM
  • Yes, it is just a typo in my post when I was typing in the exception, I'm using the $ sign.  Interestingly, if I use an environment variable %some environment variable%, it gets properly processed.  The problem is specific to Visual Studio variables.  Thanks for looking at this
    Thursday, February 24, 2011 3:50 PM
  • Hi LightningStrikes,

    Thanks for your feedback.

    Normally the assembly binary should be in the

    $(ProjectDir)\bin\Debug\myassembly.dll'

    you can check the $(SolutionDir) value in the way

    Right Click project node->Properties->Click on a text box which accept macros->Click Edit

    you can check all macros' value then

    and see if the assembly exist in that directory.

    Hope my reply helps.

     

     

    Best Regards,

    Ziwei Chen

     

     


    Ziwei Chen [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Friday, February 25, 2011 3:49 AM
  • Hi Victor,

     

    Thanks for the response.  I don't believe I was clear enough with the problem based on your response.  The macros for the project all exist.  My dll is in fact in the directory.  If I Run Custom Tool within the project to execute the template file everything works fine (meaning the macros get evaluated properly).  The problem is when processing the template via the Templating Engine API, it does not properly evaluate the macros whether I use $(SolutionDir), $(ProjectDir), or any other variable.  If you look at my earlier example, I'm opening the solution from within an AddIn and then programmatically calling ProcessTemplate.  It's as if the Templating Engine picks up values for the macros not from the solution that was opened, but somewhere internal to itself.  Again it all works fine if I manually right click on the .tt and run custom tool, so I have everything configured properly.  It's the Templating Engine ProcessTemplate call that appears to have the problem.  Is there a way to determine how/where it is looking for it's macro values as it does not appear to be looking in the solution that is open when it executes?

    Thanks

    Friday, February 25, 2011 5:28 AM
  • Hi again,

    Thanks for your clarification.

    I got to know your issue better now.

    I did some research and noticed that, then you run it via Custom Tool, the Generate() method obtains the Converted File Content/Path without macro, but you don't have this step in your addin code.

    I don't know if there are public services to help convert macros, so I think the best approach is to run custom tool in your addin.

    Could you please let me know why do you expect to do it in addin, maybe we can find some reasonable workaround.

     

     

    Best Regards,

    Ziwei Chen

     

     


    Ziwei Chen [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Friday, February 25, 2011 9:19 AM
  • Thanks Victor

    From your reply, I'm not sure that I completely understand why Custom Tool works and ProcessTemplate in the AddIn doesn't.  Something in the Custom Tool process is converting macros.  Why doesn't ProcessTemplate convert macros?  It does convert environment variables, so that doesn't make much sense to me.  Isn't the ProcessTemplate supposed to be the programmatic way of doing Run Custom Tool? This sounds like a bug in ProcessTemplate...

    Also what do you mean that my best approach is to run custom tool in my addin?  I thought that is what I was doing with the ProcessTemplate call.  Can you give me an example of how I would run custom tool from within an Addin?

     

    A correction to this thread... Environment variables are not being processed either, I thought they were, but when I decided to just go down that route as a solution found out that only Custom Tool parses them.  So I'm really stuck right now as I can't hardcode path names.

    Friday, February 25, 2011 5:42 PM
  • Hi, ever solved this issue?

    I've got the same problem.

    Thursday, December 20, 2012 2:50 PM