Click here to Skip to main content
15,896,063 members
Articles / .NET

Versioning Controlled Build

Rate me:
Please Sign up or sign in to vote.
4.90/5 (237 votes)
8 Dec 2013CPOL35 min read 2.2M   20.6K   779  
A Visual Studio add-in and command-line utility that automates versioning of .NET and VC++ projects
/*
 * Filename:    Main.cs
 * Product:     Versioning Controlled Build
 * Solution:    BuildAutoIncrement
 * Project:     CommandLine
 * Description: Entry class for command-line utility.
 * Copyright:   Julijan �ribar, 2004-2013
 * 
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the author(s) be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
 *    appreciated but is not required.
 * 2. Altered source versions must be plainly marked as such, and must not be
 *    misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 */
using System;
using System.Collections;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Resources;
using System.Reflection;
using System.Text;
using System.Windows.Forms;

namespace BuildAutoIncrement {
	/// <summary>
	///   Main class used for command line tool.
	/// </summary>
    public class CommandLineMain {

        #region FileDialogProxy
        /// <summary>
        ///   Class used to ensure FileDialog is shown on taskbar when opened
        ///   from command prompt.
        /// </summary>
        private class FileDialogProxy : System.Windows.Forms.Form {

            public FileDialogProxy() {
                ShowInTaskbar = true;
                Text = Title;
                Icon = AppIcon;
                Size = Size.Empty;
                Opacity = 0;
            }

            protected override void WndProc(ref Message m) {
                base.WndProc(ref m);
                if (m.Msg == (int)Win32Api.WM.SHOWWINDOW) {
                    if ((int)m.WParam == 1) {
                        // hack to display form in the taskbar
                        WindowState = FormWindowState.Minimized;
#if !DEBUG
                        TopMost = true;
#endif
                        OpenFileDialog fd = new OpenFileDialog();
                        fd.Filter = SolutionFilesFilter;
                        fd.Multiselect = false;
                        fd.Title = OpenSolutionFile;
                        DialogResult = fd.ShowDialog(this);
                        Filename = fd.FileName;
                        Close();
                    }
                }
            }

            public string Filename;
        }

        #endregion // FileDialogProxy

        #region Constructors
        /// <summary>
        ///   Creates empty <c>CommandLineMain</c> object.
        /// </summary>
        private CommandLineMain() {
        }

        /// <summary>
        ///   Creates <c>CommandLineMain</c> object with command line arguments
        ///   provided.
        /// </summary>
        /// <param name="args">
        ///   Command line arguments.
        /// </param>
        public CommandLineMain(string[] args) : this() {
            Console.WriteLine(CreateInfoFromAttributes());
            if (args.Length == 1 && args[0] == "/?") {
                WriteUsage();
                return;
            }
            VisualStyles.EnableStyles();
            m_commandLineArgs = new CommandLineArgs(args);
            Debug.Assert(m_commandLineArgs != null);
            SolutionFilename = m_commandLineArgs.SolutionFilename;
            Debug.Assert(SolutionFilename != null);
            // if no solution filename has been supplied, show OpenFileDialog
            // to select a solution or desktop file
            if (SolutionFilename.Length == 0) {
                FileDialogProxy fdp = new FileDialogProxy();
                if (fdp.ShowDialog() == DialogResult.OK) {
                    SolutionFilename = fdp.Filename;
                }
            }
            if (File.Exists(SolutionFilename)) {
                // load configuration
                VcbConfiguration configuration = ConfigurationPersister.Instance.Configuration;
                if (!configuration.ConfigurationFileRead)
                    Console.WriteLine("Warning: Failed to read configuration file - using default configuration.");
                // apply command line switches to modify configuration
                ApplyCommandLineArgsToIncrementScheme(configuration.NumberingOptions);
                // now validate version string
                if (m_commandLineArgs.NewVersion.Length > 0 && !ProjectVersion.IsValidPattern(m_commandLineArgs.NewVersion)) {
                    if (MustBeValidVersionString(configuration.NumberingOptions)) {
                        throw new InvalidCommandLineArgumentException(string.Format(InvalidVersionFormat, m_commandLineArgs.NewVersion));
                    }
                    else if (!configuration.NumberingOptions.AllowArbitraryInformationalVersion) {
                        Console.WriteLine(string.Format(InvalidVersionFormat, m_commandLineArgs.NewVersion));
                    }
                }
                // create file readers
                if (SolutionFilename.ToLower().EndsWith(".dsw")) {
                    m_sfr = new DswFileReader(SolutionFilename, configuration, m_commandLineArgs.SourceSafeUserOptions);
                }
                else if (SolutionFilename.ToLower().EndsWith(".sln")) {
                    m_sfr = SlnFileReader.SlnFileReaderFactory.GetSlnFileReader(SolutionFilename, configuration, m_commandLineArgs.SourceSafeUserOptions);
                }
                else {
                    throw new InvalidCommandLineArgumentException(NotSupportedFilesError);
                }
                if (ValidateSolutionIntegrity() && ValidateProjectnames()) {
                    Debug.Assert(m_sfr != null);
                    m_sfr.ApplyConfiguration(configuration);
                    IProjectFilter projectFilter = new ProjectFilterByName(configuration.NumberingOptions.IncludeSetupProjects, configuration.DisplayOptions.ShowNonVersionableProjects, 
                        configuration.DisplayOptions.ShowSubProjectRoot, configuration.DisplayOptions.ShowEnterpriseTemplateProjectRoot, 
                        m_commandLineArgs.ProjectsAllowedForVersionModification, m_commandLineArgs.ProjectsToExclude, m_commandLineArgs.ProjectsToForce);
                    m_sfr.ApplyFilter(projectFilter);
                    if (m_commandLineArgs.StartGui) {
                        StartGui();
                    }
                    else {
                        ExecuteBatchCommand(configuration.NumberingOptions);
                    }
                }
            }
            else {
                Console.WriteLine(NoSolutionFileProvided);
            }
#if DEBUG
            Console.WriteLine("Finished. Press any key...");
            Console.ReadLine();
#endif
        }

