4
votes

I have a number of custom Item and Project Templates for Visual Studio 2010. I have build a VSIX Package that can be used to deploy these extensions to multiple developer's machines.

I am now creating a custom MSBuild Task that will be required for a new Item Template.

In my local project, I can get this to work by putting in a hard-coded path in the project file:

But this does not work when the VSIX package is deployed to the 'dev' Visual Studio instance. Visual Studio just reports that the CustomBuildTask.dll cannot be found.

Where does the VSIX deploy the DLL? Is there an MSBuild %(path) variable I can use to find the DLL on the other machines, or does each user have to manually copy the DLL and/or place a global ".tasks" file into their Visual Studio installation?

NOTE: There is no VSIX content type for MSBuild tasks the way there is for Item and Project Templates. I have tried "VS Package", "MEF Component" and "Custom Extension Type" - and none appear to work.

2
After a full-drive search, I found my DLL at: C:\Documents and Settings\<userid>\Local Settings\Application Data\Microsoft\Visual Studio\10.0Exp\Extensions\<VSIX Author>\<VSIX Product Name>\<VSIX Version>\MyCustomTask.dll This appears to be where the VSIX deployed the DLL, but I cannot find an MSBuild variable to use in the UsingTask AssemblyFile attribute.Jeff B

2 Answers

1
votes

I don't believe you can do this, since VSIX packages can't install files in arbitrary locations, and the msbuild task would need to go in an msbuild folder.

0
votes

The solution for visual studio 2017/2019, which would have probably worked in 2010 ( as Microsoft.VisualStudio.TemplateWizard was available then ), is to create a wizard and to set the path to the extension install location in the replacements dictionary and use the replacement in the template with the UsingTask.

public class ProjectLocationWizard : IWizard
{
    public void BeforeOpeningFile(ProjectItem projectItem)
    {
    }

    public void ProjectFinishedGenerating(Project project)
    {
    }

    public void ProjectItemFinishedGenerating(ProjectItem projectItem)
    {
    }

    public void RunFinished()
    {
    }

    public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams)
    {
        var wizardDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        replacementsDictionary.Add("$installlocation$", wizardDirectory);
    }

    public bool ShouldAddProjectItem(string filePath)
    {
        return true;
    }
}

<UsingTask AssemblyFile="$installlocation$\MyTask.dll" TaskName="MyTask" />