Get The ProjectItem of a T4 Template From Inside the T4 Template

So you got a T4 template and need access to the ProjectItem of that T4 template or to the parent Project of the T4 template? Here’s how:

1) Set the template’s hostspecific attribute to true and reference the Visual Studio Automation assemblies.

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="envdte" #>
<#@ assembly name="envdte80" #>
<#@ import namespace="EnvDTE" #>

2) Get the Project or ProjectItem using Visual Studio Automation.

// By setting the template's 'hostspecific' property to true, 
// we get access to the text templating engine host 
// which implements IServiceProvider.
var serviceProvider = (IServiceProvider)this.Host;

// Get the automation root object
var dte = (EnvDTE.DTE)serviceProvider.GetService(typeof(EnvDTE.DTE));

// Get the project item
var projectItem = dte.Solution.FindProjectItem(this.Host.TemplateFile);

// Get the project
var project = projectItem.ContainingProject;

Write To Visual Studio’s Output Window

If you have developed a Visual Studio Extension, you might want to output messages to Visual Studio’s Output window. Here’s how to do it:

using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;

namespace MunirHusseini.Demos
{
    public class VsOutput
    {
        public static void Output(string msg)
        {
            // Get the output window
            var outputWindow = Package.GetGlobalService(typeof(SVsOutputWindow)) as IVsOutputWindow;

            // Ensure that the desired pane is visible
            var paneGuid = Microsoft.VisualStudio.VSConstants.OutputWindowPaneGuid.GeneralPane_guid;
            IVsOutputWindowPane pane;
            outputWindow.CreatePane(paneGuid, "General", 1, 0);
            outputWindow.GetPane(paneGuid, out pane);

            // Output the message
            pane.OutputString(msg);
        }
    }
}

Of course, you could output to other panels than just “General”. To do that, just change the value of the variable paneGuid. Possible values are:

BuildOutputPane_guid The build output pane inside the output window.
DebugPane_guid The debug pane inside the output window.
GeneralPane_guid The general output pane inside the output window.
SortedBuildOutputPane_guid The sorted build output pane inside the output window.
StoreValidationPane_guid The store validation pane inside the output window.

For a visual demonstration, please watch this video.

Modal WPF Windows And The Visual Studio Window

So I needed to show a modal WPF window from inside a Visual Studio Extension. To do that, I needed two thing: 1. a handle of the Visual Studio window and 2. a conversion from the window handle to something compatible with WPF. Long story short – voila:

public static bool ShowDialog(Window dialog)
{
    // Get the top-level Visual Studio object.
    var dte = (DTE)Package.GetGlobalService(typeof(SDTE));

    // Get the handle to Visual Studio's main window
    var hwnd = dte.MainWindow.HWnd;

    // WindowInteropHelper converts betwen WPF and Win32 
    var helper = new WindowInteropHelper(dialog);

    // Now we can use the main window's handle as the owner of our dialog
    helper.Owner = new IntPtr(hwnd);

    // From here on, everything is pure WPF again
    var dialogResult = dialog.ShowDialog();
    return dialogResult.HasValue && dialogResult.Value;
}