【问题标题】:Add a link to an existing item during project creation在项目创建期间添加指向现有项目的链接
【发布时间】:2010-09-07 13:12:45
【问题描述】:

我创建了一个自定义 VS 模板,当用户创建项目以设置项目属性和路径时,它使用 IWizard 类执行一些自动操作,我通过保存 . csproj 文件,在 $ 符号中包含参数,并在 RunStarted 方法期间在 replacementDictionary 中设置这些参数。

不幸的是,我无法使用相同的方法将项目作为链接添加到 .csproj。我有一个 .cs 文件,我需要将其添加为现有的和作为创建的每个项目的链接项,它的路径将由用户选择保存项目的位置确定。我已经到了我知道 .cs 文件路径的部分,(绝对和相对于项目的路径)。

这是我迄今为止尝试过的:

  • 保存 .csproj 文件,其中包含项目的部分,路径占位符:
    <Compile Include="$path_to_cs_file\cs_file_name.cs$">
    <Link>$cs_file_name.cs$</Link>
    </Compile>

我尝试过使用绝对路径和相对路径来执行此操作,但由于某种原因,这使得 VS 将路径替换为 Documents and Settings\user\Local Settings 下完全不同的相对路径。

  • 在 RunStarted 中,将自动化对象转换为 DTE 并调用它的 ItemOperations.AddExistingItem 方法。使用任一路径都会导致错误(参数不正确)。

  • 在 ProjectFinishedGenerating 中,保存项目的路径,然后在 RunFinished 中,使用该路径创建 Microsoft.Build.BuildEngine.Project 对象,调用 DTE 命令保存所有文件并卸载项目,然后调用项目对象的 AddNewItem生成的 ProjectItem 上的方法和 SetMetaData,然后我保存项目并使用 DTE 对象重新加载它,这再次导致与以前相同的错误

感谢您对这个主题的任何帮助,我很难过。提前谢谢你。

【问题讨论】:

    标签: visual-studio


    【解决方案1】:

    我设法“解决”了这个问题,我所做的是:

    • 将占位符保留在csproj中,但从未将相关参数添加到替换字典中:

      <Compile Include="$path_to_cs_file$\$cs_file_name.cs$">
      <Link>$cs_file_name.cs$</Link>
      </Compile>

    • 在ProjectFinishedGenerated方法处,卸载项目,编辑csproj文件替换路径,重新加载项目:

      projectFileName = project.FullName
      // Unload file and manually add the linked item
      dte.ExecuteCommand("File.SaveAll");
      dte.ExecuteCommand("Project.UnloadProject"); // See Note Below
      StreamReader reader = new StreamReader(projectFileName);
      string content = reader.ReadToEnd();
      reader.Close();
      content = Regex.Replace(content, @"\$path_to_cs_file\$", ...);
      content = Regex.Replace(content, @"\$cs_file_name\$", ...);
      StreamWriter writer = new StreamWriter(projectFileName);
      writer.Write(content);
      writer.Close(); dte.ExecuteCommand("Project.ReloadProject");

    注意:以上代码假设需要修改的项目是当前选中的项目,通常ProjectFinishedGenerating运行时是这种情况,但是在多项目模板中或者如果您添加了手动项目到解决方案这可能不是这种情况,您必须调用dte 方法在项目资源管理器中选择您的“主”项目,然后继续卸载、编辑和重新加载。执行此操作的代码如下所示:
    UIHierarchy UIH = dte2.ToolWindows.SolutionExplorer;
    UIHierarchyItem UIHItem = UIH.UIHierarchyItems.Item(1);
    UIHItem.UIHierarchyItems.Item(testProjectName).Select(vsUISelectionType.vsUISelectionTypeSelect);

    【讨论】:

      【解决方案2】:

      如果您不想弄乱 IWizard,另一种解决方案是在 TemplateData 中的 vstemplate 中将 CreateInPlace 设置为 true。

          <CreateInPlace>true</CreateInPlace>
      

      【讨论】:

      • 这个解决方案很棒,对我有用。非常感谢
      【解决方案3】:

      我遇到了完全相同的问题,这让我发疯了。

      我发现了一个非常肮脏的解决方法:

      在我的情况下,我在 RunStarted 方法中使用以下内容:

      EnvDTE.DTE dte = automationObject as EnvDTE.DTE;
      string solutionPath = System.IO.Path.GetDirectory(dte.DTE.Solution.FullName);
      

      这将返回一个包含文件夹“documents”的路径。调用 System.IO.Directory.Exists() 确认这是一个有效目录,但是在检查我的文件系统时,它似乎不存在。如果您将“文档”替换为“我的文档”,然后继续为链接项目使用该路径,则一切正常。

      因此,VS 似乎对“documents”目录别名感到困惑,因此默认使用一些疯狂的“AppData”目录。

      我希望这会有所帮助,但如果您找到更好的方法,请告诉我!

      【讨论】:

      • 我确实设法找到了解决方法,请在答案中查看我的方法,看看它是否适合您...
      • 感谢您的解决方法,效果很好。唯一的问题似乎是运行后,我得到一个对话框,说“项目不可用”。我只需要单击“确定”,一切都很好(项目可用并按预期工作)。您知道如何防止该错误出现吗?它发生在你身上吗?
      • 我忘了添加以下命令:dte.ExecuteCommand("Project.ReloadProject");,我想这会解决您的问题
      • 疯狂的“AppData”目录的出现是因为 CreateInPlace 是假的。一种解决方法是将 CreateInPlace 设置为 true。
      猜你喜欢
      • 1970-01-01
      • 2021-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-13
      • 1970-01-01
      相关资源
      最近更新 更多