        #endregion // Constructors

        #region Private methods
        
        /// <summary>
        ///   Executes batch command.
        /// </summary>
        /// <param name="sfr">
        ///   <c>SolutionFileReader</c> object used to explore the solution.
        /// </param>
        /// <param name="commandLineArgs">
        ///   Command line arguments.
        /// </param>
        private void ExecuteBatchCommand(NumberingOptions numberingOptions) {
            Debug.Assert(m_sfr != null);
            Debug.Assert(m_commandLineArgs != null);
            // find to which versions new version should be applied
            AssemblyVersionType applyToTypes = numberingOptions.DefaultVersionType;
            if (numberingOptions.ApplyToAllTypes)
                applyToTypes = AssemblyVersionType.All;
            // if command-line provided version(s) to apply changes to, then 
            // use them and override configuration settings
            if (m_commandLineArgs.ApplyToTypes != AssemblyVersionType.None)
                applyToTypes = m_commandLineArgs.ApplyToTypes;
            MarkForUpdate(applyToTypes);
            if (SourceSafeCommandLine.IsUnderSourceSafeControl(SolutionFilename))
                CheckOutItems();
            // apply versions to individual types
            if ((applyToTypes & AssemblyVersionType.AssemblyVersion) == AssemblyVersionType.AssemblyVersion)
                ApplyVersion(AssemblyVersionType.AssemblyVersion, numberingOptions);
            if ((applyToTypes & AssemblyVersionType.AssemblyInformationalVersion) == AssemblyVersionType.AssemblyInformationalVersion)
                ApplyVersion(AssemblyVersionType.AssemblyInformationalVersion, numberingOptions);
            if ((applyToTypes & AssemblyVersionType.AssemblyFileVersion) == AssemblyVersionType.AssemblyFileVersion)
                ApplyVersion(AssemblyVersionType.AssemblyFileVersion, numberingOptions);
            if (m_commandLineArgs.DisplaySummaryOptions.DoOutputSummary)
                OutputSummary();
        }

        /// <summary>
        ///   Marks projects for update according to configuration settings
        ///   and command line arguments.
        /// </summary>
        /// <param name="applyToTypes">
        ///   <c>AssemblyVersionType</c> flags indicating which version types
        ///   may be updated.
        /// </param>
        private void MarkForUpdate(AssemblyVersionType applyToTypes) {
            Debug.Assert(m_sfr != null);
            foreach (ProjectInfo pi in m_sfr.ProjectInfoList) {
                if (m_commandLineArgs.ApplyToAllProjects || pi.Modified) {
                    pi.MarkAssemblyVersionsForUpdate(applyToTypes);
                } 
                else {
                    // if in the list of projects forced for update
                    foreach (string projectName in m_commandLineArgs.ProjectsToForce) {
                        if (pi.CompareTo(projectName) == 0) {
                            pi.MarkAssemblyVersionsForUpdate(applyToTypes);
                        }
                    }
                }
            }
        }

