Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Slow module load caused by inefficient PSUtils.GetParentProcess #2578

Copy link
Copy link
@powercode

Description

@powercode
Issue body actions

The current implementation for getting the parent id of the current process if extremely slow:
The parent Id is not even cached, but is retrieved over and over again. On several systems I see module load times of 5+ seconds, where almost all of the time is spent blocking on the wmi call, waiting for WmiPrvSe to enumerate all processes.
The Id of the process that created us will not change, so cache it and/or use a more efficient method of getting the parent id.

The check for process start time would still have to be done (not in the example).

/// suggested alternative (about 100 times faster)
public static class ProcessInfoUtil
{
	public static System.Diagnostics.Process GetParentProcess() { return ParentProcessId == 0 ? null : System.Diagnostics.Process.GetProcessById(ParentProcessId); }

	public static readonly int ParentProcessId = GetParentProcessId();

	private static int GetParentProcessId()
	{
		var pi = new PROCESS_BASIC_INFORMATION();
		int actual;
		if (0 == NativeMethods.NtQueryInformationProcess(new IntPtr(-1), 0/*processbasicInformation*/, ref pi, pi.Size, out actual))
		{
			return (int)pi.InheritedFromUniqueProcessId;
		}
		else 
		{
			return 0;
		}
	}

	[StructLayout(LayoutKind.Sequential, Pack = 1)]
	private struct PROCESS_BASIC_INFORMATION
	{
		public IntPtr ExitStatus;
		public IntPtr PebBaseAddress;
		public IntPtr AffinityMask;
		public IntPtr BasePriority;
		public UIntPtr UniqueProcessId;
		public IntPtr InheritedFromUniqueProcessId;

		public int Size { get { return Marshal.SizeOf(typeof(PROCESS_BASIC_INFORMATION));}}
	}

	static class NativeMethods
	{
	[DllImport("NtDll", SetLastError=true)]
	public static extern int NtQueryInformationProcess(IntPtr ProcessHandle, int processInformationClass, ref PROCESS_BASIC_INFORMATION ProcessInformation, int processInformationLength, out int returnLength);
	}
}
/// this is the current implementation
 string wmiQuery = String.Format(CultureInfo.CurrentCulture,
                                            "Select * From Win32_Process Where Handle='{0}'",
                                            current.Id);

            using (CimSession cimSession = CimSession.Create(null))
            {
                IEnumerable<CimInstance> processCollection =
                    cimSession.QueryInstances("root/cimv2", "WQL", wmiQuery);

                int parentPid =
                    processCollection.Select(
                        cimProcess =>
                        Convert.ToInt32(cimProcess.CimInstanceProperties["ParentProcessId"].Value,
                                        CultureInfo.CurrentCulture)).FirstOrDefault();

                if (parentPid == 0)
                    return null;
...
Reactions are currently unavailable

Metadata

Metadata

Assignees

Labels

Resolution-FixedThe issue is fixed.The issue is fixed.WG-Enginecore PowerShell engine, interpreter, and runtimecore PowerShell engine, interpreter, and runtime

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    Morty Proxy This is a proxified and sanitized view of the page, visit original site.