我选择了使用带有项目模板的向导的解决方案,主要是因为我的一些模板已经需要向导。
我创建了一个基类,我的所有其他向导都应该扩展它,或者可以单独使用它来实现基本功能:
public class AddTargetsWizard : IWizard
{
private const string RELATIVE_PATH_TO_TARGETS = @"..\..\..\..\PATH\TO\Custom.Tasks.Targets";
private const string TASK_NOT_FOUND_MESSAGE = @"A project of this type should be created under a specific path in order for the custom build task to be properly executed.
The build task could not be found at the following location:
{0}
Including the build task would result in unexpected behavior in Visual Studio.
The project was created, but the build task WILL NOT BE INCLUDED.
This project's builds WILL NOT benefit from the custom build task.";
private string _newProjectFileName;
private bool _addTaskToProject;
private Window _mainWindow;
public AddTargetsWizard()
{
this._addTaskToProject = true;
}
protected Window MainWindow
{
get
{
return this._mainWindow;
}
}
public virtual void BeforeOpeningFile(EnvDTE.ProjectItem projectItem)
{
}
public virtual void ProjectFinishedGenerating(EnvDTE.Project project)
{
this._newProjectFileName = project.FullName;
var projectDirectory = Path.GetDirectoryName(this._newProjectFileName);
var taskPath = Path.GetFullPath(Path.Combine(projectDirectory, RELATIVE_PATH_TO_TARGETS));
if (!File.Exists(taskPath))
{
MessageBox.Show(
this.MainWindow,
string.Format(TASK_NOT_FOUND_MESSAGE, taskPath),
"Project Creation Error",
MessageBoxButton.OK,
MessageBoxImage.Error,
MessageBoxResult.OK,
MessageBoxOptions.None);
this._addTaskToProject = false;
}
}
public virtual void ProjectItemFinishedGenerating(EnvDTE.ProjectItem projectItem)
{
}
public virtual void RunFinished()
{
if (this._addTaskToProject)
{
var project = new Microsoft.Build.Evaluation.Project(this._newProjectFileName);
project.Xml.AddImport(RELATIVE_PATH_TO_TARGETS);
project.Save();
}
}
public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams)
{
var dte = (EnvDTE80.DTE2)automationObject;
var mainWindow = dte.MainWindow;
foreach (var proc in System.Diagnostics.Process.GetProcesses())
{
if (proc.MainWindowTitle.Equals(mainWindow.Caption))
{
var source = HwndSource.FromHwnd(proc.MainWindowHandle);
this._mainWindow = source.RootVisual as System.Windows.Window;
break;
}
}
this.OnRunStarted(automationObject, replacementsDictionary, runKind, customParams);
}
protected virtual void OnRunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams)
{
}
public virtual bool ShouldAddProjectItem(string filePath)
{
return true;
}
}
本演练很好地解释了如何将向导与项目(或项)模板相关联。
您会注意到我正在为OnRunStarted
需要提供附加功能的子向导提供虚拟方法,例如显示向导窗口、填充替换字典等。
我不喜欢这种方法和/或我的实现的事情:
- 它比普通的项目模板要复杂得多。
- 为了使我的向导窗口(所有 WPF)成为以 Visual Studio 作为其所有者的真正模式窗口,我发现没有比使用当前实例的标题来确定 HWND 和关联的
Window
.
- 在预期的文件夹层次结构中创建项目时,一切都很好,但 Visual Studio 的行为很奇怪(即弹出无用的对话框)。这就是为什么我选择显示错误消息并避免插入
Import
如果当前项目的位置不适用于我的相对路径。
如果有人有其他想法,我仍然全神贯注。