├── images
└── icon.png
├── NuGet
├── package.cmd
└── VsIdeBuild.nuspec
├── VsIdeBuild.sln
├── VsIdeBuild
├── VsBuilderResults.cs
├── VsBuilderOptions.cs
├── MessageFilter.cs
└── VsBuilder.cs
├── Properties
└── AssemblyInfo.cs
├── Program.cs
├── .gitignore
├── VsIdeBuild.csproj
├── readme.md
└── AVSP.ConsoleSupport
├── ConsoleHelper.cs
├── SimpleArguments.cs
└── SimpleArgumentsReader.cs
/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ninjaoxygen/VsIdeBuild/HEAD/images/icon.png
--------------------------------------------------------------------------------
/NuGet/package.cmd:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | ECHO Deleting old packages...
4 |
5 | DEL /F *.nupkg
6 |
7 | SETLOCAL enabledelayedexpansion
8 |
9 | ECHO Creating packages
10 | FOR %%I IN (*.nuspec) DO (
11 | nuget pack "%%I"
12 | IF NOT "!errorlevel!"=="0" SET ERROR=Failed to nuget pack "%%~fI" && GOTO :fail
13 | )
14 |
15 | ECHO Success
16 |
17 | ECHO To publish to nuget use
18 | ECHO nuget push *.nupkg -Source https://api.nuget.org/v3/index.json
19 |
20 | EXIT /B 0
21 |
22 | :fail
23 |
24 | ECHO ****** Build failed! ******
25 | ECHO %ERROR%
26 | EXIT /B 1
27 |
--------------------------------------------------------------------------------
/NuGet/VsIdeBuild.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | VsIdeBuild
5 | 1.0.1
6 | ChrisPoole
7 | ChrisPoole
8 | MIT
9 | https://github.com/ninjaoxygen/VsIdeBuild
10 | images\icon.png
11 | false
12 | VsIdeBuild is a command line tool to automate the Visual Studio 2008 IDE to build solutions.
13 | Initial release
14 | Copyright 2017 - 2020 AVSP Ltd
15 | VsIdeBuild crestron simpl# simpl#pro avsp
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/VsIdeBuild.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 10.00
3 | # Visual Studio 2008
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VsIdeBuild", "VsIdeBuild.csproj", "{4791B3F0-B02E-4F24-A33E-3C5C31E5B472}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Any CPU = Debug|Any CPU
9 | Release|Any CPU = Release|Any CPU
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {4791B3F0-B02E-4F24-A33E-3C5C31E5B472}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
13 | {4791B3F0-B02E-4F24-A33E-3C5C31E5B472}.Debug|Any CPU.Build.0 = Debug|Any CPU
14 | {4791B3F0-B02E-4F24-A33E-3C5C31E5B472}.Release|Any CPU.ActiveCfg = Release|Any CPU
15 | {4791B3F0-B02E-4F24-A33E-3C5C31E5B472}.Release|Any CPU.Build.0 = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | EndGlobal
21 |
--------------------------------------------------------------------------------
/VsIdeBuild/VsBuilderResults.cs:
--------------------------------------------------------------------------------
1 | #region License
2 |
3 | /*
4 | * File: Program.cs
5 | *
6 | * The MIT License
7 | *
8 | * Copyright © 2017 AVSP Ltd
9 | *
10 | * Permission is hereby granted, free of charge, to any person obtaining a copy
11 | * of this software and associated documentation files (the "Software"), to deal
12 | * in the Software without restriction, including without limitation the rights
13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | * copies of the Software, and to permit persons to whom the Software is
15 | * furnished to do so, subject to the following conditions:
16 | *
17 | * The above copyright notice and this permission notice shall be included in
18 | * all copies or substantial portions of the Software.
19 | *
20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 | * THE SOFTWARE.
27 | */
28 |
29 | #endregion License
30 |
31 | namespace VsIdeBuild.VsBuilderLibrary
32 | {
33 | public class VsBuilderResults
34 | {
35 | public int TotalBuilds;
36 | public bool Failed;
37 | }
38 | }
--------------------------------------------------------------------------------
/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("VsIdeBuild")]
8 | [assembly: AssemblyDescription("Visual Studio 2008 Solution Builder")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("AVSP Ltd")]
11 | [assembly: AssemblyProduct("VsIdeBuild")]
12 | [assembly: AssemblyCopyright("Copyright © 2017 - 2020 Chris Poole")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("bb967cbb-33f0-4095-9477-0899528d0c63")]
23 |
24 | // Version information for an assembly consists of the following four values:
25 | //
26 | // Major Version
27 | // Minor Version
28 | // Build Number
29 | // Revision
30 | //
31 | // You can specify all the values or you can default the Build and Revision Numbers
32 | // by using the '*' as shown below:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("1.0.*")]
35 |
36 | // when AssemblyFileVersion is ommitted, it will default to the AssemblyVersion
37 | //[assembly: AssemblyFileVersion("1.0.0.0")]
--------------------------------------------------------------------------------
/Program.cs:
--------------------------------------------------------------------------------
1 | #region License
2 |
3 | /*
4 | * File: Program.cs
5 | *
6 | * The MIT License
7 | *
8 | * Copyright © 2017 - 2020 AVSP Ltd
9 | *
10 | * Permission is hereby granted, free of charge, to any person obtaining a copy
11 | * of this software and associated documentation files (the "Software"), to deal
12 | * in the Software without restriction, including without limitation the rights
13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | * copies of the Software, and to permit persons to whom the Software is
15 | * furnished to do so, subject to the following conditions:
16 | *
17 | * The above copyright notice and this permission notice shall be included in
18 | * all copies or substantial portions of the Software.
19 | *
20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 | * THE SOFTWARE.
27 | */
28 |
29 | #endregion License
30 |
31 | using System;
32 | using System.Diagnostics;
33 | using AVSP.ConsoleSupport;
34 | using VsIdeBuild.VsBuilderLibrary;
35 |
36 | namespace VsIdeBuild
37 | {
38 | internal class Program
39 | {
40 | private static int Run(SimpleArguments arguments)
41 | {
42 | VsBuilderOptions options = new VsBuilderOptions();
43 |
44 | // parse command line arguments into options
45 | SimpleArgumentsReader.ArgumentsToObject(arguments, options);
46 |
47 | if (options.Solution == null || options.Solution.Length == 0)
48 | {
49 | Console.Error.WriteLine(@"ERROR: solution must be specified with -solution c:\path\to\solution.sln");
50 | return 1;
51 | }
52 |
53 | VsBuilder builder = new VsBuilder();
54 |
55 | int result = builder.Run(options);
56 |
57 | if ((result != 0) || builder.Results.Failed)
58 | {
59 | Console.Error.WriteLine("ERROR: some builds failed, check output");
60 | return 1;
61 | }
62 |
63 | Console.WriteLine("Success: all okay");
64 | return 0;
65 | }
66 |
67 | // STAThread needed for COM
68 | [STAThread]
69 | private static int Main(string[] args)
70 | {
71 | return ConsoleHelper.RunProgram(args, Run);
72 | }
73 | }
74 | }
--------------------------------------------------------------------------------
/VsIdeBuild/VsBuilderOptions.cs:
--------------------------------------------------------------------------------
1 | #region License
2 |
3 | /*
4 | * File: VsBuilderOptions.cs
5 | *
6 | * The MIT License
7 | *
8 | * Copyright © 2017 - 2020 AVSP Ltd
9 | * Copyright © 2020 Oliver Hall, Ultamation Ltd
10 | *
11 | * Permission is hereby granted, free of charge, to any person obtaining a copy
12 | * of this software and associated documentation files (the "Software"), to deal
13 | * in the Software without restriction, including without limitation the rights
14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | * copies of the Software, and to permit persons to whom the Software is
16 | * furnished to do so, subject to the following conditions:
17 | *
18 | * The above copyright notice and this permission notice shall be included in
19 | * all copies or substantial portions of the Software.
20 | *
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 | * THE SOFTWARE.
28 | */
29 |
30 | #endregion License
31 |
32 | namespace VsIdeBuild.VsBuilderLibrary
33 | {
34 | ///
35 | /// Configuration options POCO for the VsBuilder build process
36 | ///
37 | public class VsBuilderOptions
38 | {
39 | ///
40 | /// Show the VS gui in the opened project, allow user control
41 | ///
42 | public bool Debug { get; set; }
43 |
44 | ///
45 | /// Clean is only available for the entire solution
46 | ///
47 | public bool Clean { get; set; }
48 |
49 | ///
50 | /// Perform additional checks to ensure the Crestron SDK plugin loaded and completed
51 | ///
52 | public bool Crestron { get; set; }
53 |
54 | ///
55 | /// Build Solution in every available configuration
56 | ///
57 | public bool BuildAll { get; set; }
58 |
59 | ///
60 | /// Limit build to a single solution configuration, e.g. Debug, Release
61 | ///
62 | public string BuildSolutionConfiguration { get; set; }
63 |
64 | ///
65 | /// Limit build to a single project - BuildSolutionConfiguration MUST also be specified
66 | ///
67 | public string BuildProject { get; set; }
68 |
69 | ///
70 | /// Output ProjectContexts, useful to get necessary command lines for build
71 | ///
72 | public bool ShowProjectContexts { get; set; }
73 |
74 | ///
75 | /// Output ProjectOutputs, useful to get configuration information
76 | ///
77 | public bool ShowProjectOutputs { get; set; }
78 |
79 | ///
80 | /// Give detailed build output
81 | ///
82 | public bool ShowBuild { get; set; }
83 |
84 | ///
85 | /// Filepath of Visual Studio 2008 solution file
86 | ///
87 | public string Solution { get; set; }
88 | }
89 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 | [Dd]ebug/
11 | [Dd]ebugPublic/
12 | [Rr]elease/
13 | [Rr]eleases/
14 | x64/
15 | x86/
16 | build/
17 | bld/
18 | [Bb]in/
19 | [Oo]bj/
20 |
21 | # Roslyn cache directories
22 | *.ide/
23 |
24 | # MSTest test Results
25 | [Tt]est[Rr]esult*/
26 | [Bb]uild[Ll]og.*
27 |
28 | #NUNIT
29 | *.VisualState.xml
30 | TestResult.xml
31 |
32 | # Build Results of an ATL Project
33 | [Dd]ebugPS/
34 | [Rr]eleasePS/
35 | dlldata.c
36 |
37 | *_i.c
38 | *_p.c
39 | *_i.h
40 | *.ilk
41 | *.meta
42 | *.obj
43 | *.pch
44 | *.pdb
45 | *.pgc
46 | *.pgd
47 | *.rsp
48 | *.sbr
49 | *.tlb
50 | *.tli
51 | *.tlh
52 | *.tmp
53 | *.tmp_proj
54 | *.log
55 | *.vspscc
56 | *.vssscc
57 | .builds
58 | *.pidb
59 | *.svclog
60 | *.scc
61 |
62 | # Chutzpah Test files
63 | _Chutzpah*
64 |
65 | # Visual C++ cache files
66 | ipch/
67 | *.aps
68 | *.ncb
69 | *.opensdf
70 | *.sdf
71 | *.cachefile
72 |
73 | # Visual Studio profiler
74 | *.psess
75 | *.vsp
76 | *.vspx
77 |
78 | # TFS 2012 Local Workspace
79 | $tf/
80 |
81 | # Guidance Automation Toolkit
82 | *.gpState
83 |
84 | # ReSharper is a .NET coding add-in
85 | _ReSharper*/
86 | *.[Rr]e[Ss]harper
87 | *.DotSettings.user
88 |
89 | # JustCode is a .NET coding addin-in
90 | .JustCode
91 |
92 | # TeamCity is a build add-in
93 | _TeamCity*
94 |
95 | # DotCover is a Code Coverage Tool
96 | *.dotCover
97 |
98 | # NCrunch
99 | _NCrunch_*
100 | .*crunch*.local.xml
101 |
102 | # MightyMoose
103 | *.mm.*
104 | AutoTest.Net/
105 |
106 | # Web workbench (sass)
107 | .sass-cache/
108 |
109 | # Installshield output folder
110 | [Ee]xpress/
111 |
112 | # DocProject is a documentation generator add-in
113 | DocProject/buildhelp/
114 | DocProject/Help/*.HxT
115 | DocProject/Help/*.HxC
116 | DocProject/Help/*.hhc
117 | DocProject/Help/*.hhk
118 | DocProject/Help/*.hhp
119 | DocProject/Help/Html2
120 | DocProject/Help/html
121 |
122 | # Click-Once directory
123 | publish/
124 |
125 | # Publish Web Output
126 | *.[Pp]ublish.xml
127 | *.azurePubxml
128 | # TODO: Comment out the next line if you want to keep your passwords hidden
129 | *.pubxml
130 |
131 | # NuGet Packages
132 | *.nupkg
133 | # The packages folder can be ignored because of Package Restore
134 | **/packages/*
135 | # except build/, which is used as an MSBuild target.
136 | !**/packages/build/
137 | # If using the old MSBuild-Integrated Package Restore, uncomment this:
138 | #!**/packages/repositories.config
139 |
140 | # Windows Azure Build Output
141 | csx/
142 | *.build.csdef
143 |
144 | # Windows Store app package directory
145 | AppPackages/
146 |
147 | # Others
148 | sql/
149 | *.Cache
150 | ClientBin/
151 | [Ss]tyle[Cc]op.*
152 | ~$*
153 | *~
154 | *.dbmdl
155 | *.dbproj.schemaview
156 | *.pfx
157 | *.publishsettings
158 | node_modules/
159 |
160 | # RIA/Silverlight projects
161 | Generated_Code/
162 |
163 | # Backup & report files from converting an old project file
164 | # to a newer Visual Studio version. Backup files are not needed,
165 | # because we have git ;-)
166 | _UpgradeReport_Files/
167 | Backup*/
168 | UpgradeLog*.XML
169 | UpgradeLog*.htm
170 |
171 | # SQL Server files
172 | *.mdf
173 | *.ldf
174 |
175 | # Business Intelligence projects
176 | *.rdl.data
177 | *.bim.layout
178 | *.bim_*.settings
179 |
180 | # Microsoft Fakes
181 | FakesAssemblies/
182 |
--------------------------------------------------------------------------------
/VsIdeBuild/MessageFilter.cs:
--------------------------------------------------------------------------------
1 | #region License
2 |
3 | /*
4 | * File: MessageFilter.cs
5 | *
6 | * Derived from Microsoft sample code, see below for source
7 | *
8 | * Used under MICROSOFT LIMITED PUBLIC LICENSE
9 | *
10 | */
11 |
12 | #endregion License
13 |
14 | using System;
15 | using System.Runtime.InteropServices;
16 |
17 | namespace VsIdeBuild.VsBuilderLibrary
18 | {
19 | ///
20 | /// See "How to: Fix 'Application is Busy' and 'Call was Rejected By Callee' Errors"
21 | /// https://msdn.microsoft.com/en-us/library/ms228772.aspx
22 | ///
23 |
24 | internal class MessageFilter : IOleMessageFilter
25 | {
26 | //
27 | // Class containing the IOleMessageFilter
28 | // thread error-handling functions.
29 |
30 | // Start the filter.
31 | public static void Register()
32 | {
33 | IOleMessageFilter newFilter = new MessageFilter();
34 | IOleMessageFilter oldFilter = null;
35 | CoRegisterMessageFilter(newFilter, out oldFilter);
36 | }
37 |
38 | // Done with the filter, close it.
39 | public static void Revoke()
40 | {
41 | IOleMessageFilter oldFilter = null;
42 | CoRegisterMessageFilter(null, out oldFilter);
43 | }
44 |
45 | //
46 | // IOleMessageFilter functions.
47 | // Handle incoming thread requests.
48 | int IOleMessageFilter.HandleInComingCall(int dwCallType,
49 | System.IntPtr hTaskCaller, int dwTickCount, System.IntPtr
50 | lpInterfaceInfo)
51 | {
52 | //Return the flag SERVERCALL_ISHANDLED.
53 | return 0;
54 | }
55 |
56 | // Thread call was rejected, so try again.
57 | int IOleMessageFilter.RetryRejectedCall(System.IntPtr
58 | hTaskCallee, int dwTickCount, int dwRejectType)
59 | {
60 | if (dwRejectType == 2)
61 | // flag = SERVERCALL_RETRYLATER.
62 | {
63 | // Retry the thread call immediately if return >=0 &
64 | // <100.
65 | return 99;
66 | }
67 | // Too busy; cancel call.
68 | return -1;
69 | }
70 |
71 | int IOleMessageFilter.MessagePending(System.IntPtr hTaskCallee,
72 | int dwTickCount, int dwPendingType)
73 | {
74 | //Return the flag PENDINGMSG_WAITDEFPROCESS.
75 | return 2;
76 | }
77 |
78 | // Implement the IOleMessageFilter interface.
79 | [DllImport("Ole32.dll")]
80 | private static extern int
81 | CoRegisterMessageFilter(IOleMessageFilter newFilter, out
82 | IOleMessageFilter oldFilter);
83 | }
84 |
85 | [ComImport(), Guid("00000016-0000-0000-C000-000000000046"),
86 | InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
87 | internal interface IOleMessageFilter
88 | {
89 | [PreserveSig]
90 | int HandleInComingCall(
91 | int dwCallType,
92 | IntPtr hTaskCaller,
93 | int dwTickCount,
94 | IntPtr lpInterfaceInfo);
95 |
96 | [PreserveSig]
97 | int RetryRejectedCall(
98 | IntPtr hTaskCallee,
99 | int dwTickCount,
100 | int dwRejectType);
101 |
102 | [PreserveSig]
103 | int MessagePending(
104 | IntPtr hTaskCallee,
105 | int dwTickCount,
106 | int dwPendingType);
107 | }
108 | }
--------------------------------------------------------------------------------
/VsIdeBuild.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 9.0.30729
7 | 2.0
8 | {4791B3F0-B02E-4F24-A33E-3C5C31E5B472}
9 | Exe
10 | Properties
11 | VsIdeBuild
12 | VsIdeBuild
13 | v3.5
14 | 512
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 | False
36 | ..\..\..\..\..\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\PublicAssemblies\EnvDTE.dll
37 |
38 |
39 | False
40 | ..\..\..\..\..\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\PublicAssemblies\EnvDTE80.dll
41 |
42 |
43 | False
44 | ..\..\..\..\..\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\PublicAssemblies\EnvDTE90.dll
45 |
46 |
47 |
48 | 3.5
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
73 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # VsIdeBuild
2 |
3 | ## About
4 |
5 | VsIdeBuild is a command line tool to automate the Visual Studio 2008 IDE to build solutions.
6 | This is necessary when GUI IDE plugins are required for the build process, for example when using Crestron's SDK.
7 |
8 | ## Downloads
9 |
10 | The latest binary release is available as a nuget package from https://www.nuget.org/packages/VsIdeBuild/
11 |
12 | Other release binaries are available from https://github.com/ninjaoxygen/VsIdeBuild/releases
13 |
14 | ## Contact
15 |
16 | E-mail: chris@avsp.co.uk
17 |
18 | ## Copyright
19 |
20 | VsIdeBuild is Copyright (C) 2017 - 2020 AVSP Ltd
21 |
22 | ## Contributors
23 |
24 | Many thanks for contributions from:
25 |
26 | Oliver Hall, Ultamation Ltd
27 |
28 | ## Command line parameters:
29 |
30 | ~~~
31 | -Solution
32 | Specify Visual Studio 2008 .sln file to work on. Relative or absolute paths are acceptable, the .sln can be omitted.
33 |
34 | -Clean
35 | Cleans before build. This does not work with BuildProject - VS2008 only supports simple cleaning of enitre solution configurations.
36 |
37 | -BuildAll
38 | Builds all solution configurations, using their project build settings for each configuration.
39 |
40 | -BuildSolutionConfiguration
41 | Build a single solution configuration, e.g. Debug or Release.
42 |
43 | -BuildProject
44 | Build a single project, also needs -BuildSolutionConfiguration to be specified.
45 |
46 | -ShowProjectContexts
47 | Outputs all available project names and configurations.
48 |
49 | -ShowProjectOutputs
50 | Outputs all properties of all projects in the solution
51 |
52 | -ShowBuild
53 | Returns all build output from VS2008 and the Crestron SDK plugin, sandbox failures will show up here
54 |
55 | -Debug
56 | Will not hide the Visual Studio window that is opened, will allow user interaction with that window.
57 |
58 | -Crestron
59 | Enable checks to ensure the Crestron SDK plugin intialised and completed. Without this option, only Crestron sandbox failures will be detected.
60 | ~~~
61 |
62 | ## Examples
63 |
64 | Build only the Debug configuration of project ConsoleApp in Sample.sln
65 | ~~~
66 | VsIdeBuild -Solution "C:\Test\Sample.sln" -BuildSolutionConfiguration "Debug" -BuildProject "ConsoleApp"
67 | ~~~
68 |
69 | Clean then build all configurations of all projects in Sample.sln
70 | ~~~
71 | VsIdeBuild -Solution "C:\Test\Sample.sln" -Clean -BuildAll
72 | ~~~
73 |
74 | ## Return value
75 |
76 | 0 on success
77 |
78 | >=1 on failure
79 |
80 | ## License
81 |
82 | The MIT License
83 |
84 | Copyright (C) 2017 - 2020 AVSP Ltd
85 |
86 | Permission is hereby granted, free of charge, to any person obtaining a copy
87 | of this software and associated documentation files (the "Software"), to deal
88 | in the Software without restriction, including without limitation the rights
89 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
90 | copies of the Software, and to permit persons to whom the Software is
91 | furnished to do so, subject to the following conditions:
92 |
93 | The above copyright notice and this permission notice shall be included in
94 | all copies or substantial portions of the Software.
95 |
96 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
97 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
98 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
99 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
100 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
101 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
102 | THE SOFTWARE.
103 |
--------------------------------------------------------------------------------
/AVSP.ConsoleSupport/ConsoleHelper.cs:
--------------------------------------------------------------------------------
1 | #region License
2 |
3 | /*
4 | * File: ConsoleHelper.cs
5 | *
6 | * The MIT License
7 | *
8 | * Copyright © 2017 AVSP Ltd
9 | *
10 | * Permission is hereby granted, free of charge, to any person obtaining a copy
11 | * of this software and associated documentation files (the "Software"), to deal
12 | * in the Software without restriction, including without limitation the rights
13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | * copies of the Software, and to permit persons to whom the Software is
15 | * furnished to do so, subject to the following conditions:
16 | *
17 | * The above copyright notice and this permission notice shall be included in
18 | * all copies or substantial portions of the Software.
19 | *
20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 | * THE SOFTWARE.
27 | */
28 |
29 | #endregion License
30 |
31 | using System;
32 | using System.Collections.Generic;
33 | using System.Diagnostics;
34 | using System.Reflection;
35 |
36 | namespace AVSP.ConsoleSupport
37 | {
38 | ///
39 | /// Console support library for banner, copyright, version, command line arguments
40 | ///
41 | internal static class ConsoleHelper
42 | {
43 | public delegate int RunFunction(SimpleArguments arguments);
44 |
45 | public static SimpleArguments Arguments { get; private set; }
46 |
47 | ///
48 | /// Runs a console app with parsed options, sensible exit codes, exception handler
49 | ///
50 | /// Example:
51 | /// private static int Main(string[] args)
52 | /// {
53 | /// return ConsoleHelper.RunProgram(args, Run);
54 | /// }
55 | ///
56 | /// arguments from Main()
57 | /// delegate to run app
58 | /// program exit code
59 | public static int RunProgram(IList args, RunFunction run)
60 | {
61 | try
62 | {
63 | ConsoleHelper.Startup(args);
64 | ConsoleHelper.WriteBanner();
65 |
66 | int returnValue = run(ConsoleHelper.Arguments);
67 |
68 | return (Environment.ExitCode == 0) ? returnValue : Environment.ExitCode;
69 | }
70 | catch (Exception e)
71 | {
72 | Console.Error.WriteLine(e.Message);
73 | Trace.TraceError(e.ToString());
74 |
75 | return Environment.ExitCode != 0
76 | ? Environment.ExitCode : 100;
77 | }
78 | }
79 |
80 | public static void Startup(IList args)
81 | {
82 | Arguments = new SimpleArguments(args);
83 |
84 | // enable trace with v parameter
85 | if (Arguments.GetFlag("v"))
86 | {
87 | Trace.Listeners.Add(new ConsoleTraceListener(true));
88 | }
89 | }
90 |
91 | public static string GetProductVersion()
92 | {
93 | return Assembly.GetExecutingAssembly().GetName().Version.ToString();
94 | }
95 |
96 | public static string GetProductName()
97 | {
98 | return Assembly.GetExecutingAssembly().GetName().Name;
99 | }
100 |
101 | public static string GetDescription()
102 | {
103 | //Type of attribute that is desired
104 | Type type = typeof(AssemblyDescriptionAttribute);
105 |
106 | //Is there an attribute of this type already defined?
107 | if (AssemblyDescriptionAttribute.IsDefined(Assembly.GetExecutingAssembly(), type))
108 | {
109 | //if there is, get attribute of desired type
110 | AssemblyDescriptionAttribute assemblyDescriptionAttribute = (AssemblyDescriptionAttribute)AssemblyDescriptionAttribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), type);
111 |
112 | return assemblyDescriptionAttribute.Description;
113 | }
114 |
115 | return null;
116 | }
117 |
118 | public static string GetCopyright()
119 | {
120 | //Type of attribute that is desired
121 | Type type = typeof(AssemblyCopyrightAttribute);
122 |
123 | //Is there an attribute of this type already defined?
124 | if (AssemblyCopyrightAttribute.IsDefined(Assembly.GetExecutingAssembly(), type))
125 | {
126 | //if there is, get attribute of desired type
127 | AssemblyCopyrightAttribute assemblyCopyrightAttribute = (AssemblyCopyrightAttribute)AssemblyCopyrightAttribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), type);
128 |
129 | return assemblyCopyrightAttribute.Copyright;
130 | }
131 |
132 | return null;
133 | }
134 |
135 | public static void WriteBanner()
136 | {
137 | Console.WriteLine(GetProductName() + " v" + GetProductVersion());
138 | Console.WriteLine(GetCopyright());
139 | Console.WriteLine();
140 | }
141 | }
142 | }
--------------------------------------------------------------------------------
/AVSP.ConsoleSupport/SimpleArguments.cs:
--------------------------------------------------------------------------------
1 | #region License
2 |
3 | /*
4 | * File: SimpleArguments.cs
5 | *
6 | * The MIT License
7 | *
8 | * Copyright © 2017 AVSP Ltd
9 | *
10 | * Permission is hereby granted, free of charge, to any person obtaining a copy
11 | * of this software and associated documentation files (the "Software"), to deal
12 | * in the Software without restriction, including without limitation the rights
13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | * copies of the Software, and to permit persons to whom the Software is
15 | * furnished to do so, subject to the following conditions:
16 | *
17 | * The above copyright notice and this permission notice shall be included in
18 | * all copies or substantial portions of the Software.
19 | *
20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 | * THE SOFTWARE.
27 | */
28 |
29 | #endregion License
30 |
31 | using System;
32 | using System.Collections.Generic;
33 | using System.Collections.ObjectModel;
34 | using System.Linq;
35 |
36 | namespace AVSP.ConsoleSupport
37 | {
38 | ///
39 | /// Handles sets of arguments specified with a - and an optional parameter for each argument when no dash given
40 | ///
41 | public class SimpleArguments
42 | {
43 | protected Dictionary argumentValues = new Dictionary();
44 | protected Dictionary flags = new Dictionary();
45 |
46 | public ReadOnlyCollection Arguments { get; protected set; }
47 |
48 | public SimpleArguments()
49 | {
50 | Arguments = new List().AsReadOnly();
51 | }
52 |
53 | ///
54 | /// Constructor which parses command line arguments
55 | ///
56 | /// Args array from Program.Main()
57 | public SimpleArguments(IList args)
58 | {
59 | Parse(args);
60 | }
61 |
62 | ///
63 | /// Set default value for an argument, will not create a flag
64 | ///
65 | /// Name of argument to set value for
66 | /// Value to set argument to
67 | public void SetDefault(string argumentName, string value)
68 | {
69 | if (!argumentValues.ContainsKey(argumentName))
70 | {
71 | argumentValues[argumentName] = value;
72 | }
73 | }
74 |
75 | ///
76 | /// Parse a list of argument values, e.g. { "-argumentname", "argumentvalue", "-flagtoset" }
77 | ///
78 | /// List of arguments to parse
79 | public void Parse(IList args)
80 | {
81 | // list of non-option arguments
82 | List arguments = new List();
83 |
84 | string lastArgumentName = null;
85 |
86 | foreach (string arg in args)
87 | {
88 | if (arg.StartsWith("-"))
89 | {
90 | lastArgumentName = arg.Substring(1).ToLower();
91 | flags[lastArgumentName] = true;
92 | }
93 | else
94 | {
95 | if (lastArgumentName != null && lastArgumentName.Length > 0)
96 | {
97 | argumentValues[lastArgumentName] = arg;
98 | lastArgumentName = null;
99 | }
100 | else
101 | {
102 | arguments.Add(arg);
103 | }
104 | }
105 | }
106 |
107 | Arguments = arguments.AsReadOnly();
108 | }
109 |
110 | ///
111 | /// Get the value of a passed argument, or the default
112 | ///
113 | /// Name of argument to set value for
114 | /// string value of argument
115 | public string GetValue(string argumentName)
116 | {
117 | string value;
118 |
119 | argumentValues.TryGetValue(argumentName.ToLower(), out value);
120 |
121 | return value;
122 | }
123 |
124 | ///
125 | /// Get whether a flag was passed
126 | ///
127 | /// Name of argument to check for
128 | /// true when argument was passed
129 | public bool GetFlag(string argumentName)
130 | {
131 | return flags.ContainsKey(argumentName.ToLower());
132 | }
133 |
134 | ///
135 | /// Get list of values in a comma-separated option
136 | ///
137 | /// argument to retrieve
138 | /// list of string contained in argument
139 | public IEnumerable GetList(string argumentName)
140 | {
141 | string value;
142 | char[] charSplit = new char[] { ',' };
143 |
144 | if (argumentValues.TryGetValue(argumentName.ToLower(), out value))
145 | {
146 | return value.Split(charSplit, StringSplitOptions.RemoveEmptyEntries);
147 | }
148 |
149 | return Enumerable.Empty();
150 | }
151 | }
152 | }
--------------------------------------------------------------------------------
/AVSP.ConsoleSupport/SimpleArgumentsReader.cs:
--------------------------------------------------------------------------------
1 | #region License
2 |
3 | /*
4 | * File: SimpleArgumentsReader.cs
5 | *
6 | * The MIT License
7 | *
8 | * Copyright © 2017 AVSP Ltd
9 | *
10 | * Permission is hereby granted, free of charge, to any person obtaining a copy
11 | * of this software and associated documentation files (the "Software"), to deal
12 | * in the Software without restriction, including without limitation the rights
13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | * copies of the Software, and to permit persons to whom the Software is
15 | * furnished to do so, subject to the following conditions:
16 | *
17 | * The above copyright notice and this permission notice shall be included in
18 | * all copies or substantial portions of the Software.
19 | *
20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 | * THE SOFTWARE.
27 | */
28 |
29 | #endregion License
30 |
31 | using System;
32 | using System.Collections.Generic;
33 | using System.Diagnostics;
34 | using System.Reflection;
35 |
36 | namespace AVSP.ConsoleSupport
37 | {
38 | ///
39 | /// Reads arguments into POCOs, supports fields or properties of int, string, int[], string[], other type may work too
40 | ///
41 | public static class SimpleArgumentsReader
42 | {
43 | private static Type boolType = typeof(bool);
44 |
45 | ///
46 | /// Read a set of command line arguments into the properties or fields in a POCO
47 | ///
48 | /// source list of command line arguments, like the array from Main()
49 | /// destination POCO to set values in
50 | public static void ArgumentsToObject(IList args, object value)
51 | {
52 | SimpleArguments arguments = new SimpleArguments(args);
53 | ArgumentsToObject(arguments, value);
54 | }
55 |
56 | ///
57 | /// Read set of parsed SimpleArguments into the properties or fields in a POCO
58 | ///
59 | /// SimpleArguments objects with source values
60 | ///
61 | public static void ArgumentsToObject(SimpleArguments arguments, object value)
62 | {
63 | char[] commaSplit = new char[] { ',' };
64 |
65 | Type t = value.GetType();
66 |
67 | FieldInfo[] fields = t.GetFields(BindingFlags.Public | BindingFlags.Instance);
68 |
69 | foreach (FieldInfo field in fields)
70 | {
71 | MemberInfo m = field;
72 |
73 | try
74 | {
75 | if (field.FieldType == boolType)
76 | {
77 | field.SetValue(value, arguments.GetFlag(field.Name));
78 | }
79 | else
80 | {
81 | string valueString = arguments.GetValue(field.Name);
82 |
83 | if (valueString != null)
84 | {
85 | field.SetValue(value, Convert.ChangeType(valueString, field.FieldType));
86 | }
87 | }
88 | }
89 | catch (Exception ex)
90 | {
91 | throw new ArgumentException("ERROR: exception occurred whilst parsing argument " + field.Name, ex);
92 | }
93 | }
94 |
95 | PropertyInfo[] properties = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);
96 |
97 | foreach (PropertyInfo property in properties)
98 | {
99 | try
100 | {
101 | if (property.PropertyType == boolType)
102 | {
103 | // handle a normal bool, if the flag was passed, set it to true, if not, false
104 | property.SetValue(value, arguments.GetFlag(property.Name), null);
105 | }
106 | else if (property.PropertyType.BaseType.FullName == "System.Array")
107 | {
108 | // handle comma separated arrays
109 | string valueString = arguments.GetValue(property.Name);
110 |
111 | if (valueString != null)
112 | {
113 | string[] valueStringArray = valueString.Split(commaSplit);
114 |
115 | int arrayLength = valueStringArray.Length;
116 |
117 | Type elementType = property.PropertyType.GetElementType();
118 |
119 | // build the array
120 | Array y = Array.CreateInstance(elementType, arrayLength);
121 |
122 | for (int i = 0; i < arrayLength; i++)
123 | {
124 | // set an element
125 | y.SetValue(Convert.ChangeType(valueStringArray[i], elementType), i);
126 | }
127 |
128 | // put the array into the property
129 | property.SetValue(value, y, null);
130 | }
131 | }
132 | else
133 | {
134 | string valueString = arguments.GetValue(property.Name);
135 |
136 | if (valueString != null)
137 | {
138 | property.SetValue(value, Convert.ChangeType(valueString, property.PropertyType), null);
139 | }
140 | }
141 | }
142 | catch (Exception ex)
143 | {
144 | throw new ArgumentException("ERROR: exception occurred whilst parsing argument " + property.Name, ex);
145 | }
146 | }
147 | }
148 | }
149 | }
--------------------------------------------------------------------------------
/VsIdeBuild/VsBuilder.cs:
--------------------------------------------------------------------------------
1 | #region License
2 |
3 | /*
4 | * File: VsBuilder.cs
5 | *
6 | * The MIT License
7 | *
8 | * Copyright © 2017 - 2020 AVSP Ltd
9 | * Copyright © 2020 Oliver Hall, Ultamation Ltd
10 | *
11 | * Permission is hereby granted, free of charge, to any person obtaining a copy
12 | * of this software and associated documentation files (the "Software"), to deal
13 | * in the Software without restriction, including without limitation the rights
14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | * copies of the Software, and to permit persons to whom the Software is
16 | * furnished to do so, subject to the following conditions:
17 | *
18 | * The above copyright notice and this permission notice shall be included in
19 | * all copies or substantial portions of the Software.
20 | *
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 | * THE SOFTWARE.
28 | */
29 |
30 | #endregion License
31 |
32 | using System;
33 | using System.IO;
34 | using EnvDTE;
35 | using EnvDTE80;
36 |
37 | namespace VsIdeBuild.VsBuilderLibrary
38 | {
39 | public class VsBuilder
40 | {
41 | ///
42 | /// Build log message we look for to indicate sandbox failure
43 | ///
44 | private const string crestronSandboxFailureMessage = "was not prepared";
45 | private const string crestronPluginStart = "Preparing SIMPL # Project";
46 | private const string crestronPluginSuccess = "Prepared for use on a Crestron control system";
47 |
48 | private object visualStudio;
49 | private DTE dte;
50 | private DTE2 dte2;
51 | private Solution sln;
52 | private VsBuilderOptions options;
53 |
54 | ///
55 | /// After calling Run, Results will contain build counts and fail counts
56 | ///
57 | public VsBuilderResults Results { get; private set; }
58 |
59 | ///
60 | /// Build solution as specified in options
61 | ///
62 | /// Build configuration options
63 | ///
64 | public int Run(VsBuilderOptions options)
65 | {
66 | int returnValue = 0;
67 |
68 | this.options = options;
69 | this.Results = new VsBuilderResults();
70 |
71 | Console.WriteLine("Opening Visual Studio 2008...");
72 | OpenVS();
73 |
74 | dte.SuppressUI = !options.Debug;
75 | dte.UserControl = options.Debug;
76 |
77 | // Resolve the solution absolute filepath
78 | string absSolutionFilePath = ResolveSolutionName(options.Solution);
79 |
80 | if (!File.Exists(absSolutionFilePath))
81 | {
82 | Console.WriteLine("Solution file not found");
83 | return 1;
84 | }
85 |
86 | Console.WriteLine("Opening Solution...");
87 | if (!OpenSolution(absSolutionFilePath))
88 | {
89 | Console.WriteLine("Solution could not be opened");
90 | return 2;
91 | }
92 |
93 | #if DEBUG
94 | Console.WriteLine("Solution.Count = " + sln.Count);
95 |
96 | Console.WriteLine("Projects Names...");
97 | foreach (Project project in dte.Solution.Projects)
98 | {
99 | Console.WriteLine("Project: " + project.Name);
100 | }
101 | #endif
102 |
103 | if (options.ShowProjectContexts)
104 | {
105 | Console.WriteLine("Showing project contexts...");
106 | Console.WriteLine(GetProjectContexts());
107 | }
108 |
109 | if (options.ShowProjectOutputs)
110 | {
111 | Console.WriteLine("Showing project outputs...");
112 | ShowProjectOutputs();
113 | }
114 |
115 | if (options.BuildAll)
116 | {
117 | BuildAll();
118 | }
119 | else
120 | {
121 | if (options.BuildSolutionConfiguration != null)
122 | {
123 | if (options.BuildProject != null)
124 | {
125 | string projUniqueName = GetProjectUniqueName(options.BuildProject);
126 |
127 | if (string.IsNullOrEmpty(projUniqueName))
128 | {
129 | Console.WriteLine("ERROR: The specified project was not found in the solution.");
130 | returnValue = 1;
131 | }
132 | else
133 | BuildProject(options.BuildSolutionConfiguration, projUniqueName);
134 | }
135 | else
136 | {
137 | BuildSolutionConfiguration(options.BuildSolutionConfiguration);
138 | }
139 | }
140 | else
141 | {
142 | Console.WriteLine("ERROR: neither BuildAll or BuildSolutionConfiguration was specified");
143 | returnValue = 1;
144 | }
145 | }
146 |
147 | if (options.ShowBuild)
148 | {
149 | string buildOutput = GetOutputWindowText("Build");
150 |
151 | if (!string.IsNullOrEmpty(buildOutput))
152 | {
153 | Console.WriteLine("Build Output:");
154 |
155 | string[] buildLines = buildOutput.Split('\n');
156 |
157 | foreach (string line in buildLines)
158 | {
159 | Console.WriteLine(line);
160 | }
161 | }
162 | else
163 | {
164 | Console.WriteLine("Build Output: None");
165 | }
166 | }
167 |
168 | Console.WriteLine("Closing Solution...");
169 | CloseSolution();
170 |
171 | Console.WriteLine("Closing Visual Studio...");
172 | CloseVS();
173 |
174 | return returnValue;
175 | }
176 |
177 | private void PostBuildChecks()
178 | {
179 | if (sln.SolutionBuild.LastBuildInfo != 0)
180 | {
181 | Console.WriteLine("ERROR: some projects failed to build!");
182 | Results.Failed = true;
183 | return;
184 | }
185 |
186 | // Crestron SDK does not report sandbox failure as a failed build, because it is in a post-build step, so detect it separately
187 | string buildOutput = GetOutputWindowText("Build");
188 |
189 | if (buildOutput != null)
190 | {
191 | if (buildOutput.IndexOf(crestronSandboxFailureMessage) != -1)
192 | {
193 | Console.WriteLine("ERROR: Crestron sandbox failures in build!");
194 | Results.Failed = true;
195 | }
196 | else if (options.Crestron && (buildOutput.IndexOf(crestronPluginStart) == -1))
197 | {
198 | Console.WriteLine("ERROR: Crestron plugin did not run!");
199 | Results.Failed = true;
200 | }
201 | else if (options.Crestron && (buildOutput.IndexOf(crestronPluginSuccess) == -1))
202 | {
203 | Console.WriteLine("ERROR: Crestron plugin build failed!");
204 | Results.Failed = true;
205 | }
206 | }
207 | else
208 | {
209 | if (options.Crestron)
210 | {
211 | Console.WriteLine("ERROR: Crestron plugin output not found!");
212 | Results.Failed = true;
213 | }
214 | }
215 | }
216 |
217 | private void BuildSolutionConfiguration(EnvDTE80.SolutionConfiguration2 solutionConfiguration2)
218 | {
219 | Console.WriteLine("Activating solution configuration '" + solutionConfiguration2.Name + "' platform '" + solutionConfiguration2.PlatformName + "'");
220 | solutionConfiguration2.Activate();
221 |
222 | if (options.Clean)
223 | {
224 | Console.WriteLine("Cleaning solution configuration '" + solutionConfiguration2.Name + "' platform '" + solutionConfiguration2.PlatformName + "'");
225 | sln.SolutionBuild.Clean(true);
226 | System.Threading.Thread.Sleep(1000);
227 | }
228 |
229 | Console.WriteLine("Building " + solutionConfiguration2.Name + ":" + solutionConfiguration2.PlatformName);
230 | sln.SolutionBuild.Build(true);
231 | System.Threading.Thread.Sleep(1000);
232 |
233 | PostBuildChecks();
234 | }
235 |
236 | ///
237 | /// Return the unique name for the given project name
238 | /// This is required for single project builds
239 | ///
240 | /// The common project name
241 | /// The corresponding unique project name, or the empty string if not found.
242 | private string GetProjectUniqueName(string projectName)
243 | {
244 | #if DEBUG
245 | Console.WriteLine("Looking for project: {0}", projectName);
246 | #endif
247 | foreach (Project project in dte.Solution.Projects)
248 | {
249 | string uniqueName = GetProjectUniqueName(projectName, project);
250 | if (!string.IsNullOrEmpty(uniqueName))
251 | return uniqueName;
252 | }
253 | return string.Empty;
254 | }
255 |
256 | ///
257 | /// This is a recursive form of GetProjectUniqueName which checks for sub projects - which is encountered when projects are organised into folders!
258 | ///
259 | /// The project name to look for
260 | /// The project collection to search, recursively
261 | /// A project unique name or the empty string
262 | private string GetProjectUniqueName(string projectName, Project project)
263 | {
264 | #if DEBUG
265 | Console.WriteLine("Checking project: {0} => {1}", project.Name, project.UniqueName);
266 | #endif
267 | if (project.Name.ToLower() == projectName.ToLower())
268 | return project.UniqueName;
269 | else
270 | {
271 | if ((project.ProjectItems != null) && (project.ProjectItems.Count > 0))
272 | {
273 | foreach (ProjectItem projItem in project.ProjectItems)
274 | {
275 | if (projItem.SubProject != null)
276 | {
277 | string uniqueName = GetProjectUniqueName(projectName, projItem.SubProject);
278 | if (!string.IsNullOrEmpty(uniqueName))
279 | return uniqueName;
280 | #if DEBUG
281 | else
282 | {
283 | Console.WriteLine("Skipping item...");
284 | }
285 | #endif
286 | }
287 | }
288 | }
289 | }
290 | return string.Empty;
291 | }
292 |
293 | ///
294 | /// Refactored solution matching
295 | ///
296 | /// The solution config passed as an option
297 | /// A matching solution config, or null if no matches
298 | private EnvDTE80.SolutionConfiguration2 IdentifyMatchingSolution(string solutionConfigurationName)
299 | {
300 | EnvDTE.SolutionConfigurations solutionConfigurations;
301 |
302 | solutionConfigurations = sln.SolutionBuild.SolutionConfigurations;
303 |
304 | foreach (EnvDTE80.SolutionConfiguration2 solutionConfiguration2 in solutionConfigurations)
305 | {
306 | Console.WriteLine("BuildSolutionConfiguration considering solution configuration '" + solutionConfiguration2.Name + "' platform '" + solutionConfiguration2.PlatformName + "'");
307 |
308 | if (solutionConfiguration2.Name == solutionConfigurationName)
309 | {
310 | Console.WriteLine("Matches, building...");
311 | return solutionConfiguration2;
312 | }
313 | else
314 | {
315 | Console.WriteLine("Does not match, skipping");
316 | }
317 | }
318 | return null;
319 | }
320 |
321 | private void BuildProject(string solutionConfigurationName, string projectUniqueName)
322 | {
323 | SolutionConfiguration2 slnCfg = IdentifyMatchingSolution(solutionConfigurationName);
324 | if (slnCfg == null)
325 | {
326 | Console.WriteLine("No configurations matching " + solutionConfigurationName + " found.");
327 | return;
328 | }
329 |
330 | string buildConfig = slnCfg.Name + "|" + slnCfg.PlatformName;
331 | Console.WriteLine("Activating solution configuration '" + buildConfig + "'");
332 | slnCfg.Activate();
333 |
334 | if (options.Clean)
335 | {
336 | Console.WriteLine("Cleaning solution configuration '" + buildConfig + "'");
337 | sln.SolutionBuild.Clean(true);
338 | System.Threading.Thread.Sleep(1000);
339 | }
340 |
341 | Console.WriteLine("Building " + buildConfig + ":" + projectUniqueName);
342 | sln.SolutionBuild.BuildProject(buildConfig, projectUniqueName, true);
343 | System.Threading.Thread.Sleep(1000);
344 |
345 | PostBuildChecks();
346 | }
347 |
348 | private void BuildSolutionConfiguration(string solutionConfigurationName)
349 | {
350 | SolutionConfiguration2 slnCfg = IdentifyMatchingSolution(solutionConfigurationName);
351 | if (slnCfg == null)
352 | {
353 | Console.WriteLine("No configurations matching " + solutionConfigurationName + " found.");
354 | return;
355 | }
356 |
357 | BuildSolutionConfiguration(slnCfg);
358 | }
359 |
360 | private void BuildAll()
361 | {
362 | EnvDTE.SolutionConfigurations solutionConfigurations;
363 |
364 | solutionConfigurations = sln.SolutionBuild.SolutionConfigurations;
365 |
366 | foreach (EnvDTE80.SolutionConfiguration2 solutionConfiguration2 in solutionConfigurations)
367 | {
368 | Console.WriteLine("BuildAll starting solution configuration '" + solutionConfiguration2.Name + "' platform '" + solutionConfiguration2.PlatformName + "'");
369 | BuildSolutionConfiguration(solutionConfiguration2);
370 | }
371 | }
372 |
373 | private void SaveAllOutputWindowPanes(string basePath, string projectName)
374 | {
375 | OutputWindow outputWindow = dte2.ToolWindows.OutputWindow;
376 | OutputWindowPanes panes = outputWindow.OutputWindowPanes;
377 |
378 | foreach (OutputWindowPane pane in panes)
379 | {
380 | string filename = Path.Combine(basePath, "build." + projectName + "-" + pane.Name + ".log");
381 |
382 | string text = GetOutputWindowPaneText(pane);
383 | File.WriteAllText(filename, text);
384 | }
385 | }
386 |
387 | private string GetOutputWindowPaneText(OutputWindowPane outputWindowPane)
388 | {
389 | TextDocument doc = outputWindowPane.TextDocument;
390 | TextSelection sel = doc.Selection;
391 |
392 | sel.SelectAll();
393 | string txt = sel.Text;
394 |
395 | return txt;
396 | }
397 |
398 | ///
399 | /// Get the full text from an output pane
400 | ///
401 | ///
402 | /// text from chosen output pane or null if pane does not exist or an error occurs
403 | private string GetOutputWindowText(string fromPane)
404 | {
405 | try
406 | {
407 | OutputWindow outputWindow = dte2.ToolWindows.OutputWindow;
408 | OutputWindowPane outputWindowPane = outputWindow.OutputWindowPanes.Item(fromPane);
409 |
410 | return GetOutputWindowPaneText(outputWindowPane);
411 | }
412 | catch (Exception)
413 | {
414 | return null;
415 | }
416 | }
417 |
418 | private void ChangeProjectContexts(EnvDTE.Project project, string configurationName)
419 | {
420 | EnvDTE.SolutionConfigurations solutionConfigurations;
421 |
422 | solutionConfigurations = sln.SolutionBuild.SolutionConfigurations;
423 |
424 | foreach (EnvDTE80.SolutionConfiguration2 solutionConfiguration2 in solutionConfigurations)
425 | {
426 | foreach (EnvDTE.SolutionContext solutionContext in solutionConfiguration2.SolutionContexts)
427 | {
428 | if (solutionContext.ProjectName == project.UniqueName)
429 | {
430 | solutionContext.ConfigurationName = configurationName;
431 | }
432 | }
433 | }
434 | }
435 |
436 | private void ShowProjectOutputs()
437 | {
438 | foreach (Project project in dte.Solution.Projects)
439 | {
440 | Console.WriteLine("Project: " + project.Name);
441 |
442 | var dir = System.IO.Path.Combine(
443 | project.FullName,
444 | project.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputPath").Value.ToString());
445 |
446 | foreach (Property prop in project.ConfigurationManager.ActiveConfiguration.Properties)
447 | {
448 | Console.WriteLine(" - " + prop.Name + " = " + prop.Value);
449 | }
450 |
451 | string outputFileName = null;
452 |
453 | try
454 | {
455 | // and combine it with the OutputFilename to get the assembly
456 | // or skip this and grab all files in the output directory
457 | outputFileName = System.IO.Path.Combine(
458 | dir,
459 | project.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputFilename").Value.ToString());
460 | }
461 | catch (ArgumentException)
462 | {
463 | // projects in VS2008 do not seem to define this property, oh well
464 | outputFileName = System.IO.Path.Combine(dir, "???.???");
465 | }
466 |
467 | Console.WriteLine(outputFileName);
468 | }
469 | }
470 |
471 | private string GetProjectContexts()
472 | {
473 | System.Text.StringBuilder sb = new System.Text.StringBuilder();
474 | EnvDTE80.Solution2 solution2;
475 | EnvDTE80.SolutionBuild2 solutionBuild2;
476 | EnvDTE.SolutionContexts solutionContexts;
477 |
478 | solution2 = (EnvDTE80.Solution2)sln;
479 | solutionBuild2 = (EnvDTE80.SolutionBuild2)solution2.SolutionBuild;
480 |
481 | // Solution configurations/platforms
482 | sb.AppendLine();
483 | sb.AppendLine("-----------------------------------------------");
484 | sb.AppendLine("Project contexts for each solution configuration/platform:");
485 |
486 | foreach (SolutionConfiguration2 solutionConfiguration2 in solutionBuild2.SolutionConfigurations)
487 | {
488 | sb.AppendLine();
489 |
490 | sb.AppendLine(" - Solution configuration: " + solutionConfiguration2.Name);
491 | sb.AppendLine(" - Solution platform: " + solutionConfiguration2.PlatformName);
492 |
493 | solutionContexts = solutionConfiguration2.SolutionContexts;
494 |
495 | foreach (EnvDTE.SolutionContext solutionContext in solutionContexts)
496 | {
497 | sb.AppendLine();
498 | sb.AppendLine(" Project unique name: " + solutionContext.ProjectName);
499 | sb.AppendLine(" Project configuration: " + solutionContext.ConfigurationName);
500 | sb.AppendLine(" Project platform: " + solutionContext.PlatformName);
501 | sb.AppendLine();
502 | }
503 | }
504 |
505 | return sb.ToString();
506 | }
507 |
508 | private void ChangeActiveConfigurationAndPlatform(string configurationName, string platformName)
509 | {
510 | EnvDTE80.SolutionConfiguration2 solutionConfiguration2 = null;
511 |
512 | solutionConfiguration2 = (EnvDTE80.SolutionConfiguration2)sln.SolutionBuild.ActiveConfiguration;
513 |
514 | Console.WriteLine("The old configuration was: Configuration Name: " + solutionConfiguration2.Name + ", Platform Name: " + solutionConfiguration2.PlatformName);
515 |
516 | foreach (EnvDTE80.SolutionConfiguration2 solConfiguration2 in sln.SolutionBuild.SolutionConfigurations)
517 | {
518 | if (solConfiguration2.Name == configurationName && solConfiguration2.PlatformName == platformName)
519 | {
520 | solConfiguration2.Activate();
521 | break;
522 | }
523 | }
524 |
525 | solutionConfiguration2 = (EnvDTE80.SolutionConfiguration2)sln.SolutionBuild.ActiveConfiguration;
526 |
527 | Console.WriteLine("The new configuration is: Configuration Name: " + solutionConfiguration2.Name + ", Platform Name: " + solutionConfiguration2.PlatformName);
528 | }
529 |
530 | public void ShowSolutionConfigurations()
531 | {
532 | EnvDTE.SolutionConfigurations solutionConfigurations;
533 |
534 | solutionConfigurations = sln.SolutionBuild.SolutionConfigurations;
535 |
536 | foreach (EnvDTE80.SolutionConfiguration2 solutionConfiguration2 in solutionConfigurations)
537 | {
538 | Console.WriteLine(" SolutionConfigurationName: " + solutionConfiguration2.Name);
539 | foreach (EnvDTE.SolutionContext solutionContext in solutionConfiguration2.SolutionContexts)
540 | {
541 | Console.WriteLine(" SolutionConfigurationContext");
542 | Console.WriteLine(" ProjectName = " + solutionContext.ProjectName); // will match project.UniqueName
543 | Console.WriteLine(" ConfigurationName = " + solutionContext.ConfigurationName); // you can write this too
544 | }
545 | }
546 | }
547 |
548 | ///
549 | /// Convert the given solution name to an absolute path, and add the .sln extension
550 | ///
551 | /// The solution filename from the arguments
552 | /// The absolute path to the full solution
553 | private string ResolveSolutionName(string solutionFile)
554 | {
555 | string absPath = Path.GetDirectoryName(Path.GetFullPath(solutionFile));
556 | string slnFileName = Path.GetFileNameWithoutExtension(solutionFile);
557 | return Path.Combine(absPath, slnFileName + ".sln");
558 | }
559 |
560 | public bool OpenSolution(string solutionFile)
561 | {
562 | sln = dte.Solution;
563 | sln.Open(solutionFile);
564 | #if DEBUG
565 | Console.WriteLine("sln.IsOpen = " + sln.IsOpen);
566 | #endif
567 | return sln.IsOpen;
568 | }
569 |
570 | public void CloseSolution()
571 | {
572 | sln.Close(false);
573 | }
574 |
575 | ///
576 | /// Open Visual Studio 2008
577 | ///
578 | public void OpenVS()
579 | {
580 | #if DEBUG
581 | Console.WriteLine("Getting Type of Visual Studio...");
582 | #endif
583 | Type type = Type.GetTypeFromProgID("VisualStudio.DTE.9.0");
584 |
585 | #if DEBUG
586 | Console.WriteLine("Opening Visual Studio...");
587 | #endif
588 | visualStudio = Activator.CreateInstance(type, true);
589 |
590 | // See http://msdn.microsoft.com/en-us/library/ms228772.aspx
591 | MessageFilter.Register();
592 |
593 | #if DEBUG
594 | Console.WriteLine("Casting to DTE...");
595 | #endif
596 | dte = (DTE)visualStudio;
597 |
598 | #if DEBUG
599 | Console.WriteLine("Casting to DTE2...");
600 | #endif
601 | dte2 = (DTE2)visualStudio;
602 | }
603 |
604 | ///
605 | /// Close Visual Studio 2008
606 | ///
607 | public void CloseVS()
608 | {
609 | dte.Quit();
610 |
611 | MessageFilter.Revoke();
612 | }
613 | }
614 | }
--------------------------------------------------------------------------------