main.cs
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:25k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. // Code about getting running instances visual studio
  2. // was borrowed from 
  3. // http://www.codeproject.com/KB/cs/automatingvisualstudio.aspx
  4. using System;
  5. using System.Collections;
  6. using System.Collections.Generic;
  7. using System.Reflection;
  8. using System.Runtime.InteropServices;
  9. using System.Runtime.InteropServices.ComTypes;
  10. using Microsoft.CSharp;
  11. namespace VSTool
  12. {
  13.     // The MessageFilter class comes from:
  14.     // http://msdn.microsoft.com/en-us/library/ms228772(VS.80).aspx
  15.     // It allows vstool to get timing error messages from 
  16.     // visualstudio and handle them.
  17.     public class MessageFilter : IOleMessageFilter
  18.     {
  19.         //
  20.         // Class containing the IOleMessageFilter
  21.         // thread error-handling functions.
  22.         // Start the filter.
  23.         public static void Register()
  24.         {
  25.             IOleMessageFilter newFilter = new MessageFilter(); 
  26.             IOleMessageFilter oldFilter = null; 
  27.             CoRegisterMessageFilter(newFilter, out oldFilter);
  28.         }
  29.         // Done with the filter, close it.
  30.         public static void Revoke()
  31.         {
  32.             IOleMessageFilter oldFilter = null; 
  33.             CoRegisterMessageFilter(null, out oldFilter);
  34.         }
  35.         //
  36.         // IOleMessageFilter functions.
  37.         // Handle incoming thread requests.
  38.         int IOleMessageFilter.HandleInComingCall(int dwCallType, 
  39.           System.IntPtr hTaskCaller, int dwTickCount, System.IntPtr 
  40.           lpInterfaceInfo) 
  41.         {
  42.             //Return the flag SERVERCALL_ISHANDLED.
  43.             return 0;
  44.         }
  45.         // Thread call was rejected, so try again.
  46.         int IOleMessageFilter.RetryRejectedCall(System.IntPtr 
  47.           hTaskCallee, int dwTickCount, int dwRejectType)
  48.         {
  49.             if (dwRejectType == 2)
  50.             // flag = SERVERCALL_RETRYLATER.
  51.             {
  52.                 // Retry the thread call immediately if return >=0 & 
  53.                 // <100.
  54.                 return 99;
  55.             }
  56.             // Too busy; cancel call.
  57.             return -1;
  58.         }
  59.         int IOleMessageFilter.MessagePending(System.IntPtr hTaskCallee, 
  60.           int dwTickCount, int dwPendingType)
  61.         {
  62.             //Return the flag PENDINGMSG_WAITDEFPROCESS.
  63.             return 2; 
  64.         }
  65.         // Implement the IOleMessageFilter interface.
  66.         [DllImport("Ole32.dll")]
  67.         private static extern int 
  68.           CoRegisterMessageFilter(IOleMessageFilter newFilter, out 
  69.           IOleMessageFilter oldFilter);
  70.     }
  71.     [ComImport(), Guid("00000016-0000-0000-C000-000000000046"), 
  72.     InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
  73.     interface IOleMessageFilter 
  74.     {
  75.         [PreserveSig]
  76.         int HandleInComingCall( 
  77.             int dwCallType, 
  78.             IntPtr hTaskCaller, 
  79.             int dwTickCount, 
  80.             IntPtr lpInterfaceInfo);
  81.         [PreserveSig]
  82.         int RetryRejectedCall( 
  83.             IntPtr hTaskCallee, 
  84.             int dwTickCount,
  85.             int dwRejectType);
  86.         [PreserveSig]
  87.         int MessagePending( 
  88.             IntPtr hTaskCallee, 
  89.             int dwTickCount,
  90.             int dwPendingType);
  91.     }
  92.     class ViaCOM
  93.     {
  94.         public static object GetProperty(object from_obj, string prop_name)
  95.         {
  96.             try
  97.             {
  98.                 Type objType = from_obj.GetType();
  99.                 return objType.InvokeMember(
  100.                     prop_name,
  101.                     BindingFlags.GetProperty, null,
  102.                     from_obj,
  103.                     null);
  104.             }
  105.             catch (Exception e)
  106.             {
  107.                 Console.WriteLine("Error getting property: "{0}"", prop_name);
  108.                 Console.WriteLine(e.Message);
  109.                 throw e;
  110.             }
  111.         }
  112.         public static object SetProperty(object from_obj, string prop_name, object new_value)
  113.         {
  114.             try
  115.             {
  116.                 object[] args = { new_value };
  117.                 Type objType = from_obj.GetType();
  118.                 return objType.InvokeMember(
  119.                     prop_name,
  120.                     BindingFlags.DeclaredOnly |
  121.                     BindingFlags.Public |
  122.                     BindingFlags.NonPublic |
  123.                     BindingFlags.Instance |
  124.                     BindingFlags.SetProperty,
  125.                     null,
  126.                     from_obj,
  127.                     args);
  128.             }
  129.             catch (Exception e)
  130.             {
  131.                 Console.WriteLine("Error setting property: "{0}"", prop_name);
  132.                 Console.WriteLine(e.Message);
  133.                 throw e;
  134.             }
  135.         }
  136.         public static object CallMethod(object from_obj, string method_name, params object[] args)
  137.         {
  138.             try
  139.             {
  140.                 Type objType = from_obj.GetType();
  141.                 return objType.InvokeMember(
  142.                     method_name,
  143.                     BindingFlags.DeclaredOnly |
  144.                     BindingFlags.Public |
  145.                     BindingFlags.NonPublic |
  146.                     BindingFlags.Instance |
  147.                     BindingFlags.InvokeMethod,
  148.                     null,
  149.                     from_obj,
  150.                     args);
  151.             }
  152.             catch (Exception e)
  153.             {
  154.                 Console.WriteLine("Error calling method "{0}"", method_name);
  155.                 Console.WriteLine(e.Message);
  156.                 throw e;
  157.             }
  158.         }
  159.     };
  160.     /// <summary>
  161. /// The main entry point class for VSTool.
  162. /// </summary>
  163.     class VSToolMain
  164.     {
  165.         #region Interop imports
  166.         [DllImport("ole32.dll")]  
  167.         public static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot); 
  168.  
  169.         [DllImport("ole32.dll")]  
  170.         public static extern int  CreateBindCtx(int reserved, out IBindCtx ppbc);
  171.         #endregion 
  172.         static System.Boolean ignore_case = true;
  173.         static string solution_name = null;
  174.         static bool use_new_vs = false;
  175.         static Hashtable projectDict = new Hashtable();
  176.         static string startup_project = null;
  177.         static string config = null;
  178.         static object dte = null;
  179.         static object solution = null;
  180.         /// <summary>
  181. /// The main entry point for the application.
  182. /// </summary>
  183. [STAThread]
  184. static int Main(string[] args)
  185. {
  186.             int retVal = 0;
  187.             bool need_save = false;
  188.             try
  189.             {
  190.                 parse_command_line(args);
  191.                 Console.WriteLine("Editing solution: {0}", solution_name);
  192.                 bool found_open_solution = GetDTEAndSolution();
  193.                 if (dte == null || solution == null)
  194.                 {
  195.                     retVal = 1;
  196.                 }
  197.                 else
  198.                 {
  199.                     MessageFilter.Register();
  200.                     // Walk through all of the projects in the solution
  201.                     // and list the type of each project.
  202.                     foreach (DictionaryEntry p in projectDict)
  203.                     {
  204.                         string project_name = (string)p.Key;
  205.                         string working_dir = (string)p.Value;
  206.                         if (SetProjectWorkingDir(solution, project_name, working_dir))
  207.                         {
  208.                             need_save = true;
  209.                         }
  210.                     }
  211.                     if (config != null)
  212.                     {
  213.                         need_save = SetActiveConfig(config);
  214.                     }
  215.                     if (startup_project != null)
  216.                     {
  217.                         need_save = SetStartupProject(startup_project);
  218.                     }
  219.                     if (need_save)
  220.                     {
  221.                         if (found_open_solution == false)
  222.                         {
  223.                             ViaCOM.CallMethod(solution, "Close", null);
  224.                         }
  225.                     }
  226.                 }
  227.             }
  228.             catch (Exception e)
  229.             {
  230.                 Console.WriteLine(e.Message);
  231.                 retVal = 1;
  232.             }
  233.             finally
  234.             {
  235.                 if (solution != null)
  236.                 {
  237.                     Marshal.ReleaseComObject(solution);
  238.                     solution = null;
  239.                 }
  240.                 if (dte != null)
  241.                 {
  242.                     Marshal.ReleaseComObject(dte);
  243.                     dte = null;
  244.                 }
  245.                 MessageFilter.Revoke();
  246.             }
  247.             return retVal;
  248.         }
  249.         public static bool parse_command_line(string[] args)
  250.         {
  251.             string options_desc = 
  252.                 "--solution <solution_name>   : MSVC solution name. (required)n" +
  253.                 "--use_new_vs                 : Ignore running versions of visual studio.n" +
  254.                 "--workingdir <project> <dir> : Set working dir of a VC project.n" +
  255.                 "--config <config>            : Set the active config for the solution.n" +
  256.                 "--startup <project>          : Set the startup project for the solution.n";
  257.             try
  258.             {
  259.                 // Command line param parsing loop.
  260.                 int i = 0;
  261.                 for (; i < args.Length; ++i)
  262.                 {
  263.                     if ("--solution" == args[i])
  264.                     {
  265.                         if (solution_name != null)
  266.                         {
  267.                             throw new ApplicationException("Found second --solution option");
  268.                         }
  269.                         solution_name = args[++i];
  270.                     }
  271.                     else if ("--use_new_vs" == args[i])
  272.                     {
  273.                         use_new_vs = true;
  274.                     }
  275.                     else if ("--workingdir" == args[i])
  276.                     {
  277.                         string project_name = args[++i];
  278.                         string working_dir = args[++i];
  279.                         projectDict.Add(project_name, working_dir);
  280.                     }
  281.                     else if ("--config" == args[i])
  282.                     {
  283.                         if (config != null)
  284.                         {
  285.                             throw new ApplicationException("Found second --config option");
  286.                         }
  287.                         config = args[++i];
  288.                     }
  289.                     else if ("--startup" == args[i])
  290.                     {
  291.                         if (startup_project != null)
  292.                         {
  293.                             throw new ApplicationException("Found second --startup option");
  294.                         }
  295.                         startup_project = args[++i];
  296.                     }
  297.                     else
  298.                     {
  299.                         throw new ApplicationException("Found unrecognized token on command line: " + args[i]);
  300.                     }
  301.                 }
  302.                 if (solution_name == null)
  303.                 {
  304.                     throw new ApplicationException("The --solution option is required.");
  305.                 }
  306.             }
  307.             catch(ApplicationException e)
  308.             {
  309.                 Console.WriteLine("Oops! " + e.Message);
  310.                 Console.Write("Command line:");
  311.                 foreach (string arg in args)
  312.                 {
  313.                     Console.Write(" " + arg);
  314.                 }
  315.                 Console.Write("nn");
  316.                 Console.WriteLine("VSTool command line usage");
  317.                 Console.Write(options_desc);
  318.                 throw e;
  319.             }
  320.             return true;
  321.         }
  322.         public static bool GetDTEAndSolution()
  323.         {
  324.             bool found_open_solution = true;
  325.             Console.WriteLine("Looking for existing VisualStudio instance...");
  326.             // Get an instance of the currently running Visual Studio .NET IDE.
  327.             // dte = (EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.7.1");
  328.             string full_solution_name = System.IO.Path.GetFullPath(solution_name);
  329.             if (false == use_new_vs)
  330.             {
  331.                 dte = GetIDEInstance(full_solution_name);
  332.             }
  333.             if (dte == null)
  334.             {
  335.                 try
  336.                 {
  337.                     Console.WriteLine("  Didn't find open solution, starting new background VisualStudio instance...");
  338.                     Console.WriteLine("  Reading .sln file version...");
  339.                     string version = GetSolutionVersion(full_solution_name);
  340.                     Console.WriteLine("  Using version: {0}...", version);
  341.                     string progid = GetVSProgID(version);
  342.                     Type objType = Type.GetTypeFromProgID(progid);
  343.                     dte = System.Activator.CreateInstance(objType);
  344.                     Console.WriteLine("  Reading solution: "{0}"", full_solution_name);
  345.                     solution = ViaCOM.GetProperty(dte, "Solution");
  346.                     object[] openArgs = { full_solution_name };
  347.                     ViaCOM.CallMethod(solution, "Open", openArgs);
  348.                 }
  349.                 catch (Exception e)
  350.                 {
  351.                     Console.WriteLine(e.Message);
  352.                     Console.WriteLine("Quitting do to error opening: {0}", full_solution_name);
  353.                     solution = null;
  354.                     dte = null;
  355.                     return found_open_solution;
  356.                 }
  357.                 found_open_solution = false;
  358.             }
  359.             if (solution == null)
  360.             {
  361.                 solution = ViaCOM.GetProperty(dte, "Solution");
  362.             }
  363.             return found_open_solution;
  364.         }
  365.         /// <summary>
  366.         /// Get the DTE object for the instance of Visual Studio IDE that has 
  367.         /// the specified solution open.
  368.         /// </summary>
  369.         /// <param name="solutionFile">The absolute filename of the solution</param>
  370.         /// <returns>Corresponding DTE object or null if no such IDE is running</returns>
  371.         public static object GetIDEInstance( string solutionFile )
  372.         {
  373.             Hashtable runningInstances = GetIDEInstances( true );
  374.             IDictionaryEnumerator enumerator = runningInstances.GetEnumerator();
  375.             while ( enumerator.MoveNext() )
  376.             {
  377.                 try
  378.                 {
  379.                     object ide = enumerator.Value;
  380.                     if (ide != null)
  381.                     {
  382.                         object sol = ViaCOM.GetProperty(ide, "Solution");
  383.                         if (0 == string.Compare((string)ViaCOM.GetProperty(sol, "FullName"), solutionFile, ignore_case))
  384.                         {
  385.                             return ide;
  386.                         }
  387.                     }
  388.                 } 
  389.                 catch{}
  390.             }
  391.             return null;
  392.         }
  393.         /// <summary>
  394.         /// Get a table of the currently running instances of the Visual Studio .NET IDE.
  395.         /// </summary>
  396.         /// <param name="openSolutionsOnly">Only return instances that have opened a solution</param>
  397.         /// <returns>A hashtable mapping the name of the IDE in the running object table to the corresponding DTE object</returns>
  398.         public static Hashtable GetIDEInstances( bool openSolutionsOnly )
  399.         {
  400.             Hashtable runningIDEInstances = new Hashtable();
  401.             Hashtable runningObjects = GetRunningObjectTable();
  402.             IDictionaryEnumerator rotEnumerator = runningObjects.GetEnumerator();
  403.             while ( rotEnumerator.MoveNext() )
  404.             {
  405.                 string candidateName = (string) rotEnumerator.Key;
  406.                 if (!candidateName.StartsWith("!VisualStudio.DTE"))
  407.                     continue;
  408.                 object ide = rotEnumerator.Value;
  409.                 if (ide == null)
  410.                     continue;
  411.                 if (openSolutionsOnly)
  412.                 {
  413.                     try
  414.                     {
  415.                         object sol = ViaCOM.GetProperty(ide, "Solution");
  416.                         string solutionFile = (string)ViaCOM.GetProperty(sol, "FullName");
  417.                         if (solutionFile != String.Empty)
  418.                         {
  419.                             runningIDEInstances[ candidateName ] = ide;
  420.                         }
  421.                     } 
  422.                     catch {}
  423.                 }
  424.                 else
  425.                 {
  426.                     runningIDEInstances[ candidateName ] = ide;
  427.                 }                       
  428.             }
  429.             return runningIDEInstances;
  430.         }
  431.         /// <summary>
  432.         /// Get a snapshot of the running object table (ROT).
  433.         /// </summary>
  434.         /// <returns>A hashtable mapping the name of the object in the ROT to the corresponding object</returns>
  435.         [STAThread]
  436.         public static Hashtable GetRunningObjectTable()
  437.         {
  438.             Hashtable result = new Hashtable();
  439.             int numFetched = 0;
  440.             IRunningObjectTable runningObjectTable;   
  441.             IEnumMoniker monikerEnumerator;
  442.             IMoniker[] monikers = new IMoniker[1];
  443.             GetRunningObjectTable(0, out runningObjectTable);    
  444.             runningObjectTable.EnumRunning(out monikerEnumerator);
  445.             monikerEnumerator.Reset();          
  446.             
  447.             while (monikerEnumerator.Next(1, monikers, new IntPtr(numFetched)) == 0)
  448.             {     
  449.                 IBindCtx ctx;
  450.                 CreateBindCtx(0, out ctx);     
  451.                     
  452.                 string runningObjectName;
  453.                 monikers[0].GetDisplayName(ctx, null, out runningObjectName);
  454.                 object runningObjectVal;  
  455.                 runningObjectTable.GetObject( monikers[0], out runningObjectVal); 
  456.                 result[ runningObjectName ] = runningObjectVal;
  457.             } 
  458.             return result;
  459.         }
  460.         public static string GetSolutionVersion(string solutionFullFileName) 
  461.         {
  462.             string version;
  463.             System.IO.StreamReader solutionStreamReader = null;
  464.             string firstLine;
  465.             string format;
  466.             
  467.             try
  468.             {
  469.                 solutionStreamReader = new System.IO.StreamReader(solutionFullFileName);
  470.                 do
  471.                 {
  472.                     firstLine = solutionStreamReader.ReadLine();
  473.                 }
  474.                 while (firstLine == "");
  475.                 
  476.                 format = firstLine.Substring(firstLine.LastIndexOf(" ")).Trim();
  477.         
  478.                 switch(format)
  479.                 {
  480.                     case "7.00":
  481.                         version = "VC70";
  482.                         break;
  483.                     case "8.00":
  484.                         version = "VC71";
  485.                         break;
  486.                     case "9.00":
  487.                         version = "VC80";
  488.                         break;
  489.                 
  490.                     case "10.00":
  491.                         version = "VC90";
  492.                         break;
  493.                     default:
  494.                         throw new ApplicationException("Unknown .sln version: " + format);
  495.                 }
  496.             }
  497.             finally
  498.             {
  499.                 if(solutionStreamReader != null) 
  500.                 {
  501.                     solutionStreamReader.Close();
  502.                 }
  503.             }
  504.             
  505.             return version;
  506.         }
  507.         public static string GetVSProgID(string version)
  508.         {
  509.             string progid = null;
  510.             switch(version)
  511.             {
  512.                 case "VC70":
  513.                     progid = "VisualStudio.DTE.7";
  514.                     break;
  515.                 case "VC71":
  516.                     progid = "VisualStudio.DTE.7.1";
  517.                     break;
  518.                 case "VC80":
  519.                     progid = "VisualStudio.DTE.8.0";
  520.                     break;
  521.                 
  522.                 case "VC90":
  523.                     progid = "VisualStudio.DTE.9.0";
  524.                     break;
  525.                 default:
  526.                     throw new ApplicationException("Can't handle VS version: " + version);
  527.             }
  528.             return progid;
  529.         }
  530.         public static bool SetProjectWorkingDir(object sol, string project_name, string working_dir)
  531.         {
  532.             bool made_change = false;
  533.             Console.WriteLine("Looking for project {0}...", project_name);
  534.             try
  535.             {
  536.                 object prjs = ViaCOM.GetProperty(sol, "Projects");
  537.                 object count = ViaCOM.GetProperty(prjs, "Count");
  538.                 for(int i = 1; i <= (int)count; ++i)
  539.                 {
  540.                     object[] prjItemArgs = { (object)i };
  541.                     object prj = ViaCOM.CallMethod(prjs, "Item", prjItemArgs);
  542.                     string name = (string)ViaCOM.GetProperty(prj, "Name");
  543.                     if (0 == string.Compare(name, project_name, ignore_case))
  544.                     {
  545.                         Console.WriteLine("Found project: {0}", project_name);
  546.                         Console.WriteLine("Setting working directory");
  547.                         string full_project_name = (string)ViaCOM.GetProperty(prj, "FullName");
  548.                         Console.WriteLine(full_project_name);
  549.                         // *NOTE:Mani Thanks to incompatibilities between different versions of the 
  550.                         // VCProjectEngine.dll assembly, we can't cast the objects recevied from the DTE to
  551.                         // the VCProjectEngine types from a different version than the one built 
  552.                         // with. ie, VisualStudio.DTE.7.1 objects can't be converted in a project built 
  553.                         // in VS 8.0. To avoid this problem, we can use the com object interfaces directly, 
  554.                         // without the type casting. Its tedious code, but it seems to work.
  555.                         // oCfgs should be assigned to a 'Project.Configurations' collection.
  556.                         object oCfgs = ViaCOM.GetProperty(ViaCOM.GetProperty(prj, "Object"), "Configurations");
  557.                         // oCount will be assigned to the number of configs present in oCfgs.
  558.                         object oCount = ViaCOM.GetProperty(oCfgs, "Count");
  559.                         for (int cfgIndex = 1; cfgIndex <= (int)oCount; ++cfgIndex)
  560.                         {
  561.                             object[] itemArgs = {(object)cfgIndex};
  562.                             object oCfg = ViaCOM.CallMethod(oCfgs, "Item", itemArgs);
  563.                             object oDebugSettings = ViaCOM.GetProperty(oCfg, "DebugSettings");
  564.                             ViaCOM.SetProperty(oDebugSettings, "WorkingDirectory", (object)working_dir);
  565.                         }
  566.                         break;
  567.                     }
  568.                 }
  569.                 made_change = true;
  570.             }
  571.             catch( Exception e )
  572.             {
  573.                 Console.WriteLine(e.Message);
  574.                 Console.WriteLine("Failed to set working dir for project, {0}.", project_name);
  575.             }
  576.             return made_change;
  577.         }
  578.         public static bool SetStartupProject(string startup_project)
  579.         {
  580.             bool result = false;
  581.             try
  582.             {
  583.                 // You need the 'unique name of the project to set StartupProjects.
  584.                 // find the project by generic name.
  585.                 Console.WriteLine("Trying to set "{0}" to the startup project", startup_project);
  586.                 object prjs = ViaCOM.GetProperty(solution, "Projects");
  587.                 object count = ViaCOM.GetProperty(prjs, "Count");
  588.                 for (int i = 1; i <= (int)count; ++i)
  589.                 {
  590.                     object[] itemArgs = { (object)i };
  591.                     object prj = ViaCOM.CallMethod(prjs, "Item", itemArgs);
  592.                     object prjName = ViaCOM.GetProperty(prj, "Name");
  593.                     if (0 == string.Compare((string)prjName, startup_project, ignore_case))
  594.                     {
  595.                         object solBuild = ViaCOM.GetProperty(solution, "SolutionBuild");
  596.                         ViaCOM.SetProperty(solBuild, "StartupProjects", ViaCOM.GetProperty(prj, "UniqueName"));
  597.                         Console.WriteLine("  Success!");
  598.                         result = true;
  599.                         break;
  600.                     }
  601.                 }
  602.                 if (result == false)
  603.                 {
  604.                     Console.WriteLine("  Could not find project "{0}" in the solution.", startup_project);
  605.                 }
  606.             }
  607.             catch (Exception e)
  608.             {
  609.                 Console.WriteLine("  Failed to set the startup project!");
  610.                 Console.WriteLine(e.Message);
  611.             }
  612.             return result;
  613.         }
  614.         public static bool SetActiveConfig(string config)
  615.         {
  616.             bool result = false;
  617.             try
  618.             {
  619.                 Console.WriteLine("Trying to set active config to "{0}"", config);
  620.                 object solBuild = ViaCOM.GetProperty(solution, "SolutionBuild");
  621.                 object solCfgs = ViaCOM.GetProperty(solBuild, "SolutionConfigurations");
  622.                 object[] itemArgs = { (object)config };
  623.                 object solCfg = ViaCOM.CallMethod(solCfgs, "Item", itemArgs);
  624.                 ViaCOM.CallMethod(solCfg, "Activate", null);
  625.                 Console.WriteLine("  Success!");
  626.                 result = true;
  627.             }
  628.             catch (Exception e)
  629.             {
  630.                 Console.WriteLine("  Failed to set "{0}" as the active config.", config);
  631.                 Console.WriteLine(e.Message);
  632.             }
  633.             return result;
  634.         }
  635.     }
  636. }