        /// <summary>
        ///   Checks out version files if marked for updated.
        /// </summary>
        private void CheckOutItems() {
            ArrayList projectsToCheckOut = new ArrayList();
            SourceSafeCommandLine sscl = new SourceSafeCommandLine(SolutionFilename, m_commandLineArgs.SourceSafeUserOptions);
            foreach (ProjectInfo pi in m_sfr.ProjectInfoList) {
                if (pi.ToUpdate) {
                    projectsToCheckOut.Add(pi);
                }
            }
            m_sfr.CheckOutProjectVersionFiles((ProjectInfo[])projectsToCheckOut.ToArray(typeof(ProjectInfo)));
        }

        /// <summary>
        ///   Outputs version update summary.
        /// </summary>
        private void OutputSummary() {
            Debug.Assert(m_sfr != null && m_sfr.UpdateSummary != null);
            string updateSummary = m_sfr.UpdateSummary.ToString();
            Debug.Assert(updateSummary.Length > 0);
            string failedToCheckOut = SummaryOfFailedToCheckOut();
            string filesCheckedOut = SummaryOfCheckedOutFiles();
            // output this to console always:
            Console.Write(failedToCheckOut);
            if (m_commandLineArgs.DisplaySummaryOptions.ToConsole) {
                Console.Write(filesCheckedOut);
                Console.WriteLine(updateSummary);
            }
            // create summary file name
            string summaryFilename = m_commandLineArgs.DisplaySummaryOptions.SummaryFilename;
            if (summaryFilename.Length == 0) {
                summaryFilename = UpdateSummary.CreateSummaryFilename(m_sfr.SolutionName);
            }
            // if files already exists, delete it
            if (File.Exists(summaryFilename)) {
                try {
                    File.Delete(summaryFilename);
                }
                catch (Exception exception) {
                    Console.WriteLine(exception.Message);
                }
            }
            // output summary to file
            if (m_commandLineArgs.DisplaySummaryOptions.ToFile) {
                using (StreamWriter sw = new StreamWriter(summaryFilename)) {
                    sw.Write(failedToCheckOut);
                    sw.Write(filesCheckedOut);
                    sw.WriteLine(updateSummary);
                }
            }
        }

        /// <summary>
        ///   Gets a formated string of checked out filenames.
        /// </summary>
        /// <returns>
        ///   String of check-out operation.
        /// </returns>
        private string SummaryOfCheckedOutFiles() {
            using (StringWriter sw = new StringWriter()) {
                if (m_sfr.FilesCheckedOut.Length > 0) {
                    sw.WriteLine(FilesCheckedOutCaption);
                    foreach (string filename in m_sfr.FilesCheckedOut) {
                        sw.WriteLine(filename);
                    }
                    sw.WriteLine();
                }
                sw.Flush();
                return sw.ToString();
            }
        }

        /// <summary>
        ///   Gets a formated string of files failed to check out.
        /// </summary>
        /// <returns>
        ///   Summary for files failed to check out.
        /// </returns>
        private string SummaryOfFailedToCheckOut() {
            Debug.Assert(m_sfr.FilesFailedToCheckOut != null);
            using (StringWriter sw = new StringWriter()) {
                if (m_sfr.FilesFailedToCheckOut.Length > 0) {
                    sw.WriteLine(FailedToCheckOutCaption);
                    for (int i = 0; i < m_sfr.FilesFailedToCheckOut.Length; i++) {
                        sw.WriteLine(m_sfr.FilesFailedToCheckOut[i]);
                    }
                    sw.WriteLine();
                }
                sw.Flush();
                return sw.ToString();
            }
        }

        /// <summary>
        ///   Applies new version(s).
        /// </summary>
        /// <param name="sfr"></param>
        /// <param name="commandLineArgs"></param>
        /// <param name="versionToChange"></param>
        
