如何强制 powershell 刷新缓存数据?PSDrive 的 Get-ChildItem 结果不是最新的

如何强制 powershell 刷新缓存数据?PSDrive 的 Get-ChildItem 结果不是最新的
Import-Module WebAdministration
$pool = "ChannelServices"
$wp = Get-ChildItem "IIS:\AppPools\$pool\WorkerProcesses"
Get-Process -Id $wp.processId
Restart-WebAppPool $pool
sleep 5
Get-ChildItem "IIS:\AppPools\$pool\WorkerProcesses"
Get-Process -Id $wp.processId

因此,当我对特定 AppPool 的 WorkerProcesses 执行 Get-ChildItem,然后重新启动该 AppPool 时,我应该会得到一个新的 PID,我确实这样做了。但是,重新运行 Get-ChildItem 仍然显示旧 PID。如果我关闭 Powershell 并重新打开,它不会显示正确的新 PID。

我如何强制 Powershell 清除其缓存或任何保存不正确信息的东西……

显示 Get-ChildItem 如何未使用新的 PID 进行更新。

更新 只是为了清楚起见,我的问题是当使用 IIS PSDrive 时如何清除本地缓存。

我注意到 TypeName:Microsoft.IIs.PowerShell.Framework.ConfigurationElement#workerProcesses#workerProcess

有一个方法:名称 MemberType 定义
---- ---------- ----------
ClearLocalData 方法 void ClearLocalData()

但它对我来说并没有真正起作用...就像下面有人说的那样,这可能只是一个错误。

我在下面看到了有关如何使用 WMI 的答案,我知道这一点。

@theJasonHelmick 提供了一个很好的例子:

GWMI win32_process -filter "name='w3wp.exe'" | Select Name, ProcessId, @{n='AppPool';e={$_.GetOwner().user}}

这给了我运行 AppPool 的用户名。我对其进行了一些修改,以便从命令行中提取实际的应用程序池名称:

Get-WmiObject -Class win32_process -filter "name='w3wp.exe'" | Select Name, ProcessId, @{n='AppPool';e={($_.CommandLine).Split("`"")[1]}}

答案1

我可以在 IIS 8.5 上重现此行为,对我来说这看起来像是一个错误。

在 Get-ChildItem 返回过期 PID 的同一 PowerShell 会话中使用 WMI 对我来说是有效的

(gwmi -NS 'root\WebAdministration' -class 'WorkerProcess' | ? AppPoolName -eq $pool | Select -First 1).ProcessId

这返回了第一个 WorkerProcess 的正确 pid

答案2

如果您需要刷新工作进程的缓存,您只需删除并再次导入 Web 管理模块即可。

Remove-Module WebAdministration
Import-Module WebAdministration

可能不是利用 WMI 的最佳解决方案,但如果由于某种原因您无法访问 IIS WMI 对象或无法安装它们,那么这将起作用。

答案3

除非我完全错过了什么,否则我猜你将第一个 get-process 存储在变量中$wp然后再次引用该变量会返回旧数据?

如果您执行以下任一操作会怎样:

  • 第二次get-childitem再次运行时存储$wp(覆盖值)?
  • 再次使用之前删除该变量:

    移除变量wp

  • 将第二个存储get-childitem在具有完全不同名称的变量中?

我非常喜欢remove-variable自己,因为旧的价值观确实会引起意想不到的怪异现象。


[编辑] Peter Hahndorf 的答案似乎是 Microsoft 认可的替代方案,尽管我现在放错了链接。但由于导致该行为的原因确实似乎是一个可能的错误,我只会补充以下内容:

这家伙似乎已经用 C# 以最高效的方式解决了回收应用程序池的问题。如果速度至关重要(WMI 通常比较耗时),例如必须在短时间内进行大量回收,那么这种方法值得考虑。

%WinDir%\system32\Inetsrv\Microsoft.Web.Administration.dll如果首先将其加载到 shell 中以访问命名空间,那么将解决方案移植到 Powershell 看起来并不太难。

该代码的原始参考点似乎来自微软这里

答案4

回答一个老问题,因为这是 Google 搜索中关于我的问题的首要内容,并且没有我的解决方案。

我正在观察文件更新并使用 Get-ChildItem 获取对它的引用。

$output = Get-ChildItem -Path $path -File $file | Where-Object -FilterScript {($_.LastWriteTime -gt $DateNow)}

每次我想刷新 $output 时,我只需重复上面的代码即可

虽然我知道文件大小在增加,但 $output.length 会保持不变。如果我在目录中按 F5 键,那就没问题了。

使用 $output.refresh 刷新对象而无需重新分配它。

相关内容