Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Powershell 查找控制任务栏的explorer.exe?_Powershell_Windows 10 - Fatal编程技术网

Powershell 查找控制任务栏的explorer.exe?

Powershell 查找控制任务栏的explorer.exe?,powershell,windows-10,Powershell,Windows 10,我倾向于一次开几周电脑。我唯一的问题是,任务栏在几天后会脱落。通常,这采取的形式是不在“开始”菜单中呈现图标。它甚至可以不渲染“开始”菜单中的任何内容。在Windows 10中,重新启动资源管理器进程可以很好地解决此问题 与其手动尝试找出哪个explorer.exe任务正在处理任务栏并重新启动它,我想编写一个powershell脚本来实现这一点 如何通过编程确定当前负责任务栏的explorer.exe实例?当explorer.exe运行时,如果任务栏未运行,则该explorer.exe实例将为该

我倾向于一次开几周电脑。我唯一的问题是,任务栏在几天后会脱落。通常,这采取的形式是不在“开始”菜单中呈现图标。它甚至可以不渲染“开始”菜单中的任何内容。在Windows 10中,重新启动资源管理器进程可以很好地解决此问题

与其手动尝试找出哪个
explorer.exe
任务正在处理任务栏并重新启动它,我想编写一个powershell脚本来实现这一点


如何通过编程确定当前负责任务栏的
explorer.exe
实例?

explorer.exe
运行时,如果任务栏未运行,则该
explorer.exe
实例将为该用户运行任务栏。然后,合乎逻辑地得出结论,运行任务栏的最有可能的进程是最旧的
explorer.exe
进程:

$CurrentProcessUser = Get-Process -PID $PID -IncludeUserName |
    Select-Object -ExpandProperty UserName

$TaskBarProcess = Get-Process -Name explorer -IncludeUserName | 
    Where-Object UserName -eq $CurrentProcessUser | 
    Sort-Object -Property StartTime | 
    Select-Object -First 1

这有保证吗?可能不会。可能有一些情况并非如此。但它通常是正确的。

注意,文件夹选项“在单独进程中启动文件夹窗口”似乎是导致生成多个资源管理器进程的设置。如果未设置,则看起来只有一个Explorer.exe进程

在我看来,每个衍生的资源管理器窗口都有一个包含“/factory”参数的命令行,而“拥有”任务栏的进程没有:

Get-WmiObject -Class Win32_process -Filter "name='Explorer.exe'" |
    Select-Object ProcessID,CommandLine 

没有保证,但对你来说,这是一条探索之路。

一条略为简洁的替代:

注:同样,不保证: 该方法依赖于具有任务栏的文件资源管理器实例的
.MainWindowTitle
属性,该属性反映了任务栏的窗口标题,与实际文件资源管理器窗口的标题不同,该窗口标题恰好为空-至少在windows 10和windows 7上出现了这种情况(尚未尝试其他窗口):

如果其他用户可以登录,并且您必须将检查的进程限制为当前用户的进程,请从提升控制台运行以下操作:

Get-Process -IncludeUserName explorer |
  ? MainWindowTitle -eq '' |
    ? UserName -eq (whoami)

稳健但更复杂的方法

Get-Process -IncludeUserName explorer |
  ? MainWindowTitle -eq '' |
    ? UserName -eq (whoami)
使用
addmember-MemberDefinition
,您可以定义一个助手类型和方法,该类型和方法使用p/Invoke签名调用Windows API函数来查找拥有任务栏窗口的进程的句柄(HWND);请注意,在会话中第一次调用此函数时,您将受到按需编译性能的影响


至于,当可能存在多个文件资源管理器进程时()(基于尝试和错误-请告诉我是否出错):

  • 如果多个用户以交互方式登录(无论是否远程登录),则每个这样的用户可能会运行一个或多个Explorer进程,如下所述

  • 以交互方式登录的用户至少有一个资源管理器进程,该进程拥有任务栏和桌面——它可能打开也可能没有打开实际的文件资源管理器窗口;让我们称之为浏览器外壳进程

  • 如果文件资源管理器的
    在单独的进程中启动文件夹窗口
    视图选项为:

    • 关闭(默认设置):以交互方式创建的所有窗口都归Explorer外壳进程所有-不创建新进程

    • 打开:您以交互方式创建的第一个窗口生成一个新的资源管理器进程,然后所有随后打开的窗口都属于该新进程

    • 换句话说:如果您仅以交互方式打开“文件资源管理器”窗口,则可能有一个(
      在单独进程中启动文件夹窗口
      关闭)或最多两个(
      在单独进程中启动文件夹窗口
      打开)资源管理器进程。
      如果以编程方式创建资源管理器窗口,则情况就不同了—请参阅下一点

  • 无论单独进程中的
    启动文件夹窗口如何
    视图设置,都可以通过编程方式创建新的资源管理器进程:

    • 例如,像
      explorer/e,c:\
      这样的命令每次都会创建一个新的explorer进程

正如我在我的情况中所解释的,我打算重新启动该实例。这意味着您的解决方案只有在第一次需要找到流程时才可能是正确的。公平地说,您可以跟踪脚本为第一次“重新启动”任务栏而创建的资源管理器实例的流程ID,并且只在后续运行时重新启动该ID。这很有希望。我确实启用了“在单独进程中启动文件夹”;但是,请注意,如果其他用户也登录,则可能存在其他资源管理器进程;此外,通过编程很容易创建其他进程,例如使用
explorer/e、c:\
Get-Process explorer | ? MainWindowTitle -eq '' # returns taskbar-owning Explorer process
Get-Process -IncludeUserName explorer |
  ? MainWindowTitle -eq '' |
    ? UserName -eq (whoami)
# Define a helper type and method for getting a window's handle
# (HWND) by its class name and title.
$helperType = Add-Type -PassThru -Name "WinApiHelper$PID" -MemberDefinition  @'
  [DllImport("user32.dll", SetLastError=true)]
  public static extern IntPtr FindWindow(string lpszClass, string lpszWindow);
'@

# Locate the explorer.exe process that created the taskbar,
# via window class "Shell_TrayHwnd" and an empty title.
Get-Process explorer | 
  ? MainWindowHandle -eq ($helperType::FindWindow("Shell_TrayWnd", ''))