.NET Forum / Visual Studio.NET / Extensibility / April 2008
VCProjectEngine reference
|
|
Thread rating:  |
bmelt - 16 Apr 2008 16:07 GMT I use following code to set VC++ directories programmatically (or similar code in C#): DTE^ dte = (DTE^)System::Runtime::InteropServices::Marshal::GetActiveObject ("VisualStudio.DTE.8.0"); Projects ^projects = (Projects^)dte->GetObject(L"VCProjects"); VCProjectEngine ^ projectengine = (VCProjectEngine ^)projects->Properties->Item(L"VCProjectEngine")->Object; IVCCollection ^platforms = (IVCCollection^)projectengine ->Platforms; VCPlatform ^p64 = (VCPlatform ^)platforms->Item("x64"); if(p64 !=nullptr) p64->ExecutableDirectories += ";C:\\Temp";
How to write a program that would set VC++ directories for any of VS 2003, 2005 and 2008. It looks like for each version of Visual Studio I have to set reference to correspondent version of Microsoft::VisualStudio::VCProjectEngine, otherwise following code fails:
VCProjectEngine ^ projectengine (VCProjectEngine ^) projects->Properties->Item("VCProjectEngine")->Object;
As a workaround, I can probably create 3 separate dlls or exe's each of which has a reference to one of versions of VCProjectEngine and call correspondent one from the main program - is there a better way?
Also, there is CommitChanges method to save settings in .Net 2.0 or higher. How to save settings with VS 2003?
Jialiang Ge [MSFT] - 17 Apr 2008 11:06 GMT Hello bmelt,
From your post, my understanding on this issue is: you wonder how to write automation code for multiple versions of Visual Studio and how to save changes (CommitChanges) in VS2003. If I'm off base, please feel free to let me know.
1. For you first question about VS automation code that can be compatible for multiple versions of VS:
If it were Office automation, I would recommend that we can either use late binding, or reference the earliest version of Office application we intend to automate. However, for Visual Studio automation, VS Core automation model keeps good backward compatibility, but VC++ automation models do not. That's why you get the error
"Could not load file or assembly 'Microsoft.VisualStudio.VCProjectEngine, Version=8.0.0.0...'"
from the line: VCProjectEngine ^ projectengine = (VCProjectEngine ^)projects->Properties->Item("VCProjectEngine")->Object;
when the program explicitly references VCProject assembly for 8.0 but is run in VS2008 machine. Actually, if you check the public assemblies of VS2008 (C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\PublicAsemblies), you will find EnvDTE.dll, EnvDTE80.dll, and EnvDTE90.dll, but for Microsoft.VisualStudio.VCProjectEngine.dll, it has only one whose version is 9.0.
In conclusion, we can use late binding to automate multiple versions of Visual Studio, but we cannot accomplish it with early binding. I write the following C++/CLI and C# late binding sample code for your references. The code has been tested in VS2003, 2005 and 2008.
C++/CLI: Object^ dte = Marshal::GetActiveObject("VisualStudio.DTE");
Object^ projects = dte->GetType()->InvokeMember("GetObject", System::Reflection::BindingFlags::InvokeMethod, nullptr, dte, gcnew cli::array<Object^> { "VCProjects" }); Object^ properties = projects->GetType()->InvokeMember("Properties", System::Reflection::BindingFlags::GetProperty, nullptr, projects, nullptr); Object^ vcprojectItem = properties->GetType()->InvokeMember("Item", System::Reflection::BindingFlags::InvokeMethod, nullptr, properties, gcnew cli::array<Object^> { "VCProjectEngine" }); Object^ projectengine = vcprojectItem->GetType()->InvokeMember("Object", System::Reflection::BindingFlags::GetProperty, nullptr, vcprojectItem, nullptr); Object^ platforms = projectengine->GetType()->InvokeMember("Platforms", System::Reflection::BindingFlags::GetProperty, nullptr, projectengine, nullptr); Object^ p64 = platforms->GetType()->InvokeMember("Item", System::Reflection::BindingFlags::InvokeMethod, nullptr, platforms, gcnew cli::array<Object^> { "x64" });
String^ exedir; if (p64 != nullptr) { exedir = (String^)p64->GetType()->InvokeMember("ExecutableDirectories", System::Reflection::BindingFlags::GetProperty, nullptr, p64, nullptr); Console::WriteLine(exedir); }
C#: object dte = Marshal.GetActiveObject("VisualStudio.DTE"); object projects = dte.GetType().InvokeMember("GetObject", System.Reflection.BindingFlags.InvokeMethod, null, dte, new object[] { "VCProjects" }); object properties = projects.GetType().InvokeMember("Properties", System.Reflection.BindingFlags.GetProperty, null, projects, null); object vcprojectItem = properties.GetType().InvokeMember("Item", System.Reflection.BindingFlags.InvokeMethod, null, properties, new object[] { "VCProjectEngine" }); object projectengine = vcprojectItem.GetType().InvokeMember("Object", System.Reflection.BindingFlags.GetProperty, null, vcprojectItem, null); object platforms = projectengine.GetType().InvokeMember("Platforms", System.Reflection.BindingFlags.GetProperty, null, projectengine, null); object p64 = platforms.GetType().InvokeMember("Item", System.Reflection.BindingFlags.InvokeMethod, null, platforms, new object[] { "x64" }); string exedir; if (p64 != null) { exedir = (string)p64.GetType().InvokeMember("ExecutableDirectories", System.Reflection.BindingFlags.GetProperty, null, p64, null); Console.WriteLine(exedir); }
2. For your second question about CommitChanges:
According to the MSDN article http://msdn2.microsoft.com/en-us/library/microsoft.visualstudio.vcprojecteng ine.vcplatform.commitchanges(VS.80).aspx, the function is for internal use only, and is new to VS2005. In VS2003, as far as I know, there is not an equivalent. Regarding how to save changes for VS settings, please give me some time to discuss it with the Visual Studio development team. I will get back to you as soon as possible.
Please let me know if you have any other concerns, or need anything else.
Regards, Jialiang Ge (jialge@online.microsoft.com, remove ¡®online.¡¯) Microsoft Online Community Support
Delighting our customers is our #1 priority. We welcome your comments and suggestions about how we can improve the support we provide to you. Please feel free to let my manager know what you think of the level of service provided. You can send feedback directly to my manager at: msdnmg@microsoft.com.
================================================== Get notification to my posts through email? Please refer to http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif ications.
Note: The MSDN Managed Newsgroup support offering is for non-urgent issues where an initial response from the community or a Microsoft Support Engineer within 1 business day is acceptable. Please note that each follow up response may take approximately 2 business days as the support professional working with you may need further investigation to reach the most efficient resolution. The offering is not appropriate for situations that require urgent, real-time or phone-based interactions or complex project analysis and dump analysis issues. Issues of this nature are best handled working with a dedicated Microsoft Support Engineer by contacting Microsoft Customer Support Services (CSS) at ttp://msdn.microsoft.com/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
bmelt - 18 Apr 2008 23:32 GMT Hi Jialiang ,
Thank you for good explanation and code example, it workes fine. I could build my program with your code on VS 2005 and then access VC++ Directories on 2003, 2005 and 2008. In addition to your code, I could also set new paths using code like platforms->GetType()->InvokeMember("ExecutableDirectories", System::Reflection::BindingFlags::SetProperty, nullptr, pPlatform, gcnew cli::array<Object^> { "NewPath" });
Also on VS 2005 and 2008 I could commit changes with code pPlatform->GetType()->InvokeMember("CommitChanges", System::Reflection::BindingFlags::InvokeMethod, nullptr, pPlatform, nullptr); but on VS 2003 this code failed indeed (Unknown name), so I'm still waiting for an alternative to CommitChanges.
Without CommitChanges I can not save changes that were done programmatically.
Now if IDE is open and Marshal::GetActiveObject is used to get dte, I do not see changes in VC++Directories right after running my program that uses CommitChanges, but can see them if I close-open IDE. Is it possible to make changes visible without re-opening IDE?
Another problem looks strange: if CommitChanges is called, and later I change paths manually in IDE, then again run the program that calls CommitChanges - changes desappear that were done manually. I have a feel that manual and programmatic changes are saved in different places.
How to save both manual and programmatic changes on 3 supported versions of Visual Studio?
Regards, Boris
Jialiang Ge [MSFT] - 21 Apr 2008 09:09 GMT Hello Boris,
>Also on VS 2005 and 2008 I could commit changes with > code pPlatform->GetType()->InvokeMember( >"CommitChanges",System::Reflection::BindingFlags:: > InvokeMethod, nullptr, pPlatform, nullptr); but on VS 2003 this code > failed indeed (Unknown name), so I'm still waiting for an alternative > to CommitChanges. The failure of CommitChanges in VS2003 is because the method was not exposed to VS2003 automation interface. CommitChanges is brand new to VS2005. According to the confirmation from the VS team, I have to let you know that there is no equivalent to CommitChanges in VS2003. I agree it is very weird that VS offers ways to make the changes, but does not allow saving the changes. As a long-term resolution, I have submitted your concerns to the VS designers, and you are also welcome to add your supplements to make Microsoft products easier to use by submitting a ticket in https://connect.microsoft.com/VisualStudio. As a short-term workaround for the VS2003 issue, I think we can write an Visual Studio add-in. Whenever VS is started, the add-in sets the VCProject ExecutableDirectories.
>Now if IDE is open and Marshal::GetActiveObject is used to get dte, > I do not see changes in VC++Directories right after running my > program that uses CommitChanges, but can see them if I close-open > IDE. Is it possible to make changes visible without re-opening IDE? Would you check if there is more than one instance of VS running when this happens? Because based on my test when there is only one VS running, the setting takes effects immediately after I run the program. I can see the new path in VC executable directories. However, if multiple VS's are running, only one of which will reflect the change and others need a restart. The reason for this behavior is: from a COM standpoint, the DTE object is registered in the system's RunningObject. The IRunningObjectTable::GetObject will actually retrieve the last object registered, when we have duplicate objects in the ROT. We may have to enumerate the ROT instead, and set the VCProject executable directories for all of them if we do not expect a restart of VS. Ed Dore from MSFT showed some sample code in the post: http://www.dotnet247.com/247reference/msgs/46/231613.aspx
>Another problem looks strange: if CommitChanges is called, and > later I change paths manually in IDE, then again run the program > that calls CommitChanges - changes desappear that were done > manually. I have a feel that manual and programmatic changes >are saved in different places. Do you see the changes made by your program in VS IDE? If not, please refer to my reply to your second question. If we want to call CommitChanges, we should do it immediate after we programmatically changes the VCProject settings. In fact, any manual changes through VS IDE before CommitChanges will be discarded.
I understand that it is very difficult to automate Visual Studio, which is more complicated than the automation of Office. As far as I know, the VS team might rewrite its infrastructure while keeping backward compatibility. Anyway, I will do my best to help you out the present problems.
Regards, Jialiang Ge (jialge@online.microsoft.com, remove 'online.') Microsoft Online Community Support
================================================= Delighting our customers is our #1 priority. We welcome your comments and suggestions about how we can improve the support we provide to you. Please feel free to let my manager know what you think of the level of service provided. You can send feedback directly to my manager at: msdnmg@microsoft.com.
This posting is provided "AS IS" with no warranties, and confers no rights. =================================================
bmelt - 23 Apr 2008 17:43 GMT Hi Jialiang, Thank you for explanation, I decided use of CommitChange is not good for my project: it does not work with VS 2003 and removes all manual changes between two calls to this function. As a workaround, now I'm going to run VS instanse with Process, then set paths with platforms->GetType()->InvokeMember("ExecutableDirectories", System::Reflection::BindingFlags::SetProperty, nullptr, pPlatform, gcnew cli::array<Object^> { "NewPath" }); Changes are visualized in VC++ directories - it works with all 3 versions of VS. User will check if there are paths set correctly, then change something - it is enough to type ";" after the last path, then save changes clicking OK on Options dialog. Now probably the last question: how to programmatically open Options dialog and display VC++ directories window. I tried dte->ExecuteCommand ("Tools.Options",nullptr); but it did not work at all.
Regards, Boris
Jialiang Ge [MSFT] - 24 Apr 2008 08:37 GMT Hello Boris,
Executing the command "Tools.Options" can open the Tools->Options dialog, but I don't find interfaces/paramerters exposed by VS to programmatically switch to the VC++ Directories window. A possible workaround is to find the Options window's handle, and use SendMessage to turn to the target page. (See: http://msdn2.microsoft.com/en-us/library/ms996405.aspx). I am still contacting the VS team, to see if they have any suggestions. I will get back to you soon.
Regards, Jialiang Ge (jialge@online.microsoft.com, remove 'online.') Microsoft Online Community Support
================================================= Delighting our customers is our #1 priority. We welcome your comments and suggestions about how we can improve the support we provide to you. Please feel free to let my manager know what you think of the level of service provided. You can send feedback directly to my manager at: msdnmg@microsoft.com.
This posting is provided "AS IS" with no warranties, and confers no rights. =================================================
Jialiang Ge [MSFT] - 28 Apr 2008 12:03 GMT Hello Boris,
I get back with a good news. We can pass the options page GUID (which you can look up under HKLM\Software\Microsoft\VisualStudio\10.0\ToolsOptionsPages) as a parameter to dte ExecuteCommand method: dte.ExecuteCommand("Tools.Options", "3284355C-AA45-11D2-835C-00C04F796961").
If you have any other concerns or questions, feel free to let me know.
Regards, Jialiang Ge (jialge@online.microsoft.com, remove 'online.') Microsoft Online Community Support
================================================= Delighting our customers is our #1 priority. We welcome your comments and suggestions about how we can improve the support we provide to you. Please feel free to let my manager know what you think of the level of service provided. You can send feedback directly to my manager at: msdnmg@microsoft.com.
This posting is provided "AS IS" with no warranties, and confers no rights. =================================================
bmelt - 28 Apr 2008 17:50 GMT Hi Jialiang,
Finally you've answered on all my difficult questions and now I can accomplish my project.
Thanks a lot for your great assistance - it was really knowlegable and creative.
Best regards, Boris
Jialiang Ge [MSFT] - 29 Apr 2008 02:57 GMT Glad to help.
Regards, Jialiang Ge (jialge@online.microsoft.com, remove 'online.') Microsoft Online Community Support
================================================= Delighting our customers is our #1 priority. We welcome your comments and suggestions about how we can improve the support we provide to you. Please feel free to let my manager know what you think of the level of service provided. You can send feedback directly to my manager at: msdnmg@microsoft.com.
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 ...
|
|
|