/// <summary> /// Creates a new MSBuild process /// </summary> private int LaunchNode(string msbuildLocation, string commandLineArgs) { // Should always have been set already. ErrorUtilities.VerifyThrowInternalLength(msbuildLocation, "msbuildLocation"); if (!FileSystems.Default.FileExists(msbuildLocation)) { throw new BuildAbortedException(ResourceUtilities.FormatResourceStringStripCodeAndKeyword("CouldNotFindMSBuildExe", msbuildLocation)); } // Repeat the executable name as the first token of the command line because the command line // parser logic expects it and will otherwise skip the first argument commandLineArgs = msbuildLocation + " " + commandLineArgs; BackendNativeMethods.STARTUP_INFO startInfo = new BackendNativeMethods.STARTUP_INFO(); startInfo.cb = Marshal.SizeOf <BackendNativeMethods.STARTUP_INFO>(); // Null out the process handles so that the parent process does not wait for the child process // to exit before it can exit. uint creationFlags = 0; if (Traits.Instance.EscapeHatches.EnsureStdOutForChildNodesIsPrimaryStdout) { creationFlags = BackendNativeMethods.NORMALPRIORITYCLASS; } if (String.IsNullOrEmpty(Environment.GetEnvironmentVariable("MSBUILDNODEWINDOW"))) { if (!Traits.Instance.EscapeHatches.EnsureStdOutForChildNodesIsPrimaryStdout) { // Redirect the streams of worker nodes so that this MSBuild.exe's // parent doesn't wait on idle worker nodes to close streams // after the build is complete. startInfo.hStdError = BackendNativeMethods.InvalidHandle; startInfo.hStdInput = BackendNativeMethods.InvalidHandle; startInfo.hStdOutput = BackendNativeMethods.InvalidHandle; startInfo.dwFlags = BackendNativeMethods.STARTFUSESTDHANDLES; creationFlags = creationFlags | BackendNativeMethods.CREATENOWINDOW; } } else { creationFlags = creationFlags | BackendNativeMethods.CREATE_NEW_CONSOLE; } BackendNativeMethods.SECURITY_ATTRIBUTES processSecurityAttributes = new BackendNativeMethods.SECURITY_ATTRIBUTES(); BackendNativeMethods.SECURITY_ATTRIBUTES threadSecurityAttributes = new BackendNativeMethods.SECURITY_ATTRIBUTES(); processSecurityAttributes.nLength = Marshal.SizeOf <BackendNativeMethods.SECURITY_ATTRIBUTES>(); threadSecurityAttributes.nLength = Marshal.SizeOf <BackendNativeMethods.SECURITY_ATTRIBUTES>(); CommunicationsUtilities.Trace("Launching node from {0}", msbuildLocation); string exeName = msbuildLocation; #if RUNTIME_TYPE_NETCORE // Run the child process with the same host as the currently-running process. exeName = GetCurrentHost(); commandLineArgs = "\"" + msbuildLocation + "\" " + commandLineArgs; #endif if (!NativeMethodsShared.IsWindows) { ProcessStartInfo processStartInfo = new ProcessStartInfo(); processStartInfo.FileName = exeName; processStartInfo.Arguments = commandLineArgs; if (!Traits.Instance.EscapeHatches.EnsureStdOutForChildNodesIsPrimaryStdout) { // Redirect the streams of worker nodes so that this MSBuild.exe's // parent doesn't wait on idle worker nodes to close streams // after the build is complete. processStartInfo.RedirectStandardInput = true; processStartInfo.RedirectStandardOutput = true; processStartInfo.RedirectStandardError = true; processStartInfo.CreateNoWindow = (creationFlags | BackendNativeMethods.CREATENOWINDOW) == BackendNativeMethods.CREATENOWINDOW; } processStartInfo.UseShellExecute = false; Process process; try { process = Process.Start(processStartInfo); } catch (Exception ex) { CommunicationsUtilities.Trace ( "Failed to launch node from {0}. CommandLine: {1}" + Environment.NewLine + "{2}", msbuildLocation, commandLineArgs, ex.ToString() ); throw new NodeFailedToLaunchException(ex); } CommunicationsUtilities.Trace("Successfully launched msbuild.exe node with PID {0}", process.Id); return(process.Id); } else { #if RUNTIME_TYPE_NETCORE if (NativeMethodsShared.IsWindows) { // Repeat the executable name in the args to suit CreateProcess commandLineArgs = "\"" + exeName + "\" " + commandLineArgs; } #endif BackendNativeMethods.PROCESS_INFORMATION processInfo = new BackendNativeMethods.PROCESS_INFORMATION(); bool result = BackendNativeMethods.CreateProcess ( exeName, commandLineArgs, ref processSecurityAttributes, ref threadSecurityAttributes, #if FEATURE_NAMED_PIPES_FULL_DUPLEX false, #else true, // Inherit handles for the anonymous pipes for IPC #endif creationFlags, BackendNativeMethods.NullPtr, null, ref startInfo, out processInfo ); if (!result) { // Creating an instance of this exception calls GetLastWin32Error and also converts it to a user-friendly string. System.ComponentModel.Win32Exception e = new System.ComponentModel.Win32Exception(); CommunicationsUtilities.Trace ( "Failed to launch node from {0}. System32 Error code {1}. Description {2}. CommandLine: {2}", msbuildLocation, e.NativeErrorCode.ToString(CultureInfo.InvariantCulture), e.Message, commandLineArgs ); throw new NodeFailedToLaunchException(e.NativeErrorCode.ToString(CultureInfo.InvariantCulture), e.Message); } int childProcessId = processInfo.dwProcessId; if (processInfo.hProcess != IntPtr.Zero && processInfo.hProcess != NativeMethods.InvalidHandle) { NativeMethodsShared.CloseHandle(processInfo.hProcess); } if (processInfo.hThread != IntPtr.Zero && processInfo.hThread != NativeMethods.InvalidHandle) { NativeMethodsShared.CloseHandle(processInfo.hThread); } CommunicationsUtilities.Trace("Successfully launched msbuild.exe node with PID {0}", childProcessId); return(childProcessId); } }
/// <summary> /// Creates a new MSBuild process /// </summary> private int LaunchNode(string msbuildLocation, string commandLineArgs) { // Should always have been set already. ErrorUtilities.VerifyThrowInternalLength(msbuildLocation, "msbuildLocation"); if (!File.Exists(msbuildLocation)) { throw new BuildAbortedException(ResourceUtilities.FormatResourceString("CouldNotFindMSBuildExe", msbuildLocation)); } // Repeat the executable name as the first token of the command line because the command line // parser logic expects it and will otherwise skip the first argument commandLineArgs = msbuildLocation + " " + commandLineArgs; BackendNativeMethods.STARTUP_INFO startInfo = new BackendNativeMethods.STARTUP_INFO(); startInfo.cb = Marshal.SizeOf<BackendNativeMethods.STARTUP_INFO>(); // Null out the process handles so that the parent process does not wait for the child process // to exit before it can exit. uint creationFlags = BackendNativeMethods.NORMALPRIORITYCLASS; startInfo.dwFlags = BackendNativeMethods.STARTFUSESTDHANDLES; if (String.IsNullOrEmpty(Environment.GetEnvironmentVariable("MSBUILDNODEWINDOW"))) { startInfo.hStdError = BackendNativeMethods.InvalidHandle; startInfo.hStdInput = BackendNativeMethods.InvalidHandle; startInfo.hStdOutput = BackendNativeMethods.InvalidHandle; creationFlags = creationFlags | BackendNativeMethods.CREATENOWINDOW; } else { creationFlags = creationFlags | BackendNativeMethods.CREATE_NEW_CONSOLE; } BackendNativeMethods.SECURITY_ATTRIBUTES processSecurityAttributes = new BackendNativeMethods.SECURITY_ATTRIBUTES(); BackendNativeMethods.SECURITY_ATTRIBUTES threadSecurityAttributes = new BackendNativeMethods.SECURITY_ATTRIBUTES(); processSecurityAttributes.nLength = Marshal.SizeOf< BackendNativeMethods.SECURITY_ATTRIBUTES>(); threadSecurityAttributes.nLength = Marshal.SizeOf<BackendNativeMethods.SECURITY_ATTRIBUTES>(); BackendNativeMethods.PROCESS_INFORMATION processInfo = new BackendNativeMethods.PROCESS_INFORMATION(); string appName = msbuildLocation; CommunicationsUtilities.Trace("Launching node from {0}", msbuildLocation); bool result = BackendNativeMethods.CreateProcess ( msbuildLocation, commandLineArgs, ref processSecurityAttributes, ref threadSecurityAttributes, false, creationFlags, BackendNativeMethods.NullPtr, null, ref startInfo, out processInfo ); if (!result) { // Creating an instance of this exception calls GetLastWin32Error and also converts it to a user-friendly string. System.ComponentModel.Win32Exception e = new System.ComponentModel.Win32Exception(); CommunicationsUtilities.Trace ( "Failed to launch node from {0}. System32 Error code {1}. Description {2}. CommandLine: {2}", msbuildLocation, e.NativeErrorCode.ToString(CultureInfo.InvariantCulture), e.Message, commandLineArgs ); throw new NodeFailedToLaunchException(e.NativeErrorCode.ToString(CultureInfo.InvariantCulture), e.Message); } CommunicationsUtilities.Trace("Successfully launched msbuild.exe node with PID {0}", processInfo.dwProcessId); return processInfo.dwProcessId; }
public void InProcTrackingStartProcessFindStrNullCommandLine() { Console.WriteLine("Test: InProcTrackingStartProcessFindStrNullCommandLine"); try { FileTracker.StartTrackingContext(Path.GetFullPath("."), "InProcTrackingStartProcessFindStrIn"); BackEndNativeMethods.STARTUP_INFO startInfo = new BackEndNativeMethods.STARTUP_INFO(); startInfo.cb = Marshal.SizeOf<BackEndNativeMethods.STARTUP_INFO>(); uint dwCreationFlags = BackEndNativeMethods.NORMALPRIORITYCLASS; startInfo.hStdError = BackEndNativeMethods.InvalidHandle; startInfo.hStdInput = BackEndNativeMethods.InvalidHandle; startInfo.hStdOutput = BackEndNativeMethods.InvalidHandle; startInfo.dwFlags = BackEndNativeMethods.STARTFUSESTDHANDLES; dwCreationFlags = dwCreationFlags | BackEndNativeMethods.CREATENOWINDOW; BackEndNativeMethods.SECURITY_ATTRIBUTES pSec = new BackEndNativeMethods.SECURITY_ATTRIBUTES(); BackEndNativeMethods.SECURITY_ATTRIBUTES tSec = new BackEndNativeMethods.SECURITY_ATTRIBUTES(); pSec.nLength = Marshal.SizeOf<BackEndNativeMethods.SECURITY_ATTRIBUTES>(); tSec.nLength = Marshal.SizeOf<BackEndNativeMethods.SECURITY_ATTRIBUTES>(); BackEndNativeMethods.PROCESS_INFORMATION pInfo = new BackEndNativeMethods.PROCESS_INFORMATION(); string appName = NativeMethodsShared.FindOnPath("findstr.exe"); string cmdLine = null; bool created = BackEndNativeMethods.CreateProcess(appName, cmdLine, ref pSec, ref tSec, false, dwCreationFlags, BackEndNativeMethods.NullPtr, null, ref startInfo, out pInfo); // We should have correctly started the process even though the command-line was null Assert.True(created); FileTracker.WriteContextTLogs(Path.GetFullPath("."), "inlinefind"); FileTracker.EndTrackingContext(); } finally { FileTracker.StopTrackingAndCleanup(); } File.Delete("inlinefind.read.1.tlog"); }
private void LaunchDuplicateToolsAndVerifyTlogExistsForEach(string tlogPath, IList<Tuple<string, IList<Tuple<string, string, int>>>> contextSpecifications, IList<Tuple<string, int>> tlogPatterns, bool createTestDirectory) { try { if (createTestDirectory) { if (FileUtilities.DirectoryExistsNoThrow(tlogPath)) { FileUtilities.DeleteDirectoryNoThrow(tlogPath, true); } Directory.CreateDirectory(tlogPath); } BackEndNativeMethods.STARTUP_INFO startInfo = new BackEndNativeMethods.STARTUP_INFO(); startInfo.cb = Marshal.SizeOf<BackEndNativeMethods.STARTUP_INFO>(); uint dwCreationFlags = BackEndNativeMethods.NORMALPRIORITYCLASS; startInfo.hStdError = BackEndNativeMethods.InvalidHandle; startInfo.hStdInput = BackEndNativeMethods.InvalidHandle; startInfo.hStdOutput = BackEndNativeMethods.InvalidHandle; startInfo.dwFlags = BackEndNativeMethods.STARTFUSESTDHANDLES; dwCreationFlags = dwCreationFlags | BackEndNativeMethods.CREATENOWINDOW; BackEndNativeMethods.SECURITY_ATTRIBUTES pSec = new BackEndNativeMethods.SECURITY_ATTRIBUTES(); BackEndNativeMethods.SECURITY_ATTRIBUTES tSec = new BackEndNativeMethods.SECURITY_ATTRIBUTES(); pSec.nLength = Marshal.SizeOf<BackEndNativeMethods.SECURITY_ATTRIBUTES>(); tSec.nLength = Marshal.SizeOf<BackEndNativeMethods.SECURITY_ATTRIBUTES>(); BackEndNativeMethods.PROCESS_INFORMATION pInfo = new BackEndNativeMethods.PROCESS_INFORMATION(); foreach (var specification in contextSpecifications) { // Item1: FileTracker context name // Item2: Tuple <string, string, int> as described below FileTracker.StartTrackingContext(tlogPath, specification.Item1); foreach (var processSpecification in specification.Item2) { // Item1: appname // Item2: command line // Item3: number of times to launch for (int i = 0; i < processSpecification.Item3; i++) { BackEndNativeMethods.CreateProcess(processSpecification.Item1, processSpecification.Item2, ref pSec, ref tSec, false, dwCreationFlags, BackEndNativeMethods.NullPtr, null, ref startInfo, out pInfo); } } FileTracker.WriteContextTLogs(tlogPath, specification.Item1); FileTracker.StopTrackingAndCleanup(); } int tlogCount = 0; foreach (Tuple<string, int> pattern in tlogPatterns) { tlogCount += pattern.Item2; } // make sure the disk write gets time for NTFS to recognize its existence. Estimate time needed to sleep based // roughly on the number of tlogs that we're looking for (presumably roughly proportional to the number of tlogs // being written. Thread.Sleep(Math.Max(200, 250 * tlogCount)); // Item1: The pattern the tlog name should follow // Item2: The number of tlogs following that pattern that should exist in the output directory foreach (Tuple<string, int> pattern in tlogPatterns) { string[] tlogNames = Directory.GetFiles(tlogPath, pattern.Item1, SearchOption.TopDirectoryOnly); Assert.Equal(pattern.Item2, tlogNames.Length); } } finally { if (FileUtilities.DirectoryExistsNoThrow(tlogPath)) { FileUtilities.DeleteDirectoryNoThrow(tlogPath, true); } } }
/// <summary> /// Creates a new MSBuild process /// </summary> private int LaunchNode(string msbuildLocation, string commandLineArgs) { // Should always have been set already. ErrorUtilities.VerifyThrowInternalLength(msbuildLocation, "msbuildLocation"); if (!File.Exists(msbuildLocation)) { throw new BuildAbortedException(ResourceUtilities.FormatResourceString("CouldNotFindMSBuildExe", msbuildLocation)); } // Repeat the executable name as the first token of the command line because the command line // parser logic expects it and will otherwise skip the first argument commandLineArgs = msbuildLocation + " " + commandLineArgs; BackendNativeMethods.STARTUP_INFO startInfo = new BackendNativeMethods.STARTUP_INFO(); startInfo.cb = Marshal.SizeOf <BackendNativeMethods.STARTUP_INFO>(); // Null out the process handles so that the parent process does not wait for the child process // to exit before it can exit. uint creationFlags = BackendNativeMethods.NORMALPRIORITYCLASS; startInfo.dwFlags = BackendNativeMethods.STARTFUSESTDHANDLES; if (String.IsNullOrEmpty(Environment.GetEnvironmentVariable("MSBUILDNODEWINDOW"))) { startInfo.hStdError = BackendNativeMethods.InvalidHandle; startInfo.hStdInput = BackendNativeMethods.InvalidHandle; startInfo.hStdOutput = BackendNativeMethods.InvalidHandle; creationFlags = creationFlags | BackendNativeMethods.CREATENOWINDOW; } else { creationFlags = creationFlags | BackendNativeMethods.CREATE_NEW_CONSOLE; } BackendNativeMethods.SECURITY_ATTRIBUTES processSecurityAttributes = new BackendNativeMethods.SECURITY_ATTRIBUTES(); BackendNativeMethods.SECURITY_ATTRIBUTES threadSecurityAttributes = new BackendNativeMethods.SECURITY_ATTRIBUTES(); processSecurityAttributes.nLength = Marshal.SizeOf <BackendNativeMethods.SECURITY_ATTRIBUTES>(); threadSecurityAttributes.nLength = Marshal.SizeOf <BackendNativeMethods.SECURITY_ATTRIBUTES>(); CommunicationsUtilities.Trace("Launching node from {0}", msbuildLocation); #if RUNTIME_TYPE_NETCORE // Run the child process with the same host as the currently-running process. string pathToHost; using (Process currentProcess = Process.GetCurrentProcess()) pathToHost = currentProcess.MainModule.FileName; commandLineArgs = "\"" + msbuildLocation + "\" " + commandLineArgs; ProcessStartInfo processStartInfo = new ProcessStartInfo(); processStartInfo.FileName = pathToHost; processStartInfo.Arguments = commandLineArgs; processStartInfo.CreateNoWindow = (creationFlags | BackendNativeMethods.CREATENOWINDOW) == BackendNativeMethods.CREATENOWINDOW; processStartInfo.UseShellExecute = false; Process process; try { process = Process.Start(processStartInfo); } catch (Exception ex) { CommunicationsUtilities.Trace ( "Failed to launch node from {0}. CommandLine: {1}" + Environment.NewLine + "{2}", msbuildLocation, commandLineArgs, ex.ToString() ); throw new NodeFailedToLaunchException(ex); } CommunicationsUtilities.Trace("Successfully launched msbuild.exe node with PID {0}", process.Id); return(process.Id); #else BackendNativeMethods.PROCESS_INFORMATION processInfo = new BackendNativeMethods.PROCESS_INFORMATION(); string exeName = msbuildLocation; bool result = BackendNativeMethods.CreateProcess ( exeName, commandLineArgs, ref processSecurityAttributes, ref threadSecurityAttributes, false, creationFlags, BackendNativeMethods.NullPtr, null, ref startInfo, out processInfo ); if (!result) { // Creating an instance of this exception calls GetLastWin32Error and also converts it to a user-friendly string. System.ComponentModel.Win32Exception e = new System.ComponentModel.Win32Exception(); CommunicationsUtilities.Trace ( "Failed to launch node from {0}. System32 Error code {1}. Description {2}. CommandLine: {2}", msbuildLocation, e.NativeErrorCode.ToString(CultureInfo.InvariantCulture), e.Message, commandLineArgs ); throw new NodeFailedToLaunchException(e.NativeErrorCode.ToString(CultureInfo.InvariantCulture), e.Message); } CommunicationsUtilities.Trace("Successfully launched msbuild.exe node with PID {0}", processInfo.dwProcessId); return(processInfo.dwProcessId); #endif }