2011-10-10 20 views
3
<#@ template debug="true" hostspecific="true" language="C#" #> 
<#@ assembly name="EnvDTE80" #> 
<#@ include file="T4Toolbox.tt" #> 
<# 
IServiceProvider serviceProvider = (IServiceProvider)this.Host; 
EnvDTE80.DTE2 dte = (EnvDTE80.DTE2)serviceProvider.GetService(typeof(EnvDTE.DTE)); 
//add a file to a project and add its dependupon build property. 
//I want to refresh teh solution explorer window to show the hierarchy between 2 files 
//You will see this kind of relationship between Forms.cs and Form1.Designer.cs files. 

EnvDTE.UIHierarchy solExplorer = dte.ToolWindows.SolutionExplorer; 
solExplorer.Parent.Activate(); 
dte.ExecuteCommand("View.Refresh", string.Empty); 

我試圖刷新Solution Explorer中的工具窗口,這樣我可以看到嵌套在新創建的文件。我知道T4模板在一個應用程序域中執行,並使用遠程調用進入Visual Studio Appdomain。我收到有關序列化的這個錯誤。 那麼有沒有辦法可以通過首先激活它(我被告知)刷新解決方案資源管理器工具窗口(solExplorer.Parent)。T4模板 - 從一個應用程序域刷新解決方案管理器在Visual Studio 2010到另一個

在程序集'Microsoft.VisualStudio.Platform.WindowManagement,版本= 10.0.0.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a'中未輸入'Microsoft.VisualStudio.Platform.WindowManagement.DTE.WindowBase'標記爲可序列化。

更新:基於Gereth的評論。
謝謝,Gereth我試過這個,但它返回COMException,
我沒有關於Microsoft.VisualStudio.Platform.WindowManagement.DTE.WindowBase類和Activate方法的序列化錯誤似乎已經成功。 錯誤現在在dte.ExecuteCommand方法上。

//object dteObject = GetCOMService(serviceProvider, typeof(EnvDTE80.DTE2)); 
object dteObject1 = GetCOMService(serviceProvider, typeof(EnvDTE.DTE)); 
EnvDTE80.DTE2 dte = (EnvDTE80.DTE2)dteObject1; 

收到COMException提出執行該線路時:

dte.ExecuteCommand("View.Refresh", string.Empty); 

消息 「錯誤HRESULT E_FAIL已經從對COM組件的調用返回」。
源 「EnvDTE80」
堆棧跟蹤「在EnvDTE80.DTE2.ExecuteCommand(字符串的CommandName,字符串CommandArgs)
錯誤代碼-2147467259

要嘗試下?

感謝 拉德

回答

2

有一個一旦CLR發現遠程處理管道的兩端都被寫入托管代碼,DTE命令的一部分就不會與COM封送在一起。但是,由於這些組件實際上沒有設置爲.Net遠程管理,但是設置爲做COM遠程,發生這種類型的錯誤。

一般來說,如果正確設置特定DTE對象上的COM封送處理,您應該可以使用下面的代碼再次移動。 呼叫它而不是你的香草服務電話獲得DTE。

public static Object GetCOMService(IServiceProvider provider, Type type) 
{ 
    Object ret; 
    ret = provider.GetService(type); 
    if (ret == null) 
    { 
     return ret; 
    } 

    try 
    { 
     return Marshal.GetObjectForIUnknown(Marshal.GetIUnknownForObject(ret)); 
    } 
    catch (Exception) 
    { 
     return ret; 
    } 
} 
+0

謝謝,Gereth我想這一點,但它返回收到COMException,' //對象dteObject = GetCOMService(的ServiceProvider的typeof(EnvDTE80。DTE2)); object dteObject1 = GetCOMService(serviceProvider,typeof(EnvDTE.DTE)); EnvDTE80.DTE2 dte =(EnvDTE80.DTE2)dteObject1; 消息\t「錯誤HRESULT E_FAIL已從調用COM組件返回。」 來源\t「EnvDTE80」 堆棧跟蹤\t「在EnvDTE80.DTE2.ExecuteCommand(字符串的CommandName,字符串CommandArgs) 錯誤代碼\t -2147467259 '要嘗試下? – Rad

+0

這是一個恥辱。在過去,當DTE命令已失敗我作爲同步調用,我很幸運,將它們發佈到調度程序隊列,以便稍後在UI線程上通過IVsUIShell.PostExecCommand()執行。 – GarethJ

+0

我必須執行如下所示的操作:[link] https:// hg01在ShowUpdatesTabInExtensionManager方法中使用.codeplex.com/forks/damianh/405commandlineversionrange/file/700b7e8b4b5c/src/VisualStudio/ProductUpdate/ProductUpdateService.cs。是否必須使用計時器並檢查其OnTimerTick事件以確定它是否完成後才繼續剩餘的T4克代碼。即我必須將我的代碼生成分成多個方法.Tx。 – Rad

0

我終於通過卸載和重新加載項目得到了這個工作。該項目必須在解決方案資源管理器中進行選擇,否則您將得到一個COMException。

IServiceProvider hostServiceProvider = (IServiceProvider)Host; 
// see @GarethJ's answer for the following 
DTE2 dte2 = GetCOMService(hostServiceProvider, typeof(EnvDTE.DTE)) as DTE2; 
object dteObject1 = GetCOMService(hostServiceProvider, typeof(EnvDTE.DTE)); 
EnvDTE80.DTE2 dte2 = (EnvDTE80.DTE2)dteObject1; 

var solExplorer = dte2.ToolWindows.SolutionExplorer; 
solExplorer.Parent.Activate(); 
ProjectItem containingProjectItem = dte2.Solution.FindProjectItem(templateFile); 
Project project = containingProjectItem.ContainingProject; 

UIHierarchy solExplorerHierarchy = solExplorer.Parent.Object as UIHierarchy; 
string projectSolutionPath = Path.Combine(dte2.Solution.Properties.Item("Name").Value.ToString(), project.Name); 
var projectItem = solExplorerHierarchy.GetItem(projectSolutionPath); 
projectItem.Select(vsUISelectionType.vsUISelectionTypeSelect); 
dte2.ExecuteCommand("Project.UnloadProject", ""); 
dte2.ExecuteCommand("Project.ReloadProject", ""); 

然後出現任何新創建的嵌套項目。我正在使用VS2012和T4Toolbox 11.7。

0

謝謝Gareth。你的解決方案效果很好。 我已經延長我的 「的GetService」 的方法:

private T GetService<T>(Type type) where T : class 
    { 
     IServiceProvider hostServiceProvider = (IServiceProvider)Host; 
     if (hostServiceProvider == null) 
     { 
      throw new Exception("Host property returned unexpected value (null)"); 
     } 
     object serviceObj = hostServiceProvider.GetService(type); 
     try 
     { 
      serviceObj = Marshal.GetObjectForIUnknown(Marshal.GetIUnknownForObject(serviceObj)); 
     } 
     catch (Exception) { } 
     T service = serviceObj as T; 
     if (service == null) 
     { 
      throw new Exception("Unable to retrieve service"); 
     } 
     return service; 
    } 
相關問題