public static void Main(string[] argv, IFileWriter fileWriter) { _fileWriter = fileWriter ?? throw new ArgumentNullException(nameof(fileWriter)); _logger = new Logger(fileWriter); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); _openSolution = true; _createMsBuild = false; var _printVersion = false; var _printHelp = false; var quiteExecution = false; var autoUpdateNuGetDependencies = true; var nugetForceMinVersion = true; var loadUserFile = true; bool offlineMode = false; string nuspecDir = null; var dump = false; var dumpProjectStructure = false; var keepGenerated = false; string slnxFile = null; _pythonEnvVarsPath = null; OptionSet p = new OptionSet() .Add("h|help", "Prints the list of command and exits.", v => _printHelp = v != null) .Add("v|version", "Prints the tool version in the standard output and exits.", v => _printVersion = v != null) .Add("q|quite", "If set (-q/-q+) no popup will be shown in case of exceptions. [Default: not set]", v => quiteExecution = v != null) .Add("<>", "SlnX file path", v => slnxFile = v) .Add("o|openSln", "If set (-o/-o+) opens the generated Sln file. If not set (-o-), the generated Sln will not be opened. [Default: set]", v => _openSolution = v != null) .Add("u|user", "If set (-u/-u+) it loads an eventually present .user file. [Default: set]", v => loadUserFile = v != null) .Add("d|dump", "If set (-d/-d+) it dumps all project paths and environment variables in dump.txt located in the SlnX location. [Default: not set]", v => dump = v != null) .Add("p|slnxProjects", "If set (-p/-p+) it creates a SlnX file with all project and their reference in the SlnX location. [Default: not set]", v => dumpProjectStructure = v != null) .Add("k|keepGenerated", "If set (-k/-k+) it prevent the cleanup of all the slnx.config generated files. Note: this doesn't prevent the files to be overwritten. [Default: not set]", v => keepGenerated = v != null) .Add("py=|pythonModule=", "Path for the python module. If set the specified python module containing all defined environment variables is created. [Default: not set]", v => _pythonEnvVarsPath = v) .Add("b=|batchModule=", "Path to the batch module. If set the specified batch module containing all defined environment variables is created. [Default: not set]", v => _batchEnvVarsPath = v) .Add("ps=|powershellModule=", "Path to the power-shell module. If set the specified power-shell module containing all defined environment variables is created. [Default: not set]", v => _psEnvVarsPath = v) .Add("msb|msbuildModule", "If set (-msb/-msb+) a MSBuild module containing all defined environment variables is created in the SlnX location. [Default: not set]", v => _createMsBuild = v != null) .Add("log", "If set (-log/-log+), a log file location in the SlnX directory (or EXE if that path is invalid) will be created. [Default: false]", v => _logEnabled = v != null) .Add("lv=|logVerbosity=", string.Format("Set the log level of verbosity. Valid values {0}. [Default: {1}]", string.Join(",", Enum.GetNames <LogLevel>()), _logLevel), v => _logLevel = ParseLogLevel(v)) .Add("ns=|nuspec=", "Output path for the NuGet package created based on the current solution. [Default: not set]", v => nuspecDir = v) .Add("nd|nugetDependencies", "If set (-nd/-nd+), the dependencies of the provided packages will be also automatically downloaded. [Default: true]", v => autoUpdateNuGetDependencies = v != null) .Add("offline", "If set (-offline/-offline+), The current SlnX packagesPath attribute will be used as source for all packages. [Default: false]", v => offlineMode = v != null) .Add("nf|nugetForceMinVersion", "If set (-nf/-nf+), the tool will check that dependencies fulfill the min-version provided (not allowing newer versions). [Default: true]", v => nugetForceMinVersion = v != null); try { p.Parse(argv); if (_printVersion) { Console.WriteLine("SlnLauncher v{0}", typeof(SlnxHandler).Assembly.GetName().Version.ToString(3)); return; } if (_printHelp) { Console.WriteLine("SlnLauncher v{0}", typeof(SlnxHandler).Assembly.GetName().Version.ToString(3)); p.WriteOptionDescriptions(Console.Out); return; } if (slnxFile == null) { throw new ArgumentException(string.Format("Invalid parameters, no SlnX file specified.\n\n\t{0}", string.Join("\n\t", argv))); } slnxFile = Path.GetFullPath(Environment.ExpandEnvironmentVariables(slnxFile)); if (File.Exists(slnxFile)) { Environment.CurrentDirectory = Path.GetDirectoryName(slnxFile); } if (_logEnabled) { _logger.SetLog(Path.Join(Environment.CurrentDirectory, Path.GetFileNameWithoutExtension(typeof(Program).Assembly.Location) + ".log"), _logLevel); NuGetClientHelper.NuGetClientHelper.SetLogger(_logger); } _logger.Info("Application started with parameters: {0}", string.Join("\n", argv)); var slnxUserFile = string.Format("{0}{1}", slnxFile, SlnxHandler.SlnxUserExtension); SlnXType slnxUser = null; if (loadUserFile && File.Exists(slnxUserFile)) { slnxUser = SlnxHandler.ReadSlnx(slnxUserFile); } var slnx = new SlnxHandler(slnxFile, slnxUser, _fileWriter, _logger, null, offlineMode); var originalPackageList = new List <NuGetClientHelper.NuGetPackage>(slnx.Packages); bool errorOccured = false; try { DownloadPackages(slnx, quiteExecution, autoUpdateNuGetDependencies); if (_createMsBuild) { CreateMsBuildPropertiesTarget(slnx); } if (!string.IsNullOrEmpty(_pythonEnvVarsPath)) { CreatePythonnModule(slnx, Path.Combine(slnx.SlnxDirectory, _pythonEnvVarsPath)); } if (!string.IsNullOrEmpty(_batchEnvVarsPath)) { CreateBatchModule(slnx, Path.Combine(slnx.SlnxDirectory, _batchEnvVarsPath)); } if (!string.IsNullOrEmpty(_psEnvVarsPath)) { CreatePowerShellModule(slnx, Path.Combine(slnx.SlnxDirectory, _psEnvVarsPath)); } var ignoreDependencyCheck = !autoUpdateNuGetDependencies; _logger.Info($"Running dependency check with force min-version match set to {nugetForceMinVersion}, and ignore dependency is {ignoreDependencyCheck}"); NuGetClientHelper.NuGetClientHelper.CheckPackagesConsistency(slnx.Packages.ToList(), nugetForceMinVersion, ignoreDependencyCheck); _logger.Info($"Checking debug packages consistency..."); foreach (var debugPackage in slnx.DebugSlnxItems.Keys) { foreach (var package in slnx.Packages) { if (package.Dependencies.Where(x => x.PackageDependency.Id.Equals(debugPackage.Identity.Id, StringComparison.OrdinalIgnoreCase)).Any()) { _logger.Warn($"{package} depends on the package {debugPackage.Identity.Id} which is selected for debugging. This might cause runtime issues! Consider marking it for debugging as well."); } } } _logger.Info($"Check if all packages that are bind via .NET ImplementationAssemblies (lib directory) are specified in the SlnX file"); foreach (var package in slnx.Packages.Where((x) => x.PackageType == NuGetClientHelper.NuGetDotNetPackageType.DotNetImplementationAssembly)) { if (!originalPackageList.Where((x) => x.Identity.Id.Equals(package.Identity.Id, StringComparison.OrdinalIgnoreCase)).Any()) { _logger.Info($"The .NET implementation package {package} has been installed as dependency. Consider define it explicitly. Execute a dump to analyze dependency graph."); } } _logger.Info($"Check if all packages that are bind via .NET CompileTimeAssemblies (ref directory) are specified in the SlnX file"); foreach (var package in slnx.Packages.Where((x) => x.PackageType == NuGetClientHelper.NuGetDotNetPackageType.DotNetCompileTimeAssembly)) { if (originalPackageList.Where((x) => x.Identity.Id.Equals(package.Identity.Id, StringComparison.OrdinalIgnoreCase)).FirstOrDefault() == default(NuGetPackage)) { _logger.Info($"The .NET compile time package {package} has been installed as dependency."); } } MakeSln(slnx); if (!keepGenerated) { slnx.CleanGenereatedFilesRecurisvely(); } slnx.CreateGenereatedFilesRecurisvely(); if (!string.IsNullOrEmpty(nuspecDir)) { nuspecDir = Path.GetFullPath(slnx.SafeExpandEnvironmentVariables(nuspecDir)); if (nuspecDir == slnx.SlnxDirectory) { throw new Exception($"The provided nuspec directory is the same as the slnx folder. Please specify a sub folder."); } if (!Directory.Exists(nuspecDir)) { Directory.CreateDirectory(nuspecDir); } else { if (Directory.EnumerateFileSystemEntries(nuspecDir).Any()) { throw new Exception($"The provided nuspec directory is not empty: '{nuspecDir}'"); } } var nuspec = slnx.GetNuGetPackageInformation(); if (nuspec != null) { NuGetClientHelper.NuspecGenerator.Generate(nuspecDir, nuspec); } else { throw new Exception("Missing or invalid nuget content information in the provided SlnX file."); } } if (dumpProjectStructure) { DumpProjectSlnx(slnx); } } catch { errorOccured = true; throw; } finally { if (dump) { Dump(slnx, errorOccured); } } if (_logger.LogLevelDetected(LogLevel.Warning)) { if (!quiteExecution) { var baseMsg = $"Warning(s) detected. This could cause runtime issues.\nIt's highly suggested to"; string message = ""; if (_logEnabled) { message = $"{baseMsg} review them in the log file: {_logger.LogPath}"; } else { message = $"{baseMsg} re-run the application with log turned on."; } new InfoBox("Warning", message, System.Drawing.SystemIcons.Warning.ToBitmap()).ShowDialog(); } } _logger.Info($"Done!"); if (_openSolution) { OpenSln(slnx.SlnPath); } } catch (Exception ex) { string exText = ""; var stackTrace = ex.StackTrace; while (ex != null) { exText = string.Join("\n", ex.Message); ex = ex.InnerException; } _logger.Error(exText); _logger.Error(stackTrace); if (!quiteExecution) { string message; if (_logEnabled) { message = $"Inspect the log for more information.\nLog file: {_logger.LogPath}\n\n{exText}"; } else { message = $"Re-run the application with log turned on (--log) for more information\n\n{exText}"; } new InfoBox("Error", message, System.Drawing.SystemIcons.Error.ToBitmap()).ShowDialog(); } else { throw; } } }