/// <summary> /// Parses the header of the <c>ps</c> command. /// </summary> /// <param name="header"> /// A <see cref="string"/> that contains the <c>ps</c> command output header. /// </param> /// <returns> /// A <see cref="AndroidProcessHeader"/> that represents the header information. /// </returns> public static AndroidProcessHeader ParseHeader(string header) { // Sample input: // USER PID PPID VSIZE RSS WCHAN PC NAME // system 479 138 446284 21100 ffffffff b765ffe6 S com.microsoft.xde.donatelloservice // OR: // PID USER VSZ STAT COMMAND // 1 root 340 S /init AndroidProcessHeader value = new AndroidProcessHeader(); List<string> parts = new List<string>(header.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries)); value.UserIndex = parts.IndexOf("USER"); value.ProcessIdIndex = parts.IndexOf("PID"); value.ParentProcessIdIndex = parts.IndexOf("PPID"); value.VirtualSizeIndex = IndexOf(parts, "VSIZE", "VSZ"); value.ResidentSetSizeIndex = parts.IndexOf("RSS"); value.WChanIndex = parts.IndexOf("WCHAN"); value.PcIndex = parts.IndexOf("PC"); value.StateIndex = value.PcIndex != -1 ? value.PcIndex + 1 : parts.IndexOf("STAT"); value.NameIndex = IndexOf(parts, "NAME", "COMMAND"); // If the pcIndex is present, we should also increase the name index by one, because the // state field comes in the middle yet has no header if (value.PcIndex != -1) { value.NameIndex++; } return value; }
/// <summary> /// Parses an line of output of the <c>ps</c> command into a <see cref="AndroidProcess"/> /// object. /// </summary> /// <param name="line"> /// The line to parse. /// </param> /// <param name="header"> /// THe header information, that defines how the <paramref name="line"/> is structured. /// </param> /// <returns> /// A <see cref="AndroidProcess"/> that represents the process. /// </returns> public static AndroidProcess Parse(string line, AndroidProcessHeader header) { if (line == null) { throw new ArgumentNullException(nameof(line)); } // Sample input: // USER PID PPID VSIZE RSS WCHAN PC NAME // system 479 138 446284 21100 ffffffff b765ffe6 S com.microsoft.xde.donatelloservice // OR: // PID USER VSZ STAT COMMAND // 1 root 340 S /init string[] parts = line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); AndroidProcess value = new AndroidProcess() { User = header.UserIndex != -1 ? parts[header.UserIndex] : null, ProcessId = header.ProcessIdIndex != -1 ? int.Parse(parts[header.ProcessIdIndex]) : -1, ParentProcessId = header.ParentProcessIdIndex != -1 ? int.Parse(parts[header.ParentProcessIdIndex]) : -1, VirtualSize = header.VirtualSizeIndex != -1 ? int.Parse(parts[header.VirtualSizeIndex]) : -1, ResidentSetSize = header.ResidentSetSizeIndex != -1 ? int.Parse(parts[header.ResidentSetSizeIndex]) : -1, WChan = header.WChanIndex != -1 ? uint.Parse(parts[header.WChanIndex], NumberStyles.HexNumber) : uint.MaxValue, Pc = header.PcIndex != -1 ? uint.Parse(parts[header.PcIndex], NumberStyles.HexNumber) : uint.MaxValue, State = header.StateIndex != -1 ? (AndroidProcessState)Enum.Parse(typeof(AndroidProcessState), parts[header.StateIndex].Substring(0, 1)) : AndroidProcessState.Unknown, Name = header.NameIndex != -1 ? parts[header.NameIndex] : null }; // If the name starts with [, remove the starting & trailing ] characters if (value.Name != null && value.Name.StartsWith("[")) { value.Name = value.Name.Substring(1, value.Name.Length - 2); } return value; }