/// <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);
            }
        }
예제 #2
0
        /// <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;
        }
예제 #3
0
        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");
        }
예제 #4
0
        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);
                }
            }
        }
예제 #5
0
        /// <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
        }