├── .nuget
├── NuGet.exe
├── NuGet.Config
└── NuGet.targets
├── GruntLauncher
├── Key.snk
├── Resources
│ ├── icon.png
│ ├── Images.png
│ ├── Package.ico
│ ├── preview.png
│ ├── gulpInit.txt
│ └── Init.txt
├── packages.config
├── Properties
│ ├── Settings.settings
│ ├── Settings.Designer.cs
│ └── AssemblyInfo.cs
├── PkgCmdID.cs
├── GlobalSuppressions.cs
├── OptionPage.cs
├── Guids.cs
├── Helpers
│ ├── ProcessHelpers.cs
│ ├── OutputHelpers.cs
│ └── SolutionHelpers.cs
├── source.extension.vsixmanifest
├── GulpParser.cs
├── Resources.Designer.cs
├── GruntParser.cs
├── Resources.resx
├── VSPackage.resx
├── GruntLauncher.vsct
├── GruntLauncher.csproj
└── GruntLauncherPackage.cs
├── appveyor.yml
├── .gitattributes
├── README.md
├── LICENSE.txt
├── GruntLauncher.sln
├── Settings.StyleCop
└── .gitignore
/.nuget/NuGet.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/madskristensen/GruntLauncher/master/.nuget/NuGet.exe
--------------------------------------------------------------------------------
/GruntLauncher/Key.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/madskristensen/GruntLauncher/master/GruntLauncher/Key.snk
--------------------------------------------------------------------------------
/GruntLauncher/Resources/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/madskristensen/GruntLauncher/master/GruntLauncher/Resources/icon.png
--------------------------------------------------------------------------------
/GruntLauncher/Resources/Images.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/madskristensen/GruntLauncher/master/GruntLauncher/Resources/Images.png
--------------------------------------------------------------------------------
/GruntLauncher/Resources/Package.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/madskristensen/GruntLauncher/master/GruntLauncher/Resources/Package.ico
--------------------------------------------------------------------------------
/GruntLauncher/Resources/preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/madskristensen/GruntLauncher/master/GruntLauncher/Resources/preview.png
--------------------------------------------------------------------------------
/.nuget/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/GruntLauncher/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/GruntLauncher/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | version: 1.0.{build}
2 |
3 | install:
4 | - ps: (new-object Net.WebClient).DownloadString("https://raw.github.com/madskristensen/ExtensionScripts/master/AppVeyor/vsix.ps1") | iex
5 |
6 | before_build:
7 | - ps: Vsix-IncrementVsixVersion | Vsix-UpdateBuildVersion
8 |
9 | build_script:
10 | - msbuild /p:configuration=Release /p:DeployExtension=false /p:ZipPackageCompressionLevel=normal /v:m
11 |
12 | after_test:
13 | - ps: Vsix-PushArtifacts | Vsix-PublishToGallery
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
8 | *.vbproj merge=union
9 | *.fsproj merge=union
10 | *.dbproj merge=union
11 |
12 | # Standard to msysgit
13 | *.doc diff=astextplain
14 | *.DOC diff=astextplain
15 | *.docx diff=astextplain
16 | *.DOCX diff=astextplain
17 | *.dot diff=astextplain
18 | *.DOT diff=astextplain
19 | *.pdf diff=astextplain
20 | *.PDF diff=astextplain
21 | *.rtf diff=astextplain
22 | *.RTF diff=astextplain
23 |
--------------------------------------------------------------------------------
/GruntLauncher/Resources/gulpInit.txt:
--------------------------------------------------------------------------------
1 | var tasks = [];
2 |
3 | var gulpFN = {};
4 |
5 | gulpFN.task = function(task, func){
6 | tasks.push(task);
7 | }
8 |
9 | gulpFN.src = function(){
10 | return gulpFN;
11 | }
12 |
13 | gulpFN.dest = function(){
14 | return gulpFN;
15 | }
16 |
17 | gulpFN.pipe = function(){
18 | return gulpFN;
19 | }
20 |
21 | gulpFN.watch= function(){
22 |
23 | }
24 |
25 |
26 | var require = function(param){
27 | if(param==="gulp"){
28 | return gulpFN;
29 | }else{
30 | var f = function(){};
31 | f.task= function(){};
32 |
33 | return f;
34 | }
35 | };
36 |
37 |
38 |
39 | var __dirname="";
--------------------------------------------------------------------------------
/GruntLauncher/PkgCmdID.cs:
--------------------------------------------------------------------------------
1 | namespace Bjornej.GruntLauncher
2 | {
3 | using System;
4 |
5 | ///
6 | /// List of Command IDs
7 | ///
8 | public static class PkgCmdIDList
9 | {
10 | #region Visual Studio generated code
11 |
12 | ///
13 | /// Command id
14 | ///
15 | public const uint cmdidGruntLauncher = 0x100;
16 | public const uint cmdidGulpLauncher = 0x200;
17 | public const uint cmdidBowerUpdater = 0x1050;
18 | public const uint cmdidBowerInstaller = 0x1150;
19 | public const uint cmdidNpmUpdater = 0x1090;
20 |
21 | #endregion
22 | }
23 | }
--------------------------------------------------------------------------------
/GruntLauncher/GlobalSuppressions.cs:
--------------------------------------------------------------------------------
1 | // This file is used by Code Analysis to maintain SuppressMessage
2 | // attributes that are applied to this project. Project-level
3 | // suppressions either have no target or are given a specific target
4 | // and scoped to a namespace, type, member, etc.
5 | //
6 | // To add a suppression to this file, right-click the message in the
7 | // Error List, point to "Suppress Message(s)", and click "In Project
8 | // Suppression File". You do not need to add suppressions to this
9 | // file manually.
10 |
11 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1017:MarkAssembliesWithComVisible", Justification = "Default suppression inserted by visual studio")]
12 |
--------------------------------------------------------------------------------
/GruntLauncher/OptionPage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using System.Runtime.InteropServices;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using Microsoft.VisualStudio.Shell;
9 |
10 | namespace Bjornej.GruntLauncher
11 | {
12 | [ClassInterface(ClassInterfaceType.AutoDual)]
13 | [CLSCompliant(false), ComVisible(true)]
14 | public class OptionPage : DialogPage
15 | {
16 |
17 | [Category("Tasks Parser")]
18 | [DisplayName("Exclusion")]
19 | [Description("Specify a Regex pattern to exclude some unwanted tasks from list.")]
20 | public string TaskRegex
21 | {
22 | get; set;
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/GruntLauncher/Guids.cs:
--------------------------------------------------------------------------------
1 | namespace Bjornej.GruntLauncher
2 | {
3 | using System;
4 |
5 | ///
6 | /// List of giud used by the plugind
7 | ///
8 | public static class GuidList
9 | {
10 | #region Visual Studio generated code
11 |
12 | ///
13 | /// Package Guid
14 | ///
15 | public const string guidGruntLauncherPkgString = "cced4e72-2f8c-4458-b8df-4934677e4bf3";
16 |
17 | ///
18 | /// Command Guid as string
19 | ///
20 | public const string guidGruntLauncherCmdSetString = "59ce41a7-3da6-41c2-bf26-48dac265cbae";
21 |
22 | ///
23 | /// Command Guid
24 | ///
25 | public static readonly Guid guidGruntLauncherCmdSet = new Guid(guidGruntLauncherCmdSetString);
26 |
27 | #endregion
28 | }
29 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### GruntLauncher ###
2 |
3 | Originally a plugin made to launch grunt taasks from inside Visual studio by right-clicking your gruntfile in the solution explorer it has now been extended with new functionality:
4 |
5 | - Launch grunt tasks from the solution solution explorer. When right clicking on a gruntfile you will see a new submenu listing all your options
6 |
7 | 
8 |
9 | - Execute bower updates when right clicking on the bower folder or on a plugin folder (thanks to Mads Kristensen for this feature)
10 |
11 | 
12 | 
13 |
14 | - Launch gulp tasks by right clicking on your gulpfile
15 |
16 | 
17 |
18 | #### Attention
19 |
20 | To work well this plugin needs a recent version of node.js installed on yout system due to a bug where output is not correclty redirected. If you don't see any output try to update node.js.
21 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013 "Bjornej" Paolo Nicodemo
2 |
3 | Permission is hereby granted, free of charge, to any person
4 | obtaining a copy of this software and associated documentation
5 | files (the "Software"), to deal in the Software without
6 | restriction, including without limitation the rights to use,
7 | copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the
9 | Software is furnished to do so, subject to the following
10 | conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/GruntLauncher/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // Il codice è stato generato da uno strumento.
4 | // Versione runtime:4.0.30319.34003
5 | //
6 | // Le modifiche apportate a questo file possono provocare un comportamento non corretto e andranno perse se
7 | // il codice viene rigenerato.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Bjornej.GruntLauncher.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/GruntLauncher/Helpers/ProcessHelpers.cs:
--------------------------------------------------------------------------------
1 | namespace Bjornej.GruntLauncher
2 | {
3 | using System;
4 | using System.Diagnostics;
5 | using System.Management;
6 |
7 | ///
8 | /// Utility methods to manage the running processes
9 | ///
10 | public static class ProcessHelpers
11 | {
12 | ///
13 | /// Kill a process, and all of its children.
14 | ///
15 | /// Process ID
16 | public static void KillProcessAndChildren(int pid)
17 | {
18 | ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + pid);
19 | ManagementObjectCollection moc = searcher.Get();
20 | foreach (ManagementObject mo in moc)
21 | {
22 | KillProcessAndChildren(Convert.ToInt32(mo["ProcessID"]));
23 | }
24 |
25 | try
26 | {
27 | Process proc = Process.GetProcessById(pid);
28 | proc.Kill();
29 | }
30 | catch (ArgumentException)
31 | {
32 | // Process already exited.
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/GruntLauncher/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Reflection;
3 | using System.Resources;
4 | using System.Runtime.CompilerServices;
5 | using System.Runtime.InteropServices;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 | [assembly: AssemblyTitle("GruntLauncher")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("Bjornej")]
14 | [assembly: AssemblyProduct("GruntLauncher")]
15 | [assembly: AssemblyCopyright("")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 | [assembly: ComVisible(false)]
19 | [assembly: CLSCompliant(false)]
20 | [assembly: NeutralResourcesLanguage("en-US")]
21 |
22 | // Version information for an assembly consists of the following four values:
23 | //
24 | // Major Version
25 | // Minor Version
26 | // Build Number
27 | // Revision
28 | //
29 | // You can specify all the values or you can default the Revision and Build Numbers
30 | // by using the '*' as shown below:
31 | [assembly: AssemblyVersion("1.1.0")]
32 | [assembly: AssemblyFileVersion("1.1.0")]
33 |
--------------------------------------------------------------------------------
/GruntLauncher/source.extension.vsixmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Grunt Launcher
6 | Right click extension to launch Grunt, Gulp and Bower commands in Visual Studio.
7 | https://github.com/Bjornej/GruntLauncher
8 | Resources\LICENSE.txt
9 | https://github.com/Bjornej/GruntLauncher/releases
10 | Resources\icon.png
11 | Resources\preview.png
12 | grunt, gulp, bower, npm
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/GruntLauncher/GulpParser.cs:
--------------------------------------------------------------------------------
1 | namespace Bjornej.GruntLauncher
2 | {
3 | using Jurassic;
4 | using Jurassic.Library;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.IO;
9 |
10 | public static class GulpParser
11 | {
12 | public static ICollection ReadAllTasks(string path)
13 | {
14 | var list = new List();
15 |
16 | if (path.EndsWith(".ts"))
17 | {
18 | path = path.Replace(".ts", ".js").Replace(".coffee",".js");
19 | }
20 |
21 | if (!File.Exists(path))
22 | {
23 | return list;
24 | }
25 |
26 | // executes the gulpfile with some little additions :)
27 | try
28 | {
29 | var engine = new ScriptEngine();
30 | engine.Execute(Resources.gulpInit);
31 | engine.ExecuteFile(path);
32 |
33 | // reads the evaluated tasks
34 | ArrayInstance names = (ArrayInstance)engine.Evaluate("tasks");
35 | foreach (var elem in names.ElementValues)
36 | {
37 | list.Add((string)elem);
38 | }
39 | }
40 | catch (Exception)
41 | {
42 | list.Add("Cannot parse gulpfile");
43 | }
44 |
45 | return list.Distinct().ToList();
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/GruntLauncher.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.21005.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{43F51224-07C7-48E2-943E-59539AD01D6A}"
7 | ProjectSection(SolutionItems) = preProject
8 | .nuget\NuGet.Config = .nuget\NuGet.Config
9 | .nuget\NuGet.exe = .nuget\NuGet.exe
10 | .nuget\NuGet.targets = .nuget\NuGet.targets
11 | EndProjectSection
12 | EndProject
13 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9A01155A-417E-4624-B9B9-E44E9C47745B}"
14 | ProjectSection(SolutionItems) = preProject
15 | Settings.StyleCop = Settings.StyleCop
16 | EndProjectSection
17 | EndProject
18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GruntLauncher", "GruntLauncher\GruntLauncher.csproj", "{431382D5-7949-4C6E-9211-79D48E38AA5E}"
19 | EndProject
20 | Global
21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
22 | Debug|Any CPU = Debug|Any CPU
23 | Release|Any CPU = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
26 | {431382D5-7949-4C6E-9211-79D48E38AA5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {431382D5-7949-4C6E-9211-79D48E38AA5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {431382D5-7949-4C6E-9211-79D48E38AA5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {431382D5-7949-4C6E-9211-79D48E38AA5E}.Release|Any CPU.Build.0 = Release|Any CPU
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | EndGlobal
35 |
--------------------------------------------------------------------------------
/GruntLauncher/Resources/Init.txt:
--------------------------------------------------------------------------------
1 | var names = [];
2 | var module = {};
3 | var grunt = {};
4 |
5 | var require = function(){
6 | var a = function(){};
7 | a.filterDev = function(){
8 | return {
9 | forEach: function(){}
10 | };
11 | };
12 |
13 | a.resolve = function(){
14 | return "";
15 | };
16 |
17 | return a;
18 | };
19 |
20 | grunt.initConfig=function(param){
21 | for(var prop in param){
22 | if(param.hasOwnProperty(prop)){
23 | names.push(prop);
24 | if(param[prop] === Object(param[prop])){
25 | var arr=[];
26 | for(var innerProp in param[prop]){
27 | if(param[prop].hasOwnProperty(innerProp)){
28 | if(innerProp!=='options'){
29 | arr.push(prop+":"+innerProp);
30 | }
31 | }
32 | }
33 | if(arr.length > 1){
34 | for (var i=0;i< arr.length;i++){
35 | names.push(arr[i]);
36 | }
37 | }
38 | }
39 | }
40 | }
41 | };
42 | grunt.file = {
43 | match: function(){return {};},
44 | isMatch: function(){return {};},
45 | expand: function(){return {};},
46 | expandMapping: function(){return {};},
47 | mkdir: function(){return {};},
48 | recurse: function(){return {};},
49 | readYAML: function(){return {};},
50 | write: function(){return {};},
51 | copy: function(){return {};},
52 | exists: function(){return {};},
53 | isFile: function(){return {};},
54 | isPathAbsolute: function(){return {};},
55 | arePathsEquivalent: function(){return {};},
56 | doesPathContain: function(){return {};},
57 | isPathCwd: function(){return {};},
58 | isPathInCwd: function(){return {};},
59 | read: function(){return {};},
60 | readJSON: function(){return {};}
61 | }
62 | grunt.registerTask= function(name){names.push(name);};
63 | grunt.registerMultiTask= function(name){names.push(name);};
64 | grunt.loadNpmTasks = function(){};
65 | grunt.template = {
66 | today:function(){},
67 | addDelimiters:function(){},
68 | setDelimiters:function(){},
69 | process:function(){}
70 | };
71 | grunt.renameTask = function(a,b){ names.push(b);}
72 | grunt.option = function(){};
73 |
74 | var __dirname = "";
--------------------------------------------------------------------------------
/Settings.StyleCop:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | False
8 |
9 |
10 |
11 |
12 | False
13 |
14 |
15 |
16 |
17 | False
18 |
19 |
20 |
21 |
22 | False
23 |
24 |
25 |
26 |
27 | False
28 |
29 |
30 |
31 |
32 | False
33 |
34 |
35 |
36 |
37 | False
38 |
39 |
40 |
41 |
42 | False
43 |
44 |
45 |
46 |
47 | False
48 |
49 |
50 |
51 |
52 | False
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/GruntLauncher/Helpers/OutputHelpers.cs:
--------------------------------------------------------------------------------
1 | namespace Bjornej.GruntLauncher.Helpers
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using EnvDTE;
9 | using Microsoft.VisualStudio.Shell;
10 | using Microsoft.VisualStudio.Shell.Interop;
11 |
12 | ///
13 | /// Helper methods to write to the VS output window
14 | ///
15 | public static class OutputHelpers
16 | {
17 | ///
18 | /// Window pane used to show grunt output
19 | ///
20 | private static IVsOutputWindowPane outputWindowPane;
21 |
22 | ///
23 | /// Prints a string to the Output window in a custom pane
24 | ///
25 | /// The string to print
26 | /// Decides if the output pane should be focused
27 | public static void Output(string msg, bool focus = false)
28 | {
29 | if (outputWindowPane == null)
30 | {
31 | Init();
32 | }
33 |
34 | if (focus)
35 | {
36 | var outputWindow = Package.GetGlobalService(typeof(SVsOutputWindow)) as IVsOutputWindow;
37 | var dte = (DTE)Package.GetGlobalService(typeof(DTE));
38 | Window window = (Window)dte.Windows.Item(EnvDTE.Constants.vsWindowKindOutput);
39 | window.Visible = true;
40 | window.Activate();
41 | outputWindowPane.Activate();
42 | }
43 |
44 | // Output the message
45 | outputWindowPane.OutputString(msg);
46 | }
47 |
48 | ///
49 | /// Initializes the output window
50 | ///
51 | private static void Init()
52 | {
53 | var outputWindow = Package.GetGlobalService(typeof(SVsOutputWindow)) as IVsOutputWindow;
54 | var dte = (DTE)Package.GetGlobalService(typeof(DTE));
55 | Window window = (Window)dte.Windows.Item(EnvDTE.Constants.vsWindowKindOutput);
56 | window.Visible = true;
57 |
58 | // Ensure that the desired pane is visible
59 | var paneGuid = Microsoft.VisualStudio.VSConstants.OutputWindowPaneGuid.GeneralPane_guid;
60 |
61 | outputWindow.CreatePane(paneGuid, "Grunt execution", 1, 0);
62 | outputWindow.GetPane(paneGuid, out outputWindowPane);
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/GruntLauncher/Helpers/SolutionHelpers.cs:
--------------------------------------------------------------------------------
1 | namespace Bjornej.GruntLauncher.Helpers
2 | {
3 | using System;
4 | using EnvDTE;
5 | using Microsoft.VisualStudio.Shell;
6 | using EnvDTE80;
7 | using System.IO;
8 |
9 | ///
10 | /// Static helper methods to interact with the visual studio open solution
11 | ///
12 | public static class SolutionHelpers
13 | {
14 | ///
15 | /// Gets the extensibility object
16 | ///
17 | /// The estenzibility object
18 | public static EnvDTE80.DTE2 GetDTE2()
19 | {
20 | return Package.GetGlobalService(typeof(DTE)) as EnvDTE80.DTE2;
21 | }
22 |
23 | ///
24 | /// Get the full path of the file clicked upon when opening the contextual menu
25 | ///
26 | /// The full path of the current file
27 | public static string GetSourceFilePath()
28 | {
29 | EnvDTE80.DTE2 applicationObject = GetDTE2();
30 | UIHierarchy uih = applicationObject.ToolWindows.SolutionExplorer;
31 | Array selectedItems = (Array)uih.SelectedItems;
32 |
33 | if (null != selectedItems)
34 | {
35 | foreach (UIHierarchyItem selItem in selectedItems)
36 | {
37 | ProjectItem prjItem = selItem.Object as ProjectItem;
38 | string filePath;
39 | if (prjItem.Properties != null)
40 | {
41 | filePath = prjItem.Properties.Item("FullPath").Value.ToString();
42 | }
43 | else
44 | {
45 | filePath = prjItem.FileNames[1];
46 | }
47 |
48 | return filePath;
49 | }
50 | }
51 |
52 | return string.Empty;
53 | }
54 |
55 | public static string GetRootFolder(DTE2 dte)
56 | {
57 | Project project = GetActiveProject(dte);
58 |
59 | if (project == null)
60 | return null;
61 |
62 | string path = project.Properties.Item("FullPath").Value.ToString();
63 |
64 | if (Directory.Exists(path))
65 | return path;
66 |
67 | return Path.GetDirectoryName(path);
68 | }
69 |
70 | private static Project GetActiveProject(DTE2 dte)
71 | {
72 | try
73 | {
74 | Array activeSolutionProjects = dte.ActiveSolutionProjects as Array;
75 |
76 | if (activeSolutionProjects != null && activeSolutionProjects.Length > 0)
77 | return activeSolutionProjects.GetValue(0) as Project;
78 | }
79 | catch (Exception)
80 | {
81 | }
82 |
83 | return null;
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 |
5 | *.pydevproject
6 | .project
7 | .metadata
8 | bin/
9 | tmp/
10 | *.tmp
11 | *.bak
12 | *.swp
13 | *~.nib
14 | local.properties
15 | .classpath
16 | .settings/
17 | .loadpath
18 |
19 | # External tool builders
20 | .externalToolBuilders/
21 |
22 | # Locally stored "Eclipse launch configurations"
23 | *.launch
24 |
25 | # CDT-specific
26 | .cproject
27 |
28 | # PDT-specific
29 | .buildpath
30 |
31 |
32 | #################
33 | ## Visual Studio
34 | #################
35 |
36 | ## Ignore Visual Studio temporary files, build results, and
37 | ## files generated by popular Visual Studio add-ons.
38 |
39 | # User-specific files
40 | *.suo
41 | *.user
42 | *.sln.docstates
43 | *.sln.ide
44 |
45 | # Build results
46 |
47 | [Dd]ebug/
48 | [Rr]elease/
49 | x64/
50 | build/
51 | [Bb]in/
52 | [Oo]bj/
53 |
54 | # MSTest test Results
55 | [Tt]est[Rr]esult*/
56 | [Bb]uild[Ll]og.*
57 |
58 | *_i.c
59 | *_p.c
60 | *.ilk
61 | *.meta
62 | *.obj
63 | *.pch
64 | *.pdb
65 | *.pgc
66 | *.pgd
67 | *.rsp
68 | *.sbr
69 | *.tlb
70 | *.tli
71 | *.tlh
72 | *.tmp
73 | *.tmp_proj
74 | *.log
75 | *.vspscc
76 | *.vssscc
77 | .builds
78 | *.pidb
79 | *.log
80 | *.scc
81 |
82 | # Visual C++ cache files
83 | ipch/
84 | *.aps
85 | *.ncb
86 | *.opensdf
87 | *.sdf
88 | *.cachefile
89 |
90 | # Visual Studio profiler
91 | *.psess
92 | *.vsp
93 | *.vspx
94 |
95 | # Guidance Automation Toolkit
96 | *.gpState
97 |
98 | # ReSharper is a .NET coding add-in
99 | _ReSharper*/
100 | *.[Rr]e[Ss]harper
101 |
102 | # TeamCity is a build add-in
103 | _TeamCity*
104 |
105 | # DotCover is a Code Coverage Tool
106 | *.dotCover
107 |
108 | # NCrunch
109 | *.ncrunch*
110 | .*crunch*.local.xml
111 |
112 | # Installshield output folder
113 | [Ee]xpress/
114 |
115 | # DocProject is a documentation generator add-in
116 | DocProject/buildhelp/
117 | DocProject/Help/*.HxT
118 | DocProject/Help/*.HxC
119 | DocProject/Help/*.hhc
120 | DocProject/Help/*.hhk
121 | DocProject/Help/*.hhp
122 | DocProject/Help/Html2
123 | DocProject/Help/html
124 |
125 | # Click-Once directory
126 | publish/
127 |
128 | # Publish Web Output
129 | *.Publish.xml
130 | *.pubxml
131 |
132 | # NuGet Packages Directory
133 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
134 | packages/
135 |
136 | # Windows Azure Build Output
137 | csx
138 | *.build.csdef
139 |
140 | # Windows Store app package directory
141 | AppPackages/
142 |
143 | # Others
144 | sql/
145 | *.Cache
146 | ClientBin/
147 | [Ss]tyle[Cc]op.*
148 | ~$*
149 | *~
150 | *.dbmdl
151 | *.[Pp]ublish.xml
152 | *.pfx
153 | *.publishsettings
154 |
155 | # RIA/Silverlight projects
156 | Generated_Code/
157 |
158 | # Backup & report files from converting an old project file to a newer
159 | # Visual Studio version. Backup files are not needed, because we have git ;-)
160 | _UpgradeReport_Files/
161 | Backup*/
162 | UpgradeLog*.XML
163 | UpgradeLog*.htm
164 |
165 | # SQL Server files
166 | App_Data/*.mdf
167 | App_Data/*.ldf
168 |
169 | #############
170 | ## Windows detritus
171 | #############
172 |
173 | # Windows image file caches
174 | Thumbs.db
175 | ehthumbs.db
176 |
177 | # Folder config file
178 | Desktop.ini
179 |
180 | # Recycle Bin used on file shares
181 | $RECYCLE.BIN/
182 |
183 | # Mac crap
184 | .DS_Store
185 |
186 |
187 | #############
188 | ## Python
189 | #############
190 |
191 | *.py[co]
192 |
193 | # Packages
194 | *.egg
195 | *.egg-info
196 | dist/
197 | build/
198 | eggs/
199 | parts/
200 | var/
201 | sdist/
202 | develop-eggs/
203 | .installed.cfg
204 |
205 | # Installer logs
206 | pip-log.txt
207 |
208 | # Unit test / coverage reports
209 | .coverage
210 | .tox
211 |
212 | #Translations
213 | *.mo
214 |
215 | #Mr Developer
216 | .mr.developer.cfg
217 |
--------------------------------------------------------------------------------
/GruntLauncher/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // Il codice è stato generato da uno strumento.
4 | // Versione runtime:4.0.30319.34011
5 | //
6 | // Le modifiche apportate a questo file possono provocare un comportamento non corretto e andranno perse se
7 | // il codice viene rigenerato.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Bjornej.GruntLauncher {
12 | using System;
13 |
14 |
15 | ///
16 | /// Classe di risorse fortemente tipizzata per la ricerca di stringhe localizzate e così via.
17 | ///
18 | // Questa classe è stata generata automaticamente dalla classe StronglyTypedResourceBuilder.
19 | // tramite uno strumento quale ResGen o Visual Studio.
20 | // Per aggiungere o rimuovere un membro, modificare il file con estensione ResX ed eseguire nuovamente ResGen
21 | // con l'opzione /str oppure ricompilare il progetto VS.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Restituisce l'istanza di ResourceManager nella cache utilizzata da questa classe.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Bjornej.GruntLauncher.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Esegue l'override della proprietà CurrentUICulture del thread corrente per tutte le
51 | /// ricerche di risorse eseguite utilizzando questa classe di risorse fortemente tipizzata.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Cerca una stringa localizzata simile a var tasks = [];
65 | ///
66 | ///var gulp = {};
67 | ///
68 | ///gulp.task = function(task, func){
69 | /// tasks.push(task);
70 | ///}
71 | ///
72 | ///gulp.src = function(){
73 | /// return gulp;
74 | ///}
75 | ///
76 | ///gulp.dest = function(){
77 | /// return gulp;
78 | ///}
79 | ///
80 | ///gulp.pipe = function(){
81 | /// return gulp;
82 | ///}
83 | ///
84 | ///gulp.watch= function(){
85 | ///
86 | ///}
87 | ///
88 | ///var require = function(param){
89 | /// if(param==="gulp"){
90 | /// return gulp;
91 | /// }else{
92 | /// var f = function(){}
93 | /// return f;
94 | /// }
95 | ///};
96 | ///
97 | ///var __dirname="";.
98 | ///
99 | internal static string gulpInit {
100 | get {
101 | return ResourceManager.GetString("gulpInit", resourceCulture);
102 | }
103 | }
104 |
105 | ///
106 | /// Cerca una stringa localizzata simile a var names = [];
107 | ///var module = {};
108 | ///var grunt = {};
109 | ///
110 | ///var require = function(){
111 | /// var a = function(){};
112 | /// a.filterDev = function(){
113 | /// return {
114 | /// forEach: function(){}
115 | /// };
116 | /// }
117 | /// return a;
118 | ///};
119 | ///
120 | ///grunt.initConfig=function(param){
121 | /// for(var prop in param){
122 | /// if(param.hasOwnProperty(prop)){
123 | /// names.push(prop);
124 | /// }
125 | /// }
126 | ///};
127 | ///grunt.file = { readJSON: function(){return {};}}
128 | ///grunt.registerTask= function(name){names.push(name);};
129 | ///grunt.loadNpmTasks = function(){};
130 | ///grunt.template = {today:function(){}}; [stringa troncata]";.
131 | ///
132 | internal static string Init {
133 | get {
134 | return ResourceManager.GetString("Init", resourceCulture);
135 | }
136 | }
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/GruntLauncher/GruntParser.cs:
--------------------------------------------------------------------------------
1 | namespace Bjornej.GruntLauncher
2 | {
3 | using Jurassic;
4 | using Jurassic.Library;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Diagnostics;
8 | using System.IO;
9 | using System.Linq;
10 |
11 | ///
12 | /// Parses a Gruntfile to extract all the contained tasks by executing it and reading them trough a javascript hack.
13 | /// See the Init file in the resources.
14 | ///
15 | public static class GruntParser
16 | {
17 | private static List _list = null;
18 | private static bool _valid = false;
19 |
20 | private static IDictionary>> cache = new Dictionary>>();
21 |
22 | ///
23 | /// Reads all the defined tasks in a Gruntfile whose path is passed as parameter
24 | ///
25 | /// The path of the file to examine
26 | /// A list of tasks
27 | public static ICollection ReadAllTasks(string path)
28 | {
29 | _list = new List();
30 |
31 | if (path.EndsWith(".ts"))
32 | {
33 | path = path.Replace(".ts", ".js").Replace(".coffee", ".js");
34 | }
35 |
36 | if (!File.Exists(path))
37 | {
38 | return _list;
39 | }
40 |
41 | var lastModifiedDate = File.GetLastWriteTime(path);
42 |
43 | if (cache.ContainsKey(path))
44 | {
45 | var data = cache[path];
46 | if (lastModifiedDate == data.Item1) {
47 | return data.Item2;
48 | }
49 | }
50 |
51 | if (!ParseFromScriptEngine(path))
52 | {
53 | ParseFromProcess(path);
54 | }
55 |
56 | if (_list.Count == 0)
57 | {
58 | _list.Add("Cannot parse Gruntfile");
59 | }else
60 | {
61 | cache[path]= new Tuple>(lastModifiedDate, _list.Distinct().ToList());
62 | }
63 |
64 | return _list.Distinct().ToList();
65 | }
66 |
67 | ///
68 | /// Parses task names with help of Jurassic script engine.
69 | ///
70 | private static bool ParseFromScriptEngine(string path)
71 | {
72 | // executes the gruntfile with some little additions :)
73 | try
74 | {
75 | var engine = new ScriptEngine();
76 | engine.Execute(Resources.Init);
77 | engine.ExecuteFile(path);
78 | engine.Execute("module.exports(grunt);");
79 |
80 | // reads the evaluated tasks
81 | ArrayInstance names = (ArrayInstance)engine.Evaluate("names");
82 | foreach (var elem in names.ElementValues)
83 | {
84 | _list.Add(elem.ToString());
85 | }
86 | }
87 | catch (Exception)
88 | {
89 | return false;
90 | }
91 | return true;
92 | }
93 |
94 | ///
95 | /// Parses task names with help of grunt process execution.
96 | ///
97 | private static bool ParseFromProcess(string path)
98 | {
99 | _valid = false;
100 | try
101 | {
102 | System.Diagnostics.ProcessStartInfo procStartInfo = new ProcessStartInfo()
103 | {
104 | RedirectStandardOutput = true,
105 | StandardOutputEncoding = System.Text.Encoding.UTF8,
106 | UseShellExecute = false,
107 | CreateNoWindow = true,
108 | WorkingDirectory = Path.GetDirectoryName(path),
109 | FileName = "cmd",
110 | Arguments = " /c \"grunt --help 2>&1\"",
111 | };
112 |
113 | System.Diagnostics.Process proc = new System.Diagnostics.Process()
114 | {
115 | StartInfo = procStartInfo,
116 | EnableRaisingEvents = true
117 | };
118 |
119 | proc.OutputDataReceived += (object sendingProcess, DataReceivedEventArgs outLine) => GruntParser.OutputHandler(outLine.Data);
120 | proc.Start();
121 | proc.BeginOutputReadLine();
122 | proc.WaitForExit();
123 | proc.Close();
124 | }
125 | catch (Exception)
126 | {
127 | return false;
128 | }
129 | return true;
130 | }
131 |
132 | ///
133 | /// Reads output stream from process execution and builds up task name list.
134 | ///
135 | private static void OutputHandler(string message)
136 | {
137 | if (String.IsNullOrEmpty(message))
138 | {
139 | if (_valid)
140 | {
141 | // Stop to read from now on.
142 | _valid = false;
143 | }
144 | // Skip null strings.
145 | return;
146 | }
147 |
148 | message = message.Trim();
149 | if (message.StartsWith("[4mAvailable tasks[24m"))
150 | {
151 | // Start to read from now on.
152 | _valid = true;
153 | return;
154 | }
155 |
156 | if (!_valid || message.EndsWith("*") || message.StartsWith("\""))
157 | {
158 | // Skip invalid parts and internal tasks of output.
159 | return;
160 | }
161 |
162 | int index = message.IndexOf(' ');
163 | if (index > 0 && index < message.Length)
164 | {
165 | // Cut out the task name.
166 | _list.Add(message.Substring(0, index));
167 | }
168 | }
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/GruntLauncher/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | Resources\gulpInit.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252
123 |
124 |
125 | Resources\Init.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252
126 |
127 |
--------------------------------------------------------------------------------
/.nuget/NuGet.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildProjectDirectory)\..\
5 |
6 |
7 | false
8 |
9 |
10 | false
11 |
12 |
13 | true
14 |
15 |
16 | false
17 |
18 |
19 |
20 |
21 |
22 |
26 |
27 |
28 |
29 |
30 | $([System.IO.Path]::Combine($(SolutionDir), ".nuget"))
31 | $([System.IO.Path]::Combine($(ProjectDir), "packages.config"))
32 |
33 |
34 |
35 |
36 | $(SolutionDir).nuget
37 | packages.config
38 |
39 |
40 |
41 |
42 | $(NuGetToolsPath)\NuGet.exe
43 | @(PackageSource)
44 |
45 | "$(NuGetExePath)"
46 | mono --runtime=v4.0.30319 $(NuGetExePath)
47 |
48 | $(TargetDir.Trim('\\'))
49 |
50 | -RequireConsent
51 | -NonInteractive
52 |
53 |
54 | $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir "$(SolutionDir) "
55 | $(NuGetCommand) pack "$(ProjectPath)" -Properties Configuration=$(Configuration) $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols
56 |
57 |
58 |
59 | RestorePackages;
60 | $(BuildDependsOn);
61 |
62 |
63 |
64 |
65 | $(BuildDependsOn);
66 | BuildPackage;
67 |
68 |
69 |
70 |
71 |
72 |
73 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
88 |
89 |
92 |
93 |
94 |
95 |
97 |
98 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
130 |
131 |
132 |
133 |
--------------------------------------------------------------------------------
/GruntLauncher/VSPackage.resx:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | text/microsoft-resx
120 |
121 |
122 | 2.0
123 |
124 |
125 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
126 |
127 |
128 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
129 |
130 |
131 |
132 | GruntLauncher
133 |
134 |
135 | Right click extension to launch Grunt commands
136 |
137 |
138 | Resources\Package.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
139 |
140 |
--------------------------------------------------------------------------------
/GruntLauncher/GruntLauncher.vsct:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
28 |
29 |
36 |
37 |
38 |
42 |
43 |
44 |
50 |
51 |
57 |
58 |
59 |
60 |
61 |
64 |
65 |
68 |
69 |
73 |
74 |
78 |
79 |
80 |
81 |
82 |
84 |
85 |
92 |
93 |
102 |
103 |
112 |
113 |
124 |
125 |
135 |
136 |
146 |
147 |
148 |
149 |
150 |
151 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
167 |
170 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
--------------------------------------------------------------------------------
/GruntLauncher/GruntLauncher.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(VisualStudioVersion)
5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
6 | ..\
7 | true
8 |
9 |
10 |
11 |
12 | 4.0
13 | Program
14 | $(DevEnvDir)\devenv.exe
15 | /rootsuffix Exp
16 |
17 |
18 |
19 | Debug
20 | AnyCPU
21 | 2.0
22 | {431382D5-7949-4C6E-9211-79D48E38AA5E}
23 | {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
24 | Library
25 | Properties
26 | Bjornej.GruntLauncher
27 | GruntLauncher
28 | false
29 | Key.snk
30 | v4.5
31 |
32 |
33 | true
34 | full
35 | false
36 | bin\Debug\
37 | DEBUG;TRACE
38 | prompt
39 | 4
40 | True
41 | False
42 |
43 |
44 | pdbonly
45 | true
46 | bin\Release\
47 | TRACE
48 | prompt
49 | 4
50 | true
51 |
52 |
53 |
54 | False
55 | ..\packages\Jurassic.2.1.1\lib\Jurassic.dll
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | true
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | {80CC9F66-E7D8-4DDD-85B6-D9E6CD0E93E2}
82 | 8
83 | 0
84 | 0
85 | primary
86 | False
87 | False
88 |
89 |
90 | {26AD1324-4B7C-44BC-84F8-B86AED45729F}
91 | 10
92 | 0
93 | 0
94 | primary
95 | False
96 | False
97 |
98 |
99 | {1A31287A-4D7D-413E-8E32-3B374931BD89}
100 | 8
101 | 0
102 | 0
103 | primary
104 | False
105 | False
106 |
107 |
108 | {2CE2370E-D744-4936-A090-3FFFE667B0E1}
109 | 9
110 | 0
111 | 0
112 | primary
113 | False
114 | False
115 |
116 |
117 | {1CBA492E-7263-47BB-87FE-639000619B15}
118 | 8
119 | 0
120 | 0
121 | primary
122 | False
123 | False
124 |
125 |
126 | {00020430-0000-0000-C000-000000000046}
127 | 2
128 | 0
129 | 0
130 | primary
131 | False
132 | False
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 | component
144 |
145 |
146 | True
147 | True
148 | Settings.settings
149 |
150 |
151 | True
152 | True
153 | Resources.resx
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 | ResXFileCodeGenerator
163 | Resources.Designer.cs
164 | Designer
165 |
166 |
167 | true
168 | VSPackage
169 |
170 |
171 |
172 |
173 |
174 | SettingsSingleFileGenerator
175 | Settings.Designer.cs
176 |
177 |
178 | Designer
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 | Menus.ctmenu
187 | Designer
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 | Resources\LICENSE.txt
196 | true
197 |
198 |
199 | true
200 |
201 |
202 |
203 |
204 | true
205 |
206 |
207 |
208 |
209 | true
210 |
211 |
212 |
213 |
214 |
221 |
222 | ..\packages\StyleCop.MSBuild.4.7.47.0\tools\StyleCop.targets
223 |
224 |
225 |
226 | Failed to import StyleCop.MSBuild targets from '$(StyleCopMSBuildTargetsFile)'. The StyleCop.MSBuild package was either missing or incomplete when the project was loaded. Ensure that the package is present and then restart the build. If you are using an IDE (e.g. Visual Studio), reload the project before restarting the build.
227 | Failed to import StyleCop.MSBuild targets from '$(StyleCopMSBuildTargetsFile)'. The StyleCop.MSBuild package was either missing or incomplete when the project was loaded (but is now present). To fix this, restart the build. If you are using an IDE (e.g. Visual Studio), reload the project before restarting the build.
228 | Failed to import StyleCop.MSBuild targets from '$(StyleCopMSBuildTargetsFile)'. The StyleCop.MSBuild package was either missing or incomplete when the project was loaded. To fix this, restore the package and then restart the build. If you are using an IDE (e.g. Visual Studio), you may need to reload the project before restarting the build. Note that regular NuGet package restore (during build) does not work with this package because the package needs to be present before the project is loaded. If this is an automated build (e.g. CI server), you may want to ensure that the build process restores the StyleCop.MSBuild package before the project is built.
229 | Failed to import StyleCop.MSBuild targets from '$(StyleCopMSBuildTargetsFile)'. The StyleCop.MSBuild package was either missing or incomplete when the project was loaded (but is now present). To fix this, restart the build. If you are using an IDE (e.g. Visual Studio), reload the project before restarting the build. Note that when using regular NuGet package restore (during build) the package will not be available for the initial build because the package needs to be present before the project is loaded. If package restore executes successfully in the initial build then the package will be available for subsequent builds. If this is an automated build (e.g. CI server), you may want to ensure that the build process restores the StyleCop.MSBuild package before the initial build.
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 | StyleCopMSBuildTargetsNotFound;$(PrepareForBuildDependsOn)
243 |
244 |
--------------------------------------------------------------------------------
/GruntLauncher/GruntLauncherPackage.cs:
--------------------------------------------------------------------------------
1 | namespace Bjornej.GruntLauncher
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 | using System.ComponentModel.Design;
6 | using System.Diagnostics;
7 | using System.IO;
8 | using System.Runtime.InteropServices;
9 | using Bjornej.GruntLauncher.Helpers;
10 | using Microsoft.VisualStudio.Shell;
11 | using EnvDTE80;
12 | using EnvDTE;
13 | using System.Text.RegularExpressions;
14 | using System.Text;
15 |
16 |
17 |
18 | ///
19 | /// Main class that implements the gruntLauncher packages
20 | ///
21 | [PackageRegistration(UseManagedResourcesOnly = true)]
22 | [InstalledProductRegistration("#110", "#112", "1.1", IconResourceID = 400)]
23 | [ProvideMenuResource("Menus.ctmenu", 1)]
24 | [Guid(GuidList.guidGruntLauncherPkgString)]
25 | [ProvideAutoLoad("{f1536ef8-92ec-443c-9ed7-fdadf150da82}")]
26 | [ProvideOptionPage(typeof(OptionPage), "Grunt Launcher", "General", 0, 0, true)]
27 | public sealed class GruntLauncherPackage : Package
28 | {
29 | ///
30 | /// List of dynamic commands
31 | ///
32 | private static List commands;
33 |
34 | ///
35 | /// Base Grunt command
36 | ///
37 | private static OleMenuCommand baseCommand;
38 |
39 | ///
40 | /// Dictionary of currently running processes
41 | ///
42 | private static Dictionary processes;
43 |
44 | ///
45 | /// Last clicked file. Used to avoid reevaluating continuosly the same file
46 | ///
47 | private string lastFile;
48 |
49 | ///
50 | /// The DTE object of Visual Studio
51 | ///
52 | private static DTE2 dte;
53 |
54 | private static string exclusionRegex { get; set; }
55 |
56 | ///
57 | /// Default constructor of the package.
58 | /// Inside this method you can place any initialization code that does not require
59 | /// any Visual Studio service because at this point the package object is created but
60 | /// not sited yet inside Visual Studio environment. The place to do all the other
61 | /// initialization is the Initialize method.
62 | ///
63 | public GruntLauncherPackage()
64 | {
65 | processes = new Dictionary();
66 | }
67 |
68 | /////////////////////////////////////////////////////////////////////////////
69 | // Overridden Package Implementation
70 | #region Package Members
71 |
72 | ///
73 | /// Initialization of the package; this method is called right after the package is sited, so this is the place
74 | /// where you can put all the initialization code that rely on services provided by VisualStudio.
75 | ///
76 | protected override void Initialize()
77 | {
78 | base.Initialize();
79 | dte = GetService(typeof(DTE)) as DTE2;
80 |
81 | DTE env = (DTE)GetService(typeof(DTE));
82 |
83 | EnvDTE.Properties props = env.get_Properties("Grunt Launcher", "General");
84 |
85 | exclusionRegex = (string)props.Item("TaskRegex").Value;
86 |
87 | // Add our command handlers for menu (commands must exist in the .vsct file)
88 | OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
89 | if (null != mcs)
90 | {
91 | // Create the command for the menu item.
92 | CommandID cmdGrunt = new CommandID(GuidList.guidGruntLauncherCmdSet, (int)PkgCmdIDList.cmdidGruntLauncher);
93 | OleMenuCommand gruntCommand = new OleMenuCommand(this.GruntCallback, cmdGrunt);
94 | gruntCommand.Visible = false;
95 | gruntCommand.BeforeQueryStatus += GruntBeforeQueryStatus;
96 | baseCommand = gruntCommand;
97 | mcs.AddCommand(gruntCommand);
98 |
99 | CommandID gulpMenuCommandID = new CommandID(GuidList.guidGruntLauncherCmdSet, (int)PkgCmdIDList.cmdidGulpLauncher);
100 | OleMenuCommand gulpCommand = new OleMenuCommand(this.GulpCallback, gulpMenuCommandID);
101 | gulpCommand.Visible = false;
102 | gulpCommand.BeforeQueryStatus += GulpBeforeQueryStatus;
103 | mcs.AddCommand(gulpCommand);
104 |
105 | CommandID cmdBower = new CommandID(GuidList.guidGruntLauncherCmdSet, (int)PkgCmdIDList.cmdidBowerUpdater);
106 | OleMenuCommand bower = new OleMenuCommand(this.UpdateBower, cmdBower);
107 | bower.BeforeQueryStatus += BowerBeforeQueryStatus;
108 | mcs.AddCommand(bower);
109 |
110 | CommandID cmdNpm = new CommandID(GuidList.guidGruntLauncherCmdSet, (int)PkgCmdIDList.cmdidNpmUpdater);
111 | OleMenuCommand npm = new OleMenuCommand(this.UpdateNpm, cmdNpm);
112 | npm.BeforeQueryStatus += NpmBeforeQueryStatus;
113 | mcs.AddCommand(npm);
114 |
115 | CommandID cmdBowerInstall = new CommandID(GuidList.guidGruntLauncherCmdSet, (int)PkgCmdIDList.cmdidBowerInstaller);
116 | OleMenuCommand bow = new OleMenuCommand(this.InstallBower, cmdBowerInstall);
117 | bow.BeforeQueryStatus += BowerInstallBeforeQueryStatus;
118 | mcs.AddCommand(bow);
119 | }
120 | }
121 |
122 | private void BowerInstallBeforeQueryStatus(object sender, EventArgs e)
123 | {
124 | OleMenuCommand button = (OleMenuCommand)sender;
125 | packageFile = SolutionHelpers.GetSourceFilePath();
126 | bool isPackage = Path.GetFileName(packageFile).Equals("bower.json", StringComparison.OrdinalIgnoreCase);
127 | button.Visible = isPackage;
128 | }
129 |
130 | private void InstallBower(object sender, EventArgs e)
131 | {
132 | OleMenuCommand button = (OleMenuCommand)sender;
133 | string rootDir = new DirectoryInfo(packageFile).Name;
134 | RunProcess(button, " /c \"bower install 2>&1 \" ", false);
135 | }
136 |
137 | #endregion
138 |
139 | #region NPM
140 |
141 | string packageFile;
142 |
143 | private void NpmBeforeQueryStatus(object sender, EventArgs e)
144 | {
145 | OleMenuCommand button = (OleMenuCommand)sender;
146 | packageFile = SolutionHelpers.GetSourceFilePath();
147 | bool isPackage = Path.GetFileName(packageFile).Equals("package.json", StringComparison.OrdinalIgnoreCase);
148 | button.Visible = isPackage;
149 | }
150 |
151 | private void UpdateNpm(object sender, EventArgs e)
152 | {
153 | OleMenuCommand button = (OleMenuCommand)sender;
154 | string rootDir = new DirectoryInfo(packageFile).Name;
155 | RunProcess(button, " /c \"npm install 2>&1 \" ", false);
156 | }
157 |
158 | #endregion
159 |
160 | #region Bower
161 |
162 | private bool isParent, isChild;
163 |
164 | private void BowerBeforeQueryStatus(object sender, EventArgs e)
165 | {
166 | OleMenuCommand button = (OleMenuCommand)sender;
167 | string path = SolutionHelpers.GetSourceFilePath();
168 |
169 | isParent = path.EndsWith("bower_components\\", StringComparison.OrdinalIgnoreCase);
170 |
171 | if (isParent)
172 | {
173 | button.Text = "Bower: Update all packages";
174 | }
175 | else
176 | {
177 | isChild = Directory.GetParent(path).Parent.Name.EndsWith("bower_components", StringComparison.OrdinalIgnoreCase);
178 | button.Text = "Bower: Update " + Directory.GetParent(path).Name;
179 | }
180 |
181 | button.Visible = isParent || isChild;
182 | }
183 |
184 | private void UpdateBower(object sender, EventArgs e)
185 | {
186 | string path = SolutionHelpers.GetSourceFilePath();
187 | OleMenuCommand button = (OleMenuCommand)sender;
188 |
189 | if (isParent)
190 | {
191 | button.Text = "Update Bower Packages";
192 | RunProcess(button, " /c \"bower update 2>&1 \" ", true);
193 | }
194 | else if (isChild)
195 | {
196 | string bowerPackage = new DirectoryInfo(path).Name;
197 | RunProcess(button, " /c \"bower update " + bowerPackage + " 2>&1 \" ", true);
198 | }
199 | }
200 |
201 | #endregion
202 |
203 | #region Grunt
204 |
205 | ///
206 | /// Determines if the current file is a gruntfile
207 | ///
208 | /// Boolean that indicates if the clicked file was a gruntfile
209 | private bool IsGruntFile()
210 | {
211 | // gets the full path of the clicked file
212 | var path = SolutionHelpers.GetSourceFilePath();
213 |
214 | return ((path.ToLower().IndexOf("gruntfile.js") != -1) ||(path.ToLower().IndexOf("gruntfile.ts") != -1) || (path.ToLower().IndexOf("gruntfile.coffee") != -1));
215 | }
216 |
217 | ///
218 | /// Sets the visibility of the command and creates the dynamic list of commands
219 | ///
220 | /// Sender of the event
221 | /// Event arguments
222 | private void GruntBeforeQueryStatus(object sender, EventArgs e)
223 | {
224 | // gets the full path of the clicked file
225 | var path = SolutionHelpers.GetSourceFilePath();
226 |
227 | var myCommand = sender as OleMenuCommand;
228 |
229 | // if the currently selected file is a Gruntfile set the command to visible
230 | myCommand.Visible = this.IsGruntFile();
231 |
232 |
233 | if (!this.IsGruntFile() && !this.IsGulpFile())
234 | {
235 | this.lastFile = path;
236 | }
237 |
238 | if (!this.IsNewFile())
239 | {
240 | return;
241 | }
242 |
243 |
244 |
245 |
246 | OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
247 |
248 | // delete the old command list
249 | if (commands == null)
250 | {
251 | commands = new List();
252 | }
253 |
254 | foreach (var cmd in commands)
255 | {
256 | mcs.RemoveCommand(cmd);
257 | }
258 |
259 | if (myCommand.Visible)
260 | {
261 | this.lastFile = path;
262 | var list = GruntParser.ReadAllTasks(path);
263 |
264 | myCommand.Text = "Grunt";
265 | myCommand.Enabled = true;
266 |
267 | if (list.Count == 0) {
268 | myCommand.Enabled = false;
269 | myCommand.Text = "Gruntfile.js not found";
270 | }
271 |
272 | if (list.Contains("default"))
273 | {
274 | list.Remove("default");
275 | }
276 |
277 | string n = exclusionRegex;
278 |
279 | Regex a = null;
280 |
281 | if (!string.IsNullOrEmpty(n)) {
282 | try {
283 | a = new Regex(n);
284 | }
285 | catch (Exception)
286 | {
287 | // invalid regex -> ignore
288 | }
289 |
290 | }
291 |
292 | // creates the list of commands
293 | int j = 1;
294 | foreach (var ele in list)
295 | {
296 | if (a != null)
297 | {
298 | if (a.Match(ele).Success)
299 | {
300 | continue;
301 | }
302 | }
303 |
304 | CommandID menuCommandID = new CommandID(GuidList.guidGruntLauncherCmdSet, (int)PkgCmdIDList.cmdidGruntLauncher + j);
305 | j++;
306 | OleMenuCommand command = new OleMenuCommand(this.GruntCallback, menuCommandID);
307 | command.Text = "Grunt: " + ele;
308 | command.BeforeQueryStatus += (x, y) => { (x as OleMenuCommand).Visible = true; };
309 | commands.Add(command);
310 | mcs.AddCommand(command);
311 | }
312 | }
313 | }
314 |
315 | ///
316 | /// This function is the callback used to execute a command when the a menu item is clicked.
317 | /// See the Initialize method to see how the menu item is associated to this function using
318 | /// the OleMenuCommandService service and the MenuCommand class.
319 | ///
320 | /// Sender of the event
321 | /// Event arguments
322 | private void GruntCallback(object sender, EventArgs e)
323 | {
324 | var cmd = (OleMenuCommand)sender;
325 | var text = cmd.Text;
326 | var task = text.Substring(text.IndexOf(':') + 1).Trim();
327 | if (task == "Grunt") { task = ""; }
328 |
329 | // if the command is checked it means that there is a running grunt task associated
330 | // so we kill it
331 | if (cmd.Checked)
332 | {
333 | System.Diagnostics.Process pro;
334 | processes.TryGetValue(cmd, out pro);
335 | if (pro != null)
336 | {
337 | OutputHelpers.Output("Stopping process " + cmd.Text);
338 | ProcessHelpers.KillProcessAndChildren(pro.Id);
339 | processes.Remove(cmd);
340 | }
341 | }
342 |
343 | if (!cmd.Checked)
344 | {
345 | // launches the grunt process and redirects the output to the output window
346 | RunProcess(cmd, " /c \"grunt --no-color " + task + " 2>&1 \" ", false);
347 | }
348 | else
349 | {
350 | cmd.Checked = false;
351 | }
352 | }
353 |
354 | #endregion
355 |
356 | #region Gulp
357 |
358 | private bool IsGulpFile()
359 | {
360 | // gets the full path of the clicked file
361 | var path = SolutionHelpers.GetSourceFilePath();
362 |
363 | return ((path.ToLower().IndexOf("gulpfile.js") != -1) || (path.ToLower().IndexOf("gulpfile.ts") != -1) || (path.ToLower().IndexOf("gulpfile.coffee") != -1));
364 | }
365 |
366 | private void GulpBeforeQueryStatus(object sender, EventArgs e)
367 | {
368 | // gets the full path of the clicked file
369 | var path = SolutionHelpers.GetSourceFilePath();
370 |
371 | var myCommand = sender as OleMenuCommand;
372 | myCommand.Visible = this.IsGulpFile();
373 |
374 |
375 | if (!this.IsNewFile())
376 | {
377 | return;
378 | }
379 |
380 | OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
381 |
382 | // delete the old command list
383 | if (commands == null)
384 | {
385 | commands = new List();
386 | }
387 |
388 | foreach (var cmd in commands)
389 | {
390 | mcs.RemoveCommand(cmd);
391 | }
392 |
393 | if (myCommand.Visible)
394 | {
395 | this.lastFile = path;
396 |
397 | var list = GulpParser.ReadAllTasks(path);
398 |
399 | myCommand.Text = "Gulp";
400 | myCommand.Enabled = true;
401 |
402 | if (list.Count == 0)
403 | {
404 | myCommand.Enabled = false;
405 | myCommand.Text = "Gulpfile.js not found";
406 | }
407 |
408 | if (list.Contains("default"))
409 | {
410 | list.Remove("default");
411 | }
412 |
413 | string n = exclusionRegex;
414 |
415 | Regex a = null;
416 |
417 | if (!string.IsNullOrEmpty(n))
418 | {
419 | try
420 | {
421 | a = new Regex(n);
422 | }
423 | catch (Exception)
424 | {
425 | // invalid regex -> ignore
426 | }
427 |
428 | }
429 |
430 | // creates the list of commands
431 | int j = 1;
432 | foreach (var ele in list)
433 | {
434 | if (a != null)
435 | {
436 | if (a.Match(ele).Success)
437 | {
438 | continue;
439 | }
440 | }
441 |
442 |
443 | CommandID menuCommandID = new CommandID(GuidList.guidGruntLauncherCmdSet, (int)PkgCmdIDList.cmdidGulpLauncher + j);
444 | j++;
445 | OleMenuCommand command = new OleMenuCommand(this.GulpCallback, menuCommandID);
446 | command.Text = "Gulp: " + ele;
447 | command.BeforeQueryStatus += (x, y) => { (x as OleMenuCommand).Visible = true; };
448 | commands.Add(command);
449 | mcs.AddCommand(command);
450 | }
451 | }
452 | }
453 |
454 |
455 | private void GulpCallback(object sender, EventArgs e)
456 | {
457 | var cmd = (OleMenuCommand)sender;
458 | var text = cmd.Text;
459 | var task = text.Substring(text.IndexOf(':') + 1).Trim();
460 |
461 | if (task == "Gulp") { task = ""; }
462 |
463 | // if the command is checked it means that there is a running grunt task associated
464 | // so we kill it
465 | if (cmd.Checked)
466 | {
467 | System.Diagnostics.Process pro;
468 | processes.TryGetValue(cmd, out pro);
469 | if (pro != null)
470 | {
471 | OutputHelpers.Output("Stopping process " + cmd.Text);
472 | ProcessHelpers.KillProcessAndChildren(pro.Id);
473 | processes.Remove(cmd);
474 | }
475 | }
476 |
477 | if (!cmd.Checked)
478 | {
479 | // launches the grunt process and redirects the output to the output window
480 | RunProcess(cmd, " /c \"gulp --no-color " + task + " 2>&1 \" ", false);
481 | }
482 | else
483 | {
484 | cmd.Checked = false;
485 | }
486 | }
487 |
488 | #endregion
489 |
490 | ///
491 | /// Determines if the solution explorer context menu has been opened on a new file since
492 | /// last time
493 | ///
494 | /// Boolean that indicates if a new file was clicked
495 | private bool IsNewFile()
496 | {
497 | // gets the full path of the clicked file
498 | var path = SolutionHelpers.GetSourceFilePath();
499 |
500 | // optimization to avoid parsing the file again if the clicked file has not changed since last time
501 | if (path == this.lastFile)
502 | {
503 | return false;
504 | }
505 |
506 | return true;
507 | }
508 |
509 | private static void RunProcess(OleMenuCommand cmd, string argument, bool fromRoot)
510 | {
511 | dte.StatusBar.Animate(true, vsStatusAnimation.vsStatusAnimationBuild);
512 |
513 | try
514 | {
515 | System.Diagnostics.ProcessStartInfo procStartInfo = new ProcessStartInfo()
516 | {
517 | RedirectStandardOutput = true,
518 | RedirectStandardError = true,
519 | StandardOutputEncoding = Encoding.UTF8,
520 | StandardErrorEncoding = Encoding.UTF8,
521 | UseShellExecute = false,
522 | CreateNoWindow = true,
523 | WorkingDirectory = fromRoot ? SolutionHelpers.GetRootFolder(dte) : Path.GetDirectoryName(SolutionHelpers.GetSourceFilePath()),
524 | FileName = "cmd",
525 | Arguments = argument,
526 | };
527 |
528 | System.Diagnostics.Process proc = new System.Diagnostics.Process()
529 | {
530 | StartInfo = procStartInfo,
531 | EnableRaisingEvents = true
532 | };
533 |
534 | OutputHelpers.Output("Executing " + cmd.Text + " \r\n\r\n", true);
535 |
536 | proc.OutputDataReceived += (object sendingProcess, DataReceivedEventArgs outLine) => OutputHelpers.Output(outLine.Data + "\r\n");
537 | proc.ErrorDataReceived += (object sendingProcess, DataReceivedEventArgs outLine) => OutputHelpers.Output(outLine.Data + "\r\n");
538 | proc.Exited += (x, y) =>
539 | {
540 | processes.Remove(cmd);
541 | cmd.Checked = false;
542 | dte.StatusBar.Animate(false, vsStatusAnimation.vsStatusAnimationBuild);
543 | };
544 |
545 | proc.Start();
546 |
547 | proc.BeginOutputReadLine();
548 | proc.BeginErrorReadLine();
549 |
550 | cmd.Checked = true;
551 |
552 | processes.Add(cmd, proc);
553 | }
554 | catch (Exception ex)
555 | {
556 | OutputHelpers.Output(ex.Message);
557 | }
558 | }
559 | }
560 | }
561 |
--------------------------------------------------------------------------------