Home > database >  Get-Process by different info
Get-Process by different info

Time:06-18

I am trying to get a process by one of a number of different pieces of data. In this example the process is Autodesk's DesktopConnector. Sometimes Autodesk provides the name you see in Task Manager, Autodesk Desktop Connector. Sometimes they provide the actual name of the process, DesktopConnector.Applications.Tray. And sometimes they provide the executable, desktopconnector.applications.tray.exe. So I want a way to return a process object based on any of those, which I can then work with, for example Stopping the process because Autodesk is too stupid to produce installers or uninstaller that stop the process themselves, and so their update installers and uninstaller fail unless you kill the process yourself. Sigh. Anyway... This is what I have, to verify I get the object I want back and to get a sense of how much time each approach takes as well as how much time it takes to fail to find anything

$strings = @('DesktopConnector.Applications.Tray','Autodesk Desktop Connector','desktopconnector.applications.tray.exe', 'Nope')

foreach ($string in $strings) {
    (Measure-Command {
        if (($process = (Get-Process -Name:$string -errorAction:SilentlyContinue)) -or 
            ($process = ((Get-Process).Where({$PSItem.MainModule.FileVersionInfo.FileDescription -eq $string})) -or
            ($process = ((Get-Process).Where({$PSItem.Path.EndsWith($string)}))
            ))) {
            Write-Host "$string $($process.id) " -NoNewLine
        }
    }).TotalSeconds
} 

When I provide the actual process name (first condition) I get back a [System.Diagnostics.Process] as expected. When I provide the File Description you see in TaskManager (second condition) I get back a useless [Bool], and when I provide the executable (third condition) I get an error because $PSItem.Path is null. So, what am I missing in the latter two conditions that is keeping me from getting an actual process back? I know it's related to using .Where(), which returns a PSObject that I need to dig into, at least in the second condition. The third condition it's also the predicate of the .Where() that I am screwing up. But I am just at a loss for a solution in either case.

Per Theo's comment, this is what I landed on that seems to address performance, readability and, you know, actual function.

 foreach ($string in $strings) {
    (Measure-Command {
        if (($process = (Get-Process -Name:$string -errorAction:SilentlyContinue)) -or 
                        (Get-Process | Where-Object {$_.MainModule.FileVersionInfo.FileDescription -eq $string -or
                                                     $_.Path -like "*$string" })) {
            Write-Host "$string $($process.id) " -NoNewLine
        }
    }).TotalSeconds
} 

CodePudding user response:

I believe you use Get-Process too many times, where you can only do that once per iteration

Try

$strings = 'DesktopConnector.Applications.Tray','Autodesk Desktop Connector','desktopconnector.applications.tray.exe', 'Nope'

foreach ($string in $strings) {
    (Measure-Command {
        $process = Get-Process | 
                   Where-Object { $_.Name -eq $string -or
                                  $_.MainModule.FileVersionInfo.FileDescription -eq $string -or
                                  $_.Path -like "*$string" }
        if ($process) { Write-Host "$string $($process.id) " -NoNewLine }
    }).TotalSeconds
}

I'm also using $_.Path -like "*$string" instead of the EndsWith() string method, because the latter is case-sensitive while -like is not

  • Related