.NET Forum / Visual Studio.NET / Extensibility / May 2006
Enterprise Templates Properties and commandbars problem
|
|
Thread rating:  |
Shai - 25 Apr 2006 12:55 GMT We are experiencing two issues using C# to extend Visual Studio 2003.
The solution being extended contains multiple Enterprise Templates (ETP) that each contain one or more projects of various types.
The first problem is that we need to extend the properties displayed in the property browser when an ETP is selected in the Solution Explorer. We found the CatID “{3B6A4DE6-2332-42b7-B6F6-0AF06993FFA2}” to extend the ETP when referencing it in our code. However, we have been unable to find the CatID we need to use when it is selected in the Solution Explorer.
The second extension issue we are having (and much more critical ) is in adding a menu option to the context menu activated when an ETP is right clicked in the Solution Explorer. For this we need to know the name of the command bars to extend, so we can create an instance of it:
CommandBar oCommandBar = applicationObject.CommandBars["Project"];
We’ve tried extending the following command bars: “Project”, “Item”, “Folder”, “Project Node”, “Root”, “Solution Items Project”, but the Enterprise Template does not fall into any of these categories. We actually wrote small util that display all possible applicationObject.CommandBars and there sub commandbars but couldn't find anything that match the ET node.
TIA Shai
Carlos J. Quintero [VB MVP] - 25 Apr 2006 15:07 GMT Hi Shai,
About the second issue, see if this article of mine helps:
HOWTO: Guessing the name of a command bar to add a custom menu entry in Visual Studio .NET add-ins http://www.mztools.com/articles/2004/MZ002.htm
 Signature Best regards,
Carlos J. Quintero
MZ-Tools: Productivity add-ins for Visual Studio You can code, design and document much faster: http://www.mztools.com
> We are experiencing two issues using C# to extend Visual Studio 2003. > [quoted text clipped - 27 lines] > TIA > Shai Shai - 25 Apr 2006 16:35 GMT Hi Carlos ! Thanks for the replay. Actually the little util we wrote was based on your article, only on c# but it didn't help. We got list of more then 2500 commandbar, but none of them where what we are looking for. Here is the snip of code. foreach (CommandBar cmdbar in applicationObject.CommandBars) { outputWindowPane.OutputString("----------------------------------------"+"\n"); outputWindowPane.OutputString("Candidate CommandBar Name: "+ cmdbar.Name +"\n" ); outputWindowPane.OutputString("Captions on this command bar:"+"\n"); foreach ( CommandBarControl objCommandBarControl1 in cmdbar.Controls) { outputWindowPane.OutputString(" " + objCommandBarControl1.Caption +"\n" ); } }
I hope someone from the VS.net team will take a look at this issue.
TIA Shai
> Hi Shai, > [quoted text clipped - 35 lines] > > TIA > > Shai "Gary Chang[MSFT]" - 26 Apr 2006 10:34 GMT Hi Shai,
This is a quick note to let you know that I am performing research on this issue and will get back to you as soon as possible. I appreciate your patience.
Thanks for your understanding.
Best regards,
Gary Chang Microsoft Online Community Support ================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
"Ed Dore [MSFT]" - 28 Apr 2006 01:00 GMT Hi Shai,
I've only had limited exposure to those old Enterprise Template projects. This took a bit of time to track down, but I think I've found a way to retrieve the particular CommandBar you're looking for.
The guid:id pair for the context menu you are interested in is:
{FE3BBBB7-72D5-11D2-9ACE-00C04F79A2A4}:1
From a VSIP package this would be pretty easy to manipulate. But from an addin, the problem is that the DTE automation model doesn't really allow for retrieving the CommandBar with just this info. And the CommandBar name is "Root", which isn't exactly unique. We could try to test a few of the commands in the CommandBar's Controls collection to see if we retreive the right CommandBar, but that seems rather ugly.
So you'll need to use IServiceProvider::QueryService on the DTE object to retrieve the IVsProfferCommands service. Once you have this interface, you can invoke it's FindCommandBar method to retrieve the context menu used by Solution Explorer for ETP nodes.
The IServiceProvider is the COM version and not the .Net version, so you'll need to either use the interop DLL's provided with the VSIP Extra's SDK. Or define the interface yourself. I chose the latter, because using the interop assemblies that ship with the VSIP Extras SDK, means deploying the interop assemblies. With VS 2005 this isn't an issue as the interop assemblies in question actually ship with VS 2005.
Anyway, below is a quick and dirty example of how you can use IVsProfferCommands::FindCommandBar to retrieve and add a new menu item to the ETP project node's context menu.
// defines COM version of IServiceProvider, which is different from // the .NET version. [ ComImport, Guid("6D5140C1-7436-11CE-8034-00AA006009FA"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown) ] public interface IOleServiceProvider { [PreserveSig] int QueryService([In]ref Guid guidService, [In]ref Guid riid, out IntPtr ppvObject); }
[GuidAttribute("76B3EBA5-07E4-4772-BD88-A8D6AC5BCBC4"), ProgId("ETPMenu.Connect")] public class Connect : Object, Extensibility.IDTExtensibility2 { public Connect() { }
public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom) { applicationObject = (_DTE)application; addInInstance = (AddIn)addInInst; CommandBarButton btnTest;
// retrieve IServiceProvider from DTE object IOleServiceProvider sp = (IOleServiceProvider)applicationObject; Guid guidSvc = new Guid(typeof(IVsProfferCommands).GUID.ToString()); IntPtr service; sp.QueryService(ref guidSvc, ref guidSvc, out service); IVsProfferCommands vsProfferCmds = (IVsProfferCommands)Marshal.GetObjectForIUnknown(service); Marshal.Release(service); Guid guidCmdGroup = new Guid("{FE3BBBB7-72D5-11D2-9ACE-00C04F79A2A4}"); uint menuId = 1; CommandBar cmdBar = (CommandBar)vsProfferCmds.FindCommandBar(IntPtr.Zero, ref guidCmdGroup, menuId); try { Object objMissing = System.Reflection.Missing.Value; btnTest = (CommandBarButton)cmdBar.Controls.Add(MsoControlType.msoControlButton, objMissing, objMissing, objMissing, objMissing); btnTest.Caption = "ETP Test"; btnTest.Click +=new _CommandBarButtonEvents_ClickEventHandler(btnTest_Click); } catch(Exception e) { Debug.WriteLine(e.Message); } }
One caveat is that I noticed the FindCommandBar call does fail if an ETP project hasn't been loaded first. But if you're attempting to do this from a project or solution extender, then I suspect this probably won't be an issue.
Concerning the CatID problem, are you creating a solution or project extender to add the additional properties to the ETP projects? Can you provide some additional details as to what exactly you're trying to do there. I'm didn't quite follow what you're trying to do with regards to your CATID question.
Sincerely, Ed Dore [MSFT]
This post is 'AS IS' with no warranties, and confers no rights.
Carlos J. Quintero [VB MVP] - 28 Apr 2006 13:01 GMT Hi Ed,
I am interested about some ideas of your post (inline):
> The IServiceProvider is the COM version and not the .Net version, Which is the difference between the .NET version and the COM version? When do you use each one? Also, you talk about IServiceProvider but the code uses IOleServiceProvider, are they the same?
> so you'll need to either use the interop DLL's provided with the VSIP > Extra's SDK. Or > define the interface yourself. I chose the latter, because using the > interop assemblies that ship with the VSIP Extras SDK, means deploying the > interop assemblies. This is very interesting news. I am using an add-in (not a package) and I have tried to define the IOleServiceProvider in my VB.NET code following your sample, and I get an invalid cast exception when casting applicationObject to IOleServiceProvider, which makes sense since the type IOleServiceProvider defined in my assembly is not the same than the type IOleServiceProvider defined in the interop assemblies (since the assemblies are not the same). So, can you really avoid using the interop assemblies to retrieve IOleServiceProvider? Does your code execute without that exception?
> With VS 2005 this isn't an issue as the interop assemblies in question > actually ship with VS 2005. This is good news...
Thanks in advance for any info,
Carlos
"Ed Dore [MSFT]" - 28 Apr 2006 21:28 GMT Hi Carlos,
I tested the code in a simple C# addin before posting, so I'm pretty sure it works.
The IServiceProvider defined in the .Net runtime, is not the same as the original IServiceProvider interface defined by COM.
Win32 defines IServiceProvider (in the Platform SDK's ServProv.idl file) with the guid 6d5140c1-7436-11ce-8034-00aa006009fa, whereas .Net defines IServiceProvider in it's framework with the guid 8f10f540-7f5d-3f37-8d79-1e0aeb074aa0.
So there are really two different interfaces here. Most VSIP samples (and even the package wizard generated code) will redefine the Win32 version of IServiceProvider to IOleServiceProvider so that it's more readily identifiable as the Win32 COM interface, and not the .NET interface. The IServiceProvider in the code snippet in my previous post uses the Win32 COM IServiceProvider interface (but I named the interface IOleServiceProvider in keeping with the VSIP SDK precedent.
In the VSIP SDK, the IServiceProvider is defined in Microsoft.VisualStudio.OLE.Interop.dll. Because this wasn't around when we first shipped Visual Studio 2003, we provide an installer for it "VSIP Interop Assembly Redist.msi" with the VSIP Extras. So if you use the interop assembly, you wouldn't need to define the interface yourself. But you would need to deploy it by way of the .msi, which is a bit of a hassle for just one simply interface definition :-)
For VB.Net the following should work: Though it's probably not the best written VB code, it works without throwing an exception. You might want to compare your interface definition with the one below. In particular the attributes it uses.
<ComVisible(True), ComImport(), Guid("6D5140C1-7436-11CE-8034-00AA006009FA"), _ InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _ Interface IOleServiceProvider Function QueryService(<InAttribute()> ByRef guidService As Guid, _ <InAttribute()> ByRef riid As Guid, <Out()> ByRef ppvObject As IntPtr) As Integer End Interface
<GuidAttribute("2148639E-1683-4CE7-800D-ED8D73B8B650"), ProgIdAttribute("Carlos.Connect")> _ Public Class Connect
Implements Extensibility.IDTExtensibility2
Dim applicationObject As EnvDTE.DTE Dim addInInstance As EnvDTE.AddIn
<.....>
Public Sub OnConnection(ByVal application As Object, ByVal connectMode As Extensibility.ext_ConnectMode, _ ByVal addInInst As Object, ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnConnection
applicationObject = CType(application, EnvDTE.DTE) addInInstance = CType(addInInst, EnvDTE.AddIn)
Dim sp As IOleServiceProvider = CType(applicationObject, IOleServiceProvider) Dim guidSvc As Guid = New Guid(GetType(IVsProfferCommands).GUID.ToString()) Dim pUnk As IntPtr sp.QueryService(guidSvc, guidSvc, pUnk) Dim obj As Object = Marshal.GetObjectForIUnknown(pUnk) Marshal.Release(pUnk) Dim vsProfferCmds As IVsProfferCommands = CType(obj, IVsProfferCommands) Dim menuId As UInt32 = Convert.ToUInt32(1)
Dim guidCmdGroup = New Guid("{FE3BBBB7-72D5-11D2-9ACE-00C04F79A2A4}") obj = vsProfferCmds.FindCommandBar(IntPtr.Zero, guidCmdGroup, menuId)
Dim cmdBar As CommandBar = CType(obj, CommandBar) Debug.WriteLine(cmdBar.Name)
End Sub
<....>
End Class
Sincerely, Ed Dore [MSFT]
This post is 'AS IS' with no warranties, and confers no rights
Carlos J. Quintero [VB MVP] - 03 May 2006 16:16 GMT Thanks Ed, it was a problem in my code.
Carlos
> Hi Carlos, > [quoted text clipped - 89 lines] > > This post is 'AS IS' with no warranties, and confers no rights Shai - 29 Apr 2006 19:24 GMT Hi Ed! Thank you very much for this solution. It working and we can get the menu for the ETP node.
The other problem we have is to be able to extend this node properties as we did on Solution level or regular project level. Here is more detailed description.
We think we found the CatID we needed, but there is still a problem casting the ExtendeeObject that is being passed into the extender.
The CatID for an ETP when it is selected in the solution explorer is “{E72203D8-B699-4723-8867-03E20F835499}”. To extend the properties of the ETP we added a key in the registry to
“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\7.1\Extenders\{E72203D8-B699-4723-8867-03E20F835499}”
Corresponding to our extender, namely “SolutionMisc”. In that key we set the default value to “{D629F716-77FE-49cd-8F9A-564111B80AFF}”, the GUID for our extender.
Our extender first check to make sure the object to be extended is what is expected via the following function:
public bool CanExtend(string ExtenderCATID, string ExtenderName, object ExtendeeObject) { //return true if it can extend the ExtendeeObject as an ETP if (ExtenderCATID.ToUpper() == “{E72203D8-B699-4723-8867-03E20F835499”) { return true; } else { return false; } }
That is now returning true for Enterprise Templates. The next step is to cast the ExtendeeObject passed as an object in to the method
public object GetExtender(string ExtenderCATID, string ExtenderName, object ExtendeeObject, EnvDTE.IExtenderSite ExtenderSite, int Cookie)
To find out the type of the ExtendeeObject we used the following line
MessageBox.Show(Information.TypeName(ExtendeeObject));
This showed the type as being “IDispEFNode”.
The current problem is that IDispEFNode does not appear in any documentation other than on one website “http://custom.programming-in.net/articles/art14-2.asp?Interop=EFLib”, where it is simply listed as a member of EFLib classes.
Where can we find this type, or is there another comparable type that will work?
TIA Shai
> Hi Shai, > [quoted text clipped - 104 lines] > > This post is 'AS IS' with no warranties, and confers no rights. Yan-Hong Huang[MSFT] - 02 May 2006 08:15 GMT Hello Shai,
In order to better share the knowledge in the community and make others search issues more efficiently, could you please post the question in a new thread in the newsgroup? We will follow up on your new post.
Thanks very much for your understanding.
Sincerely, Yanhong Huang Microsoft Online Community Support
================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Shai - 02 May 2006 08:36 GMT Hi Yanhong Huang !
I opened anther post subject : "Problem with project extender properties for ETP projects" , http://msdn.microsoft.com/newsgroups/default.aspx?&guid=&sloc=en-us&dg=microsoft .public.vstudio.extensibility&p=1&tid=0008b5d1-2bcb-434a-a216-fafe85a3198e&mid=0 008b5d1-2bcb-434a-a216-fafe85a3198e
Please follow up this post.
TIA Shai
> Hello Shai, > [quoted text clipped - 14 lines] > > This posting is provided "AS IS" with no warranties, and confers no rights. "Gary Chang[MSFT]" - 03 May 2006 03:49 GMT That's no problem, we will follow it there.:)
Thanks!
Best regards,
Gary Chang Microsoft Online Community Support ================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
Yan-Hong Huang[MSFT] - 03 May 2006 06:42 GMT Thank you, Shai.
Sincerely, Yanhong Huang Microsoft Online Community Support
================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|