示例#1
0
 public BuildErrorInfo(string filePath, int lineNumber, string errorMessage, BuildInitiatorProcessViewModel initiatorProcess)
 {
     this.FilePath         = filePath;
     this.LineNumber       = lineNumber;
     this.ErrorMessage     = errorMessage;
     this.InitiatorProcess = initiatorProcess;
     this.OpenFileCommand  = new SimpleCommand(this.ExecuteOpenFile, this.CanExecuteOpenFile);
 }
        private InitiatorProcessQueryResult GetInitiatorProcessId(int id, out int initiatorId)
        {
            initiatorId = -1;

            Process currentProcess;

            try
            {
                currentProcess = Process.GetProcessById(id);
            }
            catch (ArgumentException)
            {
                // the fbuild process is already terminated
                return(InitiatorProcessQueryResult.Exited);
            }

            if (!BuildInitiatorProcessViewModel.GetIsProcessAccessible(id))
            {
                return(InitiatorProcessQueryResult.AccessDenied);
            }

            var startTime = currentProcess.StartTime;

            var parentId = WinAPIUtils.GetParentProcessId(id);

            if (!BuildInitiatorProcessViewModel.GetIsProcessAccessible(parentId))
            {
                return(InitiatorProcessQueryResult.AccessDenied);
            }

            try
            {
                var process = Process.GetProcessById(parentId);

                if (process.StartTime > startTime)
                {
                    // parent is already exited, this 'process' is just a fake one which
                    // reused parent's process id - try to find a wrapped initator
                    return(this.GetWrappedInitiatorProcessId(currentProcess, out initiatorId));
                }

                return(GetRootProcessId(id, startTime, out initiatorId));
            }
            catch (ArgumentException)
            {
                // parent not found - try to find a wrapped initator
                return(this.GetWrappedInitiatorProcessId(currentProcess, out initiatorId));
            }
        }
        private InitiatorProcessQueryResult GetWrappedInitiatorProcessId(Process process, out int initiatorId)
        {
            // FASTBuild uses a process wrapping mechanism to spawn a chain of (3) processes
            // in order to finally get a "standalone" process which is not a child/descendant
            // process of the build initiator by terminating the "intermediate" process so
            // the derivation chain is cut.

            // we use a tricky approach here to find the initiator, but it's best to output
            // the initiator process ID directly from FASTBuild

            // first, find other fbuild.exe processes
            var processes = Process.GetProcessesByName(process.ProcessName)
                            .Where(p => BuildInitiatorProcessViewModel.GetIsProcessAccessible(p.Id) && p.Id != process.Id);

            // and pick out the one which is started right before our fbuild process
            // this is hacky and maybe not reliable in a small chance
            var     minDeltaTime           = double.MaxValue;
            Process candidateSourceProcess = null;

            foreach (var p in processes)
            {
                var deltaTime = (process.StartTime - p.StartTime).TotalSeconds;
                if (deltaTime < 0)
                {
                    continue;
                }

                if (deltaTime < minDeltaTime)
                {
                    candidateSourceProcess = p;
                    minDeltaTime           = deltaTime;
                }
            }

            if (candidateSourceProcess == null)
            {
                initiatorId = -1;
                return(InitiatorProcessQueryResult.Exited);
            }

            return(this.GetRootProcessId(candidateSourceProcess.Id, candidateSourceProcess.StartTime, out initiatorId));
        }
        private InitiatorProcessQueryResult GetRootProcessId(int id, DateTime startTime, out int rootId)
        {
            while (true)
            {
                var parentId = WinAPIUtils.GetParentProcessId(id);
                if (parentId <= 0)
                {
                    // root reached
                    rootId = id;
                    return(InitiatorProcessQueryResult.Success);
                }

                if (!BuildInitiatorProcessViewModel.GetIsProcessAccessible(parentId))
                {
                    // parent not accessible (access deined etc.), which might be running under a system account (e.g. svchost)
                    // assume root reached
                    rootId = id;
                    return(InitiatorProcessQueryResult.Success);
                }

                Process parentProcess;

                try
                {
                    parentProcess = Process.GetProcessById(parentId);
                }
                catch (ArgumentException)
                {
                    // parent exited - root reached
                    rootId = id;
                    return(InitiatorProcessQueryResult.Success);
                }

                if (parentProcess.StartTime > startTime)
                {
                    // parent exited (and its id is reused by a newer process) - root reached
                    rootId = id;
                    return(InitiatorProcessQueryResult.Success);
                }

                if (parentProcess.ProcessName == "devenv")
                {
                    // special care for Visual Studio: stop traverse up even if there are more
                    // ancestors (e.g. Visual Studio started by a command line)
                    // todo: this is not really reliable, we need more evidence to prove this
                    // is a Visual Studio process
                    rootId = parentId;
                    return(InitiatorProcessQueryResult.Success);
                }

                if (parentProcess.ProcessName == "explorer")
                {
                    // most programs are started from explorer
                    // todo: this is not really reliable, we need more evidence to prove this
                    // is an explorer process
                    rootId = id;
                    return(InitiatorProcessQueryResult.Success);
                }

                id        = parentId;
                startTime = parentProcess.StartTime;
            }
        }