【问题标题】:Why do powershell and python give different result for same command?为什么powershell和python对相同的命令给出不同的结果?
【发布时间】:2019-11-21 22:08:11
【问题描述】:

为什么要用 Python 编写这个脚本

import subprocess, io
p = subprocess.Popen(["powershell.exe", "Get-Process | Where-Object { $_.MainWindowTitle } |    Format-List Id,Name,Path"], stdout=subprocess.PIPE)
for line in io.TextIOWrapper(p.stdout, encoding="utf-8"):
    line = " ".join(line.split())
    print(line)

在 Powershell 中编写命令

Get-Process | Where-Object { $_.MainWindowTitle } | Format-List Id,Name,Path

有不同的结果? 例如,这是 Powershell 的一些结果:

Id   : 7692
Name : NVIDIA Share
Path : C:\Program Files\NVIDIA Corporation\NVIDIA GeForce Experience\NVIDIA Share.exe

Id   : 7232
Name : Origin
Path : C:\Program Files (x86)\Origin\Origin.exe

这在 Python 中也是一样的:

Id   : 7692
Name : NVIDIA Share
Path :

Id   : 7232
Name : Origin
Path : C:\Program Files (x86)\Origin\Origin.exe

在 Powershell 中,Python 结果中有时会缺少路径。为什么会这样?有什么方法可以解决这个问题?

【问题讨论】:

  • 两个进程都提升了吗?
  • 两个进程都被提升了。
  • 我的理解是,如果你想运行多个进程并将结果从一个传递到下一个,你必须使用shell=True 参数到Popen()。既然你没有这样做,我什至不知道你的命令是如何假装工作的。
  • 使用shell=True 参数没有任何区别。
  • 都是 x64 进程吗?

标签: python powershell


【解决方案1】:

我认为,就像@Viet Hoang 一样,这是一个简单的海拔问题(因为这通常是 90% 的问题)。因此,在盲目的系统管理员信心下,我决定对其进行测试。让我们以管理员身份启动 PowerShell,然后运行:

PS C:\> (New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
True

好的。好的。我们有一个真正提升的 PowerShell 会话。让我们启动 Python,一劳永逸地证明 @Lolman 不知道他在做什么,并证明 Python 不知道如何启动适当的提升 PowerShell 会话:

PS C:\> python
Python 3.8.0 (tags/v3.8.0:fa919fd, Oct 14 2019, 19:21:23) [MSC v.1916 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess, io
>>> p = subprocess.Popen(["powershell.exe", "(New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)"], stdout=subprocess.PIPE)
>>> for line in io.TextIOWrapper(p.stdout, encoding="utf-8"):
...     line = " ".join(line.split())
...     print(line)
...
True

太棒了!正如预期的那样,它返回了......嗯......呃 - 哦......True ........嗯......嗯......坚果。有了这个想法。 @Lolman 实际上确实知道如何尝试。

好的。现在这需要一些创造性的思考。让我们比较一下我得到的一些条目:

PowerShell

PS C:\> Get-Process | Where-Object { $_.MainWindowTitle } | Format-List Id,Name,Path

...

Id   : 2660
Name : powershell
Path : C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe

Id : 31200
Name : Code
Path : C:\Users\HAL9256\AppData\Local\Programs\Microsoft VS Code\Code.exe

Id : 22804
Name : devenv
Path : C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\devenv.exe

...

Python

PS C:\> python
Python 3.8.0 (tags/v3.8.0:fa919fd, Oct 14 2019, 19:21:23) [MSC v.1916 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess, io
>>> p = subprocess.Popen(["powershell.exe", "Get-Process | Where-Object { $_.MainWindowTitle } | Format-List Id,Name,Path"], stdout=subprocess.PIPE)
>>> for line in io.TextIOWrapper(p.stdout, encoding="utf-8"):
...     line = " ".join(line.split())
...     print(line)
...

Id   : 2660
Name : powershell
Path : 

Id   : 31200
Name : Code
Path :

Id   : 22804
Name : devenv
Path : C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\devenv.exe

...

那么,让我们看看显示路径信息的进程与不显示路径信息的进程之间的区别。我看到很多 Program Files (x86),但没有看到 Program Files...嗯...这看起来像是 32 位与 64 位的问题。

为了证明这一点,我以管理员身份启动了 32 位 Windows PowerShell (x86),并运行了相同的命令:

Windows PowerShell (x86)

PS C:\> (New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
True

PS C:\> Get-Process | Where-Object { $_.MainWindowTitle } | Format-List Id,Name,Path

...

Id   : 2660
Name : powershell
Path : 

Id   : 31200
Name : Code
Path :

Id   : 22804
Name : devenv
Path : C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\devenv.exe

...

啊哈! 确实看起来像是 32 位与 64 位的问题。行。所以,让我们证明这一点。让我们下载 Python 64 位再试一次:

PS C:\> C:\Users\HAL9256\AppData\Local\Programs\Python\Python38\python.exe
Python 3.8.0 (tags/v3.8.0:fa919fd, Oct 14 2019, 19:37:50) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess, io
>>> p = subprocess.Popen(["powershell.exe", "Get-Process | Where-Object { $_.MainWindowTitle } |    Format-List Id,Name,Path"], stdout=subprocess.PIPE)
>>> for line in io.TextIOWrapper(p.stdout, encoding="utf-8"):
...     line = " ".join(line.split())
...     print(line)
...

Id   : 2660
Name : powershell
Path : C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe

Id : 31200
Name : Code
Path : C:\Users\HAL9256\AppData\Local\Programs\Microsoft VS Code\Code.exe

Id : 22804
Name : devenv
Path : C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\devenv.exe

...

是的!我们现在得到了所有的信息。 PowerShell 控制台以 64 位运行,因此可以查看完整路径和进程信息。 Python 默认是 32 位的,因此看不到 64 位进程的完整路径和进程信息。只有通过显式运行 64 位版本的 Python(来自提升的会话),我们才能看到所有路径和进程信息。

【讨论】:

  • 现在这是一个非常令人信服的答案。让我的回答现在看起来像评论。我想将它留在上下文参考中仍然没有什么用处。很好的侦探 - 赞成。
  • 感谢您提供清晰而翔实的答案。老实说,我对我在那里所做的事情知之甚少。问题是运行 32 位 Python。安装64位版本,运行正常。
【解决方案2】:

进程路径未显示是缺乏提升访问权限的非常明显的指示。

即使您以管理员身份运行 Python,子进程也会失去其管理访问权限。

您可以通过在 Python 内外运行以下检查来正确验证:

(New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-15
    • 1970-01-01
    • 2015-06-15
    • 2021-03-14
    • 2017-01-02
    • 2021-05-25
    • 2012-06-22
    相关资源
    最近更新 更多