为什么Get-ChildItem(或ls或dir)返回在x86和x64 PowerShell控制台上执行的不同结果

我在Windows Server机器上启动了用于x86的Powershell控制台并执行:

get-childitem C:\Windows\System32\WindowsPowerShell\v1.0\Modules\*s 

我得到以下列表:

CimCmdlets,DirectAccessClientComponents来说,KDS,Microsoft.PowerShell.Diagnostics,NetQoS的,NetworkConnectivityStatus,PSDiagnostics,ScheduledTasks,TLS

然后,我启动了x64控制台并执行相同的命令,并获得更多的DIR列表:

BestPractices ,CimCmdlets,DirectAccessClientComponents, FailoverClusters ,Kds,Microsoft.PowerShell.Diagnostics,NetQos,NetworkConnectivityStatus, NFS ,PSDiagnostics,ScheduledTasks, SmbWitness ,TLS

我检查了硬链接的FailoverClusters模块文件(我实际上试图导入):

 PS C:\windows\system32\WindowsPowerShell\v1.0\Modules> fsutil hardlink list C:\Windows\System32\WindowsPowerShell\v1.0\Modules\FailoverClusters\failoverclusters.psd1 

我得到以下结果:

\ Windows \ System32 \ WindowsPowerShell \ v1.0 \ Modules \ FailoverClusters \ FailoverClusters.psd1 \ Windows \ WinSxS \ amd64_microsoft-windows-f..rcluster-powershell_31bf3856ad364e35_6.3.9600.17112_none_8555e001e29b71bc \ FailoverClusters.psd1

(注意:看起来像目录本身没有链接,fsutil只返回一个条目 – 与dirname相同)

所以问题是:为什么Get-ChildItem在x86与x64 Get-ChildItem主机上的工作方式不同? 这实际上是如何工作的?

是的,我明白,FailoverClusters模块不能在x86架构上工作,但仍然…我打破了我的头,试图找出错误在哪里(意外编译我的x86架构的C#主机),因为它总是返回类似“未find模块”或“找不到文件”….

从我的答案这里 :

在32位Windows操作系统上,系统文件夹是C:\Windows\System32 。 在64位Windows操作系统上,64位系统文件夹也是C:\Windows\System32 。 但是,64位Windows安装上的32位进程的系统文件夹实际上是C:\Windows\SysWOW64

为了兼容性,64位操作系统上的32位进程将对C:\Windows\System32 透明地重定向C:\Windows\SysWOW64调用,这一过程并不为人所知。

要使32位进程在64位操作系统上引用真实的 System32 ,可以使用C:\Windows\SysNative

由于PowerShell具有32位和64位版本,并且位于系统文件夹内,因此需要使用上述规则来引用正确的可执行文件,具体取决于您是从64位还是32位进程调用它。

典型的场景(你想调用相同的位的版本)是最简单的(只需调用powershell.exe或通过System32引用它),但如果你想引用其他版本,它会变得毛茸茸的。


获取模块

我会进一步补充说,如果你想查看哪些模块可用,你应该调用Get-modulee而不是查看目录。

在32位代码中使用64位模块

如果你需要一个只有64位代码的模块的功能,那么你可以使用PowerShell Remoting来完成这个功能。

你可以远程访问一个64位的机器(甚至是当前机器),执行你需要的代码,把结果返回到32位的过程。

您也可以使用隐式远程来远程使用这些命令,就像它们本地可用一样:

示例(从32位PowerShell):

 $session = New-PSSession -ComputerName . # connecting to the local computer Invoke-Command -Session $session -ScriptBlock { Import-modulee NFS } Import-PSSessin -Session $session -modulee NFS # Call NFS cmdlets # more program stuff Remove-PSSession -Session $session