        /// <summary>
        ///   Applies new version(s).
        /// </summary>
        /// <param name="versionToChange">
        ///   <c>AssemblyVersionType</c> flags for version types to change.
        /// </param>
        /// <param name="numberingOptions">
        ///   <c>NumberingOptions</c> object.
        /// </param>
        private void ApplyVersion(AssemblyVersionType versionToChange, NumberingOptions numberingOptions) {
            Debug.Assert(m_sfr != null);
            Debug.Assert(m_commandLineArgs != null);
            Debug.Assert(versionToChange != AssemblyVersionType.All && versionToChange != AssemblyVersionType.None);
            NewVersionProvider nvp = new NewVersionProvider(numberingOptions);
            foreach (ProjectInfo pi in m_sfr.ProjectsToUpdate) {
                if (pi.CurrentAssemblyVersions.ContainsVersion(versionToChange)) {
                    // if a new version hasn't been provided
                    if (m_commandLineArgs.NewVersion.Length == 0) {
                        if (pi.ToUpdate) {
                            pi.SetToBecomeVersion(nvp);
                            string newVersion = pi.ToBecomeAssemblyVersions.HighestProjectVersion.ToString();
                            SaveVersion(pi, versionToChange, newVersion);
                        }
                    }
                    else {
                        if (ProjectVersion.IsValidPattern(m_commandLineArgs.NewVersion)) {
                            int buildAndRevisionResetValue = (int)numberingOptions.ResetBuildAndRevisionTo;
                            string newVersion = ProjectVersion.ApplyVersionPattern(m_commandLineArgs.NewVersion, pi.CurrentAssemblyVersions[versionToChange].ToString(), buildAndRevisionResetValue);
                            SaveVersion(pi, versionToChange, newVersion);
                        }
                        else {
                            // irregular pattern cannot be applied to ProductVersion of VC++ projects
                            if (pi.ProjectTypeInfo.ProjectType != ProjectType.VCppProject) {
                                Debug.Assert(versionToChange == AssemblyVersionType.AssemblyInformationalVersion);
                                SaveVersion(pi, versionToChange, m_commandLineArgs.NewVersion);
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        ///   Checks if validation of version string may be performed.
        /// </summary>
        /// <param name="numberingOptions">
        ///   <c>NumberingOptions</c> object.
        /// </param>
        /// <returns>
        ///   <c>true</c> if version string must be a valid one.
        /// </returns>
        private bool MustBeValidVersionString(NumberingOptions numberingOptions) {
            Debug.Assert(numberingOptions != null);
            Debug.Assert(m_commandLineArgs != null);
            // if defined explicitely by command-line argument
            if (m_commandLineArgs.ApplyToTypes == AssemblyVersionType.AssemblyInformationalVersion)
                return false;
            // else use configuration settings
            if ((m_commandLineArgs.ApplyToTypes == AssemblyVersionType.None) && !numberingOptions.ApplyToAllTypes && (numberingOptions.DefaultVersionType == AssemblyVersionType.AssemblyInformationalVersion)) 
                return false;
            return true;
        }

        /// <summary>
        ///   Saves version(s).
        /// </summary>
        /// <param name="pi">
        ///   <c>ProjectInfo</c> for which new version must be saved.
        /// </param>
        /// <param name="versionToChange">
        ///   <c>AssemblyVersionType</c> flag for version to change.
        /// </param>
        /// <param name="newVersion">
        ///   New version to apply.
        /// </param>
        private void SaveVersion(ProjectInfo pi, AssemblyVersionType versionToChange, string newVersion) {
            Debug.Assert(m_sfr != null);
            Debug.Assert(pi != null);
            Debug.Assert(versionToChange != AssemblyVersionType.All && versionToChange != AssemblyVersionType.None);
            Debug.Assert(newVersion != null && newVersion.Length > 0);
            if (pi.Save(versionToChange, newVersion)) {
                m_sfr.UpdateSummary.SetUpdated(pi, versionToChange, newVersion);
            }
        }

        /// <summary>
        ///   Apply command line arguments to configuration.
        /// </summary>
        /// <param name="numberingOptions">
        ///   <c>NumberingOptions</c> object.
        /// </param>
        private void ApplyCommandLineArgsToIncrementScheme(NumberingOptions numberingOptions) {
            numberingOptions.ApplyToAllTypes = m_commandLineArgs.ApplyToTypes != numberingOptions.DefaultVersionType;
            switch (m_commandLineArgs.SynchronizeProjects) {
            case CommandLineArgs.ProjectsSynchronization.IncrementAndSynchronize:
                numberingOptions.BatchCommandIncrementScheme = BatchCommandIncrementScheme.IncrementAllAndSynchronize;
                break;
            case CommandLineArgs.ProjectsSynchronization.Synchronize:
                numberingOptions.BatchCommandIncrementScheme = BatchCommandIncrementScheme.IncrementModifiedOnlyAndSynchronize;
                break;
            case CommandLineArgs.ProjectsSynchronization.None:
                numberingOptions.BatchCommandIncrementScheme = BatchCommandIncrementScheme.IncrementModifiedIndependently;
                break;
            case CommandLineArgs.ProjectsSynchronization.NotDefined:
                // use as configured
                break;
            default:
                Debug.Assert(false, "Not supported value of CommandLineArgs.ProjectsSynchronization");
                break;
            }
        }

        /// <summary>
        ///   Starts GUI form if "/g" command line switch was provided.
        /// </summary>
        /// <param name="sb">
        ///   Solution browser used to fill the listview.
        /// </param>
        private void StartGui() {
            MainForm mainForm = new MainForm(m_sfr);
#if !DEBUG
            mainForm.TopMost = true;
#endif
            mainForm.ShowInTaskbar = true;
            mainForm.BuildButtonsVisible = false;
            mainForm.Icon = AppIcon;
            mainForm.MinimizeBox = true;
            if (mainForm.ShowDialog() != DialogResult.Cancel) {
                mainForm.SaveVersions();
            }
        }

        /// <summary>
        ///   Outputs command line tool usage to the console.
        /// </summary>
        private void WriteUsage() {
            Console.WriteLine(Description);
            Console.WriteLine();
            string name = Assembly.GetEntryAssembly().GetName().Name.ToUpper();
            CommandLineArgs.OuputDescription(name);
        }

        /// <summary>
        ///   Creates product information from custom attributes.
        /// </summary>
        /// <returns>
        ///   String with product information.
        /// </returns>
        private string CreateInfoFromAttributes() {
            string title        = "";
            string product      = "";
            string copyright    = "";
            string company      = "";
            foreach (object obj in Assembly.GetExecutingAssembly().GetCustomAttributes(true)) {
                AssemblyProductAttribute assProduct = obj as AssemblyProductAttribute;
                if (assProduct != null)
                    product = assProduct.Product;
                AssemblyTitleAttribute assTitle = obj as AssemblyTitleAttribute;
                if (assTitle != null)
                    title = assTitle.Title;
                AssemblyCopyrightAttribute assCopyright = obj as AssemblyCopyrightAttribute;
                if (assCopyright != null)
                    copyright = assCopyright.Copyright.Replace("�", "(c)");
                AssemblyCompanyAttribute assCompany = obj as AssemblyCompanyAttribute;
                if (assCompany != null)
                    company = assCompany.Company;
            }
            StringBuilder sb = new StringBuilder(product);
            Version ver = Assembly.GetExecutingAssembly().GetName().Version;
            sb.AppendFormat(" {0}.{1}.{2}", ver.Major, ver.Minor, ver.Revision);
            sb.Append(Environment.NewLine);
            sb.Append(copyright);
            sb.Append(Environment.NewLine);
            return sb.ToString();
        }


        /// <summary>
        ///   Validates solution integrity i.e. if all project files and all 
        ///   items in each project file are found.
        /// </summary>
        /// <returns>
        ///   <c>true</c> if solution is complete.
        /// </returns>
        private bool ValidateSolutionIntegrity() {
            using (StringWriter sw = new StringWriter()) {
                foreach (string projectName in m_sfr.ProjectsNotFound) {
                    sw.WriteLine(ProjectFileNotFound, projectName);
                }
                IDictionaryEnumerator en = m_sfr.FilesNotFound.GetEnumerator();
                while (en.MoveNext()) {
                    string projectName = (string)en.Key;
                    sw.WriteLine(FilesNotFoundForProject, projectName);
                    string[] filesNotFound = (string[])en.Value;
                    foreach (string filename in filesNotFound) {
                        sw.WriteLine("  {0}", filename);
                    }
                }
                sw.Flush();
                string output = sw.ToString();
                if (output.Length > 0)
                    Console.WriteLine(sw.ToString());
#if DEBUG
                return true;
#else
                return output.Length == 0;
#endif
            }
        }

        /// <summary>
        ///   Validates if project names provided by some switches exist in the 
        ///   solution.
        /// </summary>
        /// <returns>
        ///   <c>true</c> if all filenames provided are correct or a switch to
        ///   ignore invalid names is set.
        /// </returns>
        private bool ValidateProjectnames() {
            Debug.Assert(m_commandLineArgs != null);
            using (StringWriter sw = new StringWriter()) {
                foreach (string projectName in m_commandLineArgs.ProjectsAllowedForVersionModification) {
                    if (!m_sfr.ProjectInfoList.Contains(projectName)) {
                        sw.WriteLine(ProjectNotFound, projectName);
                    }
                }
                foreach (string projectName in m_commandLineArgs.ProjectsToExclude) {
                    if (!m_sfr.ProjectInfoList.Contains(projectName)) {
                        sw.WriteLine(ProjectNotFound, projectName);
                    }
                }
                foreach (string projectName in m_commandLineArgs.ProjectsToForce) {
                    if (!m_sfr.ProjectInfoList.Contains(projectName)) {
                        sw.WriteLine(ProjectNotFound, projectName);
                    }
                }
                sw.Flush();
                string output = sw.ToString();
                if (output.Length > 0)
                    Console.WriteLine(sw.ToString());
                return output.Length == 0 || !m_commandLineArgs.CheckProjectsExistance;
            }
        }

        #endregion // Private methods

        #region Private fields

        private SolutionFileReader m_sfr = null;

        private CommandLineArgs m_commandLineArgs = null;

        private readonly string SolutionFilename = null;

        #endregion // Private fields

        #region Static and const strings

        private const string Title                      = "Versioning Controlled Build";
        private const string Description                = "Increments versions of modules in Visual Studio solution.";
        private const string OpenSolutionFile           = "Open Solution File";
        private const string SolutionFilesFilter        = "All solution files (*.sln;*.dsw)|*.sln;*.dsw|Solution files (*.sln)|*.sln|Compatible desktop files (*.dsw)|*.dsw";
        private const string NotSupportedFilesError     = "Only files with \'.sln\' and \'.dsw\' extensions are supported.";
        private const string NoSolutionFileProvided     = "Solution file name not provided - application closed without any changes.";
        private const string ProjectFileNotFound        = "ERROR: Project file '{0}' not found.";
        private const string FilesNotFoundForProject    = "ERROR: Following file(s) in project \'{0}\' not found:";
        private const string ProjectNotFound            = "Project '{0}' not found in current solution.";
        private const string FailedToCheckOutCaption    = "Failed to check out following files:";
        private const string FilesCheckedOutCaption     = "Files checked out:";
        private const string InvalidVersionFormat       = "Invalid version pattern format: \'{0}\'";

        private static readonly Icon   AppIcon;
        
        #endregion // Static and const strings

        #region Static constructor and methods

        /// <summary>
        ///   The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args) {
            try {
                CommandLineMain clm = new CommandLineMain(args);
            }
            catch (Exception exception) {
#if DEBUG
                Console.WriteLine("ERROR: {0}", exception.Message);
                Console.WriteLine(exception.ToString());
                Console.ReadLine();
#else
                Console.WriteLine("ERROR: {0}", exception.Message);
#endif
            }
        }

        /// <summary>
        ///   Static constructor.
        /// </summary>
        static CommandLineMain() {
            ResourceManager resources = new ResourceManager("BuildAutoIncrement.Resources.CommandLine", typeof(CommandLineMain).Assembly);
            Debug.Assert(resources != null);

            AppIcon = ((System.Drawing.Icon)(resources.GetObject("AppIcon")));

            Debug.Assert(AppIcon != null);
        }

        #endregion // Static constructor and methods
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Croatia Croatia
Graduated at the Faculty of Electrical Engineering and Computing, University of Zagreb (Croatia) and received M.Sc. degree in electronics. For several years he was research and lecturing assistant in the fields of solid state electronics and electronic circuits, published several scientific and professional papers, as well as a book "Physics of Semiconductor Devices - Solved Problems with Theory" (in Croatian).
During that work he gained interest in C++ programming language and have co-written "C++ Demystified" (in Croatian), 1st edition published in 1997, 2nd in 2001, 3rd in 2010, 4th in 2014.
After book publication, completely switched to software development, programming mostly in C++ and in C#.
In 2016 coauthored the book "Python for Curious" (in Croatian).

Comments and Discussions