I would like to know how to find out in Powershell which path is running a process when it is shown in blank / empty in the command line of the Task Manager.
Any help to solve this issue wold be appreciated
Regards
CodePudding user response:
There are processes (e. g. "csrss.exe") that run in a higher security context (see protected processes) than the current PowerShell session, even if the PowerShell session runs as administrator. For such processes, PowerShell isn't able to query some informations like the process path using Get-Process
or the .NET Process
class, because PowerShell doesn't have the required permissions.
It depends on the kind of API being used though. Since Windows Vista there is a newer native API QueryFullProcessImageName()
that works when the process is opened using the flag PROCESS_QUERY_LIMITED_INFORMATION
. AFAIK this functionality isn't available as a .NET API, so you have to use P/Invoke:
Add-Type -TypeDefinition @'
using System;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Text;
public static class WinApiProcess {
[Flags]
public enum ProcessAccess
{
/// <summary>
/// Required to create a thread.
/// </summary>
CreateThread = 0x0002,
/// <summary>
///
/// </summary>
SetSessionId = 0x0004,
/// <summary>
/// Required to perform an operation on the address space of a process
/// </summary>
VmOperation = 0x0008,
/// <summary>
/// Required to read memory in a process using ReadProcessMemory.
/// </summary>
VmRead = 0x0010,
/// <summary>
/// Required to write to memory in a process using WriteProcessMemory.
/// </summary>
VmWrite = 0x0020,
/// <summary>
/// Required to duplicate a handle using DuplicateHandle.
/// </summary>
DupHandle = 0x0040,
/// <summary>
/// Required to create a process.
/// </summary>
CreateProcess = 0x0080,
/// <summary>
/// Required to set memory limits using SetProcessWorkingSetSize.
/// </summary>
SetQuota = 0x0100,
/// <summary>
/// Required to set certain information about a process, such as its priority class (see SetPriorityClass).
/// </summary>
SetInformation = 0x0200,
/// <summary>
/// Required to retrieve certain information about a process, such as its token, exit code, and priority class (see OpenProcessToken).
/// </summary>
QueryInformation = 0x0400,
/// <summary>
/// Required to suspend or resume a process.
/// </summary>
SuspendResume = 0x0800,
/// <summary>
/// Required to retrieve certain information about a process (see GetExitCodeProcess, GetPriorityClass, IsProcessInJob, QueryFullProcessImageName).
/// A handle that has the PROCESS_QUERY_INFORMATION access right is automatically granted PROCESS_QUERY_LIMITED_INFORMATION.
/// </summary>
QueryLimitedInformation = 0x1000,
/// <summary>
/// Required to wait for the process to terminate using the wait functions.
/// </summary>
Synchronize = 0x100000,
/// <summary>
/// Required to delete the object.
/// </summary>
Delete = 0x00010000,
/// <summary>
/// Required to read information in the security descriptor for the object, not including the information in the SACL.
/// To read or write the SACL, you must request the ACCESS_SYSTEM_SECURITY access right. For more information, see SACL Access Right.
/// </summary>
ReadControl = 0x00020000,
/// <summary>
/// Required to modify the DACL in the security descriptor for the object.
/// </summary>
WriteDac = 0x00040000,
/// <summary>
/// Required to change the owner in the security descriptor for the object.
/// </summary>
WriteOwner = 0x00080000,
StandardRightsRequired = 0x000F0000,
/// <summary>
/// All possible access rights for a process object.
/// </summary>
AllAccess = StandardRightsRequired | Synchronize | 0xFFFF
}
[DllImport("kernel32.dll")]
private static extern bool QueryFullProcessImageName(IntPtr hprocess, int dwFlags,
StringBuilder lpExeName, out int size);
[DllImport("kernel32.dll")]
private static extern IntPtr OpenProcess(ProcessAccess dwDesiredAccess,
bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr hHandle);
public static string QueryProcessPath(int ProcessId)
{
var buffer = new StringBuilder(1024);
IntPtr hprocess = OpenProcess(ProcessAccess.QueryLimitedInformation, false, ProcessId);
if (hprocess != IntPtr.Zero)
{
try
{
int size = buffer.Capacity;
if (QueryFullProcessImageName(hprocess, 0, buffer, out size))
{
return buffer.ToString();
}
}
finally
{
CloseHandle(hprocess);
}
}
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
'@
Usage example:
[WinApiProcess]::QueryProcessPath( (Get-Process csrss)[0].Id )
This works for me when PowerShell runs elevated ("as administrator").
CodePudding user response:
Finally works , the problem was that to show all the info, I needed to use a user with elevated privileges or DC admin. Then you can see the full info
Many thanks for your help