public static async Task <int> Execute( IServiceProvider services, Project project, string command, string[] args) { var environment = (IApplicationEnvironment)services.GetService(typeof(IApplicationEnvironment)); var commandText = project.Commands[command]; var replacementArgs = CommandGrammar.Process( commandText, (key) => GetVariable(environment, key), preserveSurroundingQuotes: false) .ToArray(); var entryPoint = replacementArgs[0]; args = replacementArgs.Skip(1).Concat(args).ToArray(); if (string.IsNullOrEmpty(entryPoint) || string.Equals(entryPoint, "run", StringComparison.Ordinal)) { entryPoint = project.Name; } CallContextServiceLocator.Locator.ServiceProvider = services; return(await ExecuteMain(services, entryPoint, args)); }
internal string AddScriptExtensionPropertyToCommandLine(string scriptCommandline, string scriptExtensionPropertyName) { var scriptArguments = CommandGrammar.Process( scriptCommandline, (s) => null, preserveSurroundingQuotes: true); scriptArguments = scriptArguments.Where(argument => !string.IsNullOrEmpty(argument)).ToArray(); var scriptCommand = scriptArguments.First(); var trimmedCommand = scriptCommand.Trim('\"').Trim('\''); // Path.IsPathRooted only looks at paths conforming to the current os, // we need to account for all things if (!IsPathRootedForAnyOS(trimmedCommand)) { scriptCommand = @".\" + scriptCommand; } if (scriptCommand.EndsWith("\"") || scriptCommand.EndsWith("'")) { var endChar = scriptCommand.Last(); scriptCommand = $"{scriptCommand.TrimEnd(endChar)}$({scriptExtensionPropertyName}){endChar}"; } else { scriptCommand += $"$({scriptExtensionPropertyName})"; } var command = string.Join(" ", new[] { scriptCommand }.Concat(scriptArguments.Skip(1))); return(command); }
internal string ReplaceScriptVariables(string scriptCommandline) { Func <string, string> scriptVariableReplacementDelegate = key => { if (ScriptVariableToMSBuildMap.ContainsKey(key)) { if (ScriptVariableToMSBuildMap[key] == null) { MigrationErrorCodes.MIGRATE1016( $"{key} is currently an unsupported script variable for project migration") .Throw(); } return(ScriptVariableToMSBuildMap[key]); } return($"$({key})"); }; var scriptArguments = CommandGrammar.Process( scriptCommandline, scriptVariableReplacementDelegate, preserveSurroundingQuotes: true); scriptArguments = scriptArguments.Where(argument => !string.IsNullOrEmpty(argument)).ToArray(); return(string.Join(" ", scriptArguments)); }
private static IEnumerable <string> ParseScriptArguments(Project project, string scriptCommandLine, Func <string, string> getVariable) { var scriptArguments = CommandGrammar.Process( scriptCommandLine, GetScriptVariable(project, getVariable), preserveSurroundingQuotes: false); scriptArguments = scriptArguments.Where(argument => !string.IsNullOrEmpty(argument)).ToArray(); if (scriptArguments.Length == 0) { return(null); } return(scriptArguments); }
public void Execute(Runtime.Project project, string scriptName, Func <string, string> getVariable) { IEnumerable <string> scriptCommandLines; if (!project.Scripts.TryGetValue(scriptName, out scriptCommandLines)) { return; } foreach (var scriptCommandLine in scriptCommandLines) { var scriptArguments = CommandGrammar.Process( scriptCommandLine, GetScriptVariable(project, getVariable)); // Command-lines on Windows are executed via "cmd /C" in order // to support batch files, &&, built-in commands like echo, etc. // ComSpec is Windows-specific, and contains the full path to cmd.exe var comSpec = Environment.GetEnvironmentVariable("ComSpec"); if (!string.IsNullOrEmpty(comSpec)) { scriptArguments = new[] { comSpec, "/C", "\"" } .Concat(scriptArguments) .Concat(new[] { "\"" }) .ToArray(); } var startInfo = new ProcessStartInfo { FileName = scriptArguments.FirstOrDefault(), Arguments = String.Join(" ", scriptArguments.Skip(1)), WorkingDirectory = project.ProjectDirectory, #if NET45 UseShellExecute = false, #endif }; var process = Process.Start(startInfo); process.WaitForExit(); } }
private string AddScriptExtension(ProjectPropertyGroupElement propertyGroup, string scriptCommandline, string scriptId) { var scriptArguments = CommandGrammar.Process( scriptCommandline, (s) => null, preserveSurroundingQuotes: false); scriptArguments = scriptArguments.Where(argument => !string.IsNullOrEmpty(argument)).ToArray(); var scriptCommand = scriptArguments.First(); var propertyName = $"MigratedScriptExtension_{scriptId}"; var windowsScriptExtensionProperty = propertyGroup.AddProperty(propertyName, s_windowsScriptExtension); var unixScriptExtensionProperty = propertyGroup.AddProperty(propertyName, s_unixScriptExtension); windowsScriptExtensionProperty.Condition = $" '$(OS)' == 'Windows_NT' and Exists('{scriptCommand}{s_windowsScriptExtension}') "; unixScriptExtensionProperty.Condition = $" '$(OS)' != 'Windows_NT' and Exists('{scriptCommand}{s_unixScriptExtension}') "; return(propertyName); }
public bool Execute(Runtime.Project project, string scriptName, Func <string, string> getVariable) { IEnumerable <string> scriptCommandLines; if (!project.Scripts.TryGetValue(scriptName, out scriptCommandLines)) { return(true); } Report?.WriteLine($"Executing script '{scriptName}' in {Runtime.Project.ProjectFileName}"); foreach (var scriptCommandLine in scriptCommandLines) { // Preserve quotation marks around arguments since command is about to be passed to a shell. May need // the quotes to ensure the shell groups arguments correctly. var scriptArguments = CommandGrammar.Process( scriptCommandLine, GetScriptVariable(project, getVariable), preserveSurroundingQuotes: true); // Ensure the array won't be empty and the elements won't be null or empty strings. scriptArguments = scriptArguments.Where(argument => !string.IsNullOrEmpty(argument)).ToArray(); if (scriptArguments.Length == 0) { continue; } if (RuntimeEnvironmentHelper.IsWindows) { // Only forward slashes are used in script blocks. Replace with backslashes to correctly // locate the script. The directory separator is platform-specific. scriptArguments[0] = scriptArguments[0].Replace( Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); // Command-lines on Windows are executed via "cmd /S /C" in order to support batch files, &&, // built-in commands like echo, et cetera. /S allows quoting the command as well as the arguments. // ComSpec is Windows-specific, and contains the full path to cmd.exe var comSpec = Environment.GetEnvironmentVariable("ComSpec"); if (!string.IsNullOrEmpty(comSpec)) { scriptArguments = new[] { comSpec, "/S", "/C", "\"" } .Concat(scriptArguments) .Concat(new[] { "\"" }) .ToArray(); } } else { // Special-case a script name that, perhaps with added .sh, matches an existing file. var surroundWithQuotes = false; var scriptCandidate = scriptArguments[0]; if (scriptCandidate.StartsWith("\"", StringComparison.Ordinal) && scriptCandidate.EndsWith("\"", StringComparison.Ordinal)) { // Strip surrounding quotes; they were required in project.json to keep the script name // together but confuse File.Exists() e.g. "My Script", lacking ./ prefix and .sh suffix. surroundWithQuotes = true; scriptCandidate = scriptCandidate.Substring(1, scriptCandidate.Length - 2); } if (!scriptCandidate.EndsWith(".sh", StringComparison.Ordinal)) { scriptCandidate = scriptCandidate + ".sh"; } if (File.Exists(Path.Combine(project.ProjectDirectory, scriptCandidate))) { // scriptCandidate may be a path relative to the project root. If so, likely will not be found // in the $PATH; add ./ to let bash know where to look. var prefix = Path.IsPathRooted(scriptCandidate) ? string.Empty : "./"; var quote = surroundWithQuotes ? "\"" : string.Empty; scriptArguments[0] = $"{ quote }{ prefix }{ scriptCandidate }{ quote }"; } // Always use /usr/bin/env bash -c in order to support redirection and so on; similar to Windows case. // Unlike Windows, must escape quotation marks within the newly-quoted string. scriptArguments = new[] { "/usr/bin/env", "bash", "-c", "\"" } .Concat(scriptArguments.Select(argument => argument.Replace("\"", "\\\""))) .Concat(new[] { "\"" }) .ToArray(); } var startInfo = new ProcessStartInfo { FileName = scriptArguments.FirstOrDefault(), Arguments = string.Join(" ", scriptArguments.Skip(1)), WorkingDirectory = project.ProjectDirectory, #if DNX451 UseShellExecute = false #endif }; var process = Process.Start(startInfo); process.WaitForExit(); if (process.ExitCode != 0) { ErrorMessage = string.Format(ErrorMessageTemplate, scriptName, process.ExitCode); ExitCode = process.ExitCode; return(false); } } return(true); }
public bool Execute(Runtime.Project project, string scriptName, Func <string, string> getVariable) { IEnumerable <string> scriptCommandLines; if (!project.Scripts.TryGetValue(scriptName, out scriptCommandLines)) { return(true); } foreach (var scriptCommandLine in scriptCommandLines) { var scriptArguments = CommandGrammar.Process( scriptCommandLine, GetScriptVariable(project, getVariable)); // Ensure the array won't be empty and the first element won't be null or empty string. scriptArguments = scriptArguments.Where(argument => !string.IsNullOrEmpty(argument)).ToArray(); if (scriptArguments.Length == 0) { continue; } if (!PlatformHelper.IsMono) { // Forward-slash is used in script blocked only. Replace them with back-slash to correctly // locate the script. The directory separator is platform-specific. scriptArguments[0] = scriptArguments[0].Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); // Command-lines on Windows are executed via "cmd /C" in order // to support batch files, &&, built-in commands like echo, etc. // ComSpec is Windows-specific, and contains the full path to cmd.exe var comSpec = Environment.GetEnvironmentVariable("ComSpec"); if (!string.IsNullOrEmpty(comSpec)) { scriptArguments = new[] { comSpec, "/C", "\"" } .Concat(scriptArguments) .Concat(new[] { "\"" }) .ToArray(); } } else { var scriptCandiate = scriptArguments[0] + ".sh"; if (File.Exists(scriptCandiate)) { scriptArguments[0] = scriptCandiate; scriptArguments = new[] { "/bin/bash" }.Concat(scriptArguments).ToArray(); } } var startInfo = new ProcessStartInfo { FileName = scriptArguments.FirstOrDefault(), Arguments = String.Join(" ", scriptArguments.Skip(1)), WorkingDirectory = project.ProjectDirectory, #if ASPNET50 UseShellExecute = false #endif }; var process = Process.Start(startInfo); process.WaitForExit(); if (process.ExitCode != 0) { ErrorMessage = string.Format(ErrorMessageTemplate, scriptName, process.ExitCode); ExitCode = process.ExitCode; return(false); } } return(true); }
public Task <int> Main(string[] args) { RuntimeOptions options; string[] programArgs; int exitCode; bool shouldExit = ParseArgs(args, out options, out programArgs, out exitCode); if (shouldExit) { return(Task.FromResult(exitCode)); } IFileWatcher watcher; if (options.WatchFiles) { watcher = new FileWatcher(ProjectResolver.ResolveRootDirectory(Path.GetFullPath(options.ApplicationBaseDirectory))); } else { watcher = NoopWatcher.Instance; } var host = new DefaultHost(options, _serviceProvider, _loadContextAccessor, watcher); if (host.Project == null) { return(Task.FromResult(-1)); } var lookupCommand = string.IsNullOrEmpty(options.ApplicationName) ? "run" : options.ApplicationName; string replacementCommand; if (host.Project.Commands.TryGetValue(lookupCommand, out replacementCommand)) { // preserveSurroundingQuotes: false to imitate a shell. Shells remove quotation marks before calling // Main methods. Here however we are invoking Main() without involving a shell. var replacementArgs = CommandGrammar .Process(replacementCommand, GetVariable, preserveSurroundingQuotes: false) .ToArray(); options.ApplicationName = replacementArgs.First(); programArgs = replacementArgs.Skip(1).Concat(programArgs).ToArray(); } if (string.IsNullOrEmpty(options.ApplicationName) || string.Equals(options.ApplicationName, "run", StringComparison.Ordinal)) { options.ApplicationName = host.Project.EntryPoint ?? host.Project.Name; } IDisposable disposable = null; try { disposable = host.AddLoaders(_container); return(ExecuteMain(host, options.ApplicationName, programArgs) .ContinueWith(async(t, state) => { ((IDisposable)state).Dispose(); return await t; }, disposable).Unwrap()); } catch { // If there's an error, dispose the host and throw if (disposable != null) { disposable.Dispose(); } throw; } }
public Task <int> Main(string[] args) { DefaultHostOptions options; string[] programArgs; var isShowingInformation = ParseArgs(args, out options, out programArgs); if (isShowingInformation) { return(Task.FromResult(0)); } var host = new DefaultHost(options, _serviceProvider); if (host.Project == null) { return(Task.FromResult(-1)); } var lookupCommand = string.IsNullOrEmpty(options.ApplicationName) ? "run" : options.ApplicationName; string replacementCommand; if (host.Project.Commands.TryGetValue(lookupCommand, out replacementCommand)) { var replacementArgs = CommandGrammar.Process( replacementCommand, GetVariable).ToArray(); options.ApplicationName = replacementArgs.First(); programArgs = replacementArgs.Skip(1).Concat(programArgs).ToArray(); } if (string.IsNullOrEmpty(options.ApplicationName) || string.Equals(options.ApplicationName, "run", StringComparison.Ordinal)) { if (string.IsNullOrEmpty(host.Project.Name)) { options.ApplicationName = Path.GetFileName(options.ApplicationBaseDirectory); } else { options.ApplicationName = host.Project.Name; } } IDisposable disposable = null; try { disposable = host.AddLoaders(_container); return(ExecuteMain(host, options.ApplicationName, programArgs) .ContinueWith(async(t, state) => { ((IDisposable)state).Dispose(); return await t; }, disposable).Unwrap()); } catch { // If there's an error, dispose the host and throw if (disposable != null) { disposable.Dispose(); } throw; } }
public static int Main(string[] args) { DefaultHostOptions options; string[] programArgs; int exitCode; DefaultHost host; try { bool shouldExit = ParseArgs(args, out options, out programArgs, out exitCode); if (shouldExit) { return(exitCode); } host = new DefaultHost(options, PlatformServices.Default.AssemblyLoadContextAccessor); if (host.Project == null) { return(1); } var lookupCommand = string.IsNullOrEmpty(options.ApplicationName) ? "run" : options.ApplicationName; string replacementCommand; if (host.Project.Commands.TryGetValue(lookupCommand, out replacementCommand)) { // preserveSurroundingQuotes: false to imitate a shell. Shells remove quotation marks before calling // Main methods. Here however we are invoking Main() without involving a shell. var replacementArgs = CommandGrammar .Process(replacementCommand, GetVariable, preserveSurroundingQuotes: false) .ToArray(); options.ApplicationName = replacementArgs.First(); programArgs = replacementArgs.Skip(1).Concat(programArgs).ToArray(); } if (string.IsNullOrEmpty(options.ApplicationName) || string.Equals(options.ApplicationName, "run", StringComparison.Ordinal)) { options.ApplicationName = host.Project.EntryPoint ?? host.Project.Name; } } catch (Exception ex) { throw SuppressStackTrace(ex); } IDisposable disposable = null; try { disposable = host.AddLoaders(PlatformServices.Default.AssemblyLoaderContainer); return(ExecuteMain(host, options.ApplicationName, programArgs) .ContinueWith((t, state) => { ((IDisposable)state).Dispose(); return t.GetAwaiter().GetResult(); }, disposable).GetAwaiter().GetResult()); } catch { // If there's an error, dispose the host and throw if (disposable != null) { disposable.Dispose(); } throw; } }
public Task<int> Main(string[] args) { ILogger log = null; try { ApplicationHostOptions options; string[] programArgs; int exitCode; bool shouldExit = ParseArgs(args, out options, out programArgs, out exitCode); if (shouldExit) { return Task.FromResult(exitCode); } string traceConfig = string.IsNullOrEmpty(options.Trace) ? Environment.GetEnvironmentVariable(EnvironmentNames.Trace) : options.Trace; // Initialize logging RuntimeLogging.Initialize(traceConfig, ConfigureLogging); // "Program" is a terrible name for a logger and this is the only logger in // this namespace :). log = RuntimeLogging.Logger("Microsoft.Framework.ApplicationHost"); log.LogInformation("Application Host Starting"); // Construct the necessary context for hosting the application var builder = RuntimeHostBuilder.ForProjectDirectory( options.ApplicationBaseDirectory, NuGetFramework.Parse(_environment.RuntimeFramework.FullName), _serviceProvider); // Configure assembly loading builder.Loaders.Add(new ProjectAssemblyLoaderFactory( new LibraryExporter( builder.TargetFramework, builder.PackagePathResolver))); builder.Loaders.Add(new PackageAssemblyLoaderFactory(builder.PackagePathResolver)); if (builder.Project == null) { // Failed to load the project Console.Error.WriteLine("Unable to find a project.json file."); return Task.FromResult(3); } // Boot the runtime var host = builder.Build(); // Get the project and print some information from it log.LogInformation($"Project: {host.Project.Name} ({host.Project.BaseDirectory})"); // Determine the command to be executed var command = string.IsNullOrEmpty(options.ApplicationName) ? "run" : options.ApplicationName; string replacementCommand; if (host.Project.Commands.TryGetValue(command, out replacementCommand)) { var replacementArgs = CommandGrammar.Process( replacementCommand, GetVariable).ToArray(); options.ApplicationName = replacementArgs.First(); programArgs = replacementArgs.Skip(1).Concat(programArgs).ToArray(); } if (string.IsNullOrEmpty(options.ApplicationName) || string.Equals(options.ApplicationName, "run", StringComparison.Ordinal)) { options.ApplicationName = host.Project.EntryPoint ?? host.Project.Name; } log.LogInformation($"Executing '{options.ApplicationName}' '{string.Join(" ", programArgs)}'"); return host.ExecuteApplication( _loaderContainer, _loadContextAccessor, options.ApplicationName, programArgs); } catch (Exception ex) { if (log != null) { log.LogError($"{ex.GetType().FullName} {ex.Message}", ex); } Console.Error.WriteLine($"Error loading project: {ex.Message}"); return Task.FromResult(1); } }