Creating a recipe that inserts 2 files in different folders

Topics: General Discussion Forum, July and December Releases Forum
Apr 28, 2007 at 12:03 AM
Hi,

I've been fighting with this for a while to no avail. What I'm trying to do is add context sensitive menu option to add some additional files to the selected project. The problem comes with needing to add files to different folders and the creation of the folders. I can code a recipe to add the files (generated using t4 templates) to the root folder without any problems.

The challenge is to generate the folders and then add a file to the root and then a file to the new folder.

Currently I bind the recipe to the project in the vstemplate file for the project (as below) and in this code I have to set the target. But I have more than 1 target.

<WizardData>
<Template SchemaVersion="1.0" xmlns="http://schemas.microsoft.com/pag/gax-template">
<References>
<RecipeReference Name="AddErrorHandlingComponents" Target="/" />
</References>
</Template>
</WizardData>

The AddErrorHandlingComponents recipe is then defined in the ASMX Guidance Package.xml file. The recipe uses the GenerateClass and AddClass actions to insert the t4 template files in the project.

<Action Name="GenerateClass" Type="Microsoft.Practices.RecipeFramework.VisualStudio.Library.Templates.TextTemplateAction, Microsoft.Practices.RecipeFramework.VisualStudio.Library" Template="T4\ErrorHandling.cs.t4" >
<Input Name="TargetNamespace" RecipeArgument="TargetNamespace" />
<Output Name="Content" />
</Action>
<Action Name="AddClass" Type="Microsoft.Practices.RecipeFramework.Library.Actions.AddItemFromStringAction, Microsoft.Practices.RecipeFramework.Library" Open="true">
<Input Name="Content" ActionOutput="GenerateClass.Content" />
<Input Name="TargetFileName" RecipeArgument="TargetFile" />
<Input Name="Project" RecipeArgument="CurrentProject" />
</Action>

Any ideas would be much appreciated.

Geordie.


Developer
Apr 30, 2007 at 11:08 PM
You have an action to do that (create the folder and add the specified item to that folder.
You may use the AddClass but with the action that is in the Extensions library "AddItemFromStringToProjectItemByNameAction".
In this case, you may define the action as follows:
<Action Name="AddClass" Type="Microsoft.Practices.RecipeFramework.Extensions.Actions.VisualStudio.AddItemFromStringToProjectItemByNameAction, Microsoft.Practices.RecipeFramework.Extensions" Open="true" ItemName="NameOfYourFolder">
<Input Name="Content" ActionOutput="GenerateClass.Content" />
<Input Name="TargetFileName" RecipeArgument="TargetFile" />
<Input Name="Project" RecipeArgument="CurrentProject" />
</Action>
This action should create the folder specified in ItemName argument and add the deserialized file from "Content" arg to the created folder.

Charly
May 1, 2007 at 5:07 AM
Hi Charly,

Thanks for responding to my question. I tried what you suggested and it worked if I placed the file into a directory one level down. When I tried to insert a file 2 directories down it would not accept the directory name (format 'DirA\DirB'). Is there a trick to entering paths?

<Action Name="AddClass" Type="Microsoft.Practices.RecipeFramework.Extensions.Actions.VisualStudio.AddItemFromStringToProjectItemByNameAction, Microsoft.Practices.RecipeFramework.Extensions"
Open="true" ItemName="DirA\DirB">

This results in an illegal character error when the recipe is run.

Any ideas?

Geordie
Developer
May 2, 2007 at 9:59 AM
For this scenario, you should pass the last folder name like ItemName="DirB” and create previously the parent folders with the following recipe:
<Action Name="AddClass" Type="Microsoft.Practices.RecipeFramework.Extensions.Actions.VisualStudio.AddItemToProjectItemByNameAction, Microsoft.Practices.RecipeFramework.Extensions" TargetFolderName="DirA">
     <Input Name="Project" RecipeArgument="CurrentProject" />
</Action>
So you should add this action before "AddItemFromStringToProjectItemByNameAction" for as many parent folders as you want and after that then you can add the last child folder along with the generated/updated file.

Charly
May 2, 2007 at 7:54 PM
Thanks Charly,

I'll give it a go tonight.
May 3, 2007 at 5:20 AM
Hi Charly,

Just been trying the solution you suggested and I didn't get very far. When I tried to run the recipe with the action you suggested above an exception was thrown becouse in the version of the service factory that I have the action 'AddItemToProjectItemByNameAction' does not exist. Is there a more current version or addon actions? I'm pretty sure I have the last version 2 release.

When I looked into the available actions in the same namespace, as the one above, I found an action called 'AddProjectItemsFromDirectoryAction'. I thought this might work if it allowed me to add a the directory structure with the file inside Although I did get the action to run with out blowing up the directories and folder did not appear in the project?

<Action Name="AddWebRefs" Type="Microsoft.Practices.RecipeFramework.Extensions.Actions.VisualStudio.AddProjectItemsFromDirectoryAction, Microsoft.Practices.RecipeFramework.Extensions"
Open="false" SourceFilePath="CatalystFiles" copy="true">
<Input Name="TargetProject" RecipeArgument="CurrentProject" />
</Action>

Any new thoughts

Geordie
Developer
May 3, 2007 at 1:37 PM
The issue with that recipe (AddProjectItemsFromDirectoryAction) is that the SourceFilePath should be a folder fullpath and therefore the relative path that you set will not work. On the orther hand, this folder is assumed to exist, otherwise it won't be created and you will get the same result (no files added).
Regarding the fromer action (AddItemToProjectItemByNameAction), that was my mistake because it is actually included in the Extensions library version GAX Extension Library newer than the one included in WSSF V2.
Perhaps the best bet might be to download that version of Extensions and copy the "AddItemToProjectItemByNameAction" action to the same folder in the Extensions library included with WSSF V2. Then you should be ready to run the recipe as described in my previous post.

Chalry
May 3, 2007 at 5:08 PM
Hi Charly,

I have it working..

I've added the code below for future reference for other people working through a similar problem.

<Action Name="GenerateClass" Type="Microsoft.Practices.RecipeFramework.VisualStudio.Library.Templates.TextTemplateAction, Microsoft.Practices.RecipeFramework.VisualStudio.Library"
Template="T4\File.cs.t4" >
<Input Name="TargetNamespace" RecipeArgument="TargetNamespace" />
<Output Name="Content" />
</Action>
<Action Name="AddFolder1" Type="Microsoft.Practices.RecipeFramework.Extensions.Actions.VisualStudio.AddItemToProjectItemByNameAction, Microsoft.Practices.RecipeFramework.Extensions"
TargetFolderName="DirA">
<Input Name="Project" RecipeArgument="CurrentProject" />
</Action>
<Action Name="AddFolder2" Type="Microsoft.Practices.RecipeFramework.Extensions.Actions.VisualStudio.AddItemToProjectItemByNameAction, Microsoft.Practices.RecipeFramework.Extensions"
TargetFolderName="DirB" ParentItem="DirA">
<Input Name="Project" RecipeArgument="CurrentProject" />
</Action>
<Action Name="AddClass" Type="Microsoft.Practices.RecipeFramework.Extensions.Actions.VisualStudio.AddItemFromStringToProjectItemByNameAction, Microsoft.Practices.RecipeFramework.Extensions"
Open="false" ItemName="DirB">
<Input Name="Content" ActionOutput="GenerateClass.Content" />
<Input Name="TargetFileName" RecipeArgument="TargetFileCS" />
<Input Name="Project" RecipeArgument="CurrentProject" />
</Action>

Thanks again for your help Charly.

Geordie
Developer
May 4, 2007 at 2:43 AM
Well done Geordi!! ,and glad I could help.