用Ruby执行PowerShell命令

6
我试图从Ruby代码中执行PowerShell命令。以下是命令: Get-WmiObject -Class Win32_Product -ComputerName . -Filter "Name='Qlik Sense Client'" | Select-Object -Property version 它完美地给出了产品版本。但是,当我尝试在Ruby中执行相同的操作时(整个命令在反引号中),如下所示: find = `powershell.exe Get-WmiObject -Class Win32_Product -ComputerName . -Filter "Name=''"|Select-Object -Property version` 命令会中断,无法解释Ruby中的引号、管道符等。我尝试转义这些引号,但仍然会中断。我不知道如何转义那个管道符。 请在此处帮助我或为我提供相关信息。非常感谢。
2个回答

7

我现在已经测试过了:

require 'base64'
cmd = %{Get-WmiObject -Class Win32_Product -ComputerName . -Filter "Name='Qlik Sense Client'"|Select-Object -Property version}
encoded_cmd = Base64.strict_encode64(cmd.encode('utf-16le'))
find = `powershell.exe -encodedCommand #{encoded_cmd}`

Powershell需要UTF-16LE编码的字符串,因此在进行base64转换之前,您需要将其从Ruby的编码(UTF-8)转换。


或者,您可以尝试使用shellescape来自shellwords,以便转义命令,使shell将其解释为单个字符串。

另一种选择是使用powershell.exe -Command -popen3。这将允许您使用文件流编写命令并读取其结果。


感谢Max的回复。但是我执行ps命令的最后一行无法读取该二进制文件。它给出了以下信息:“??????4??????????????????????????????????????????4?????????:术语\n'??????4?????????????????????? ????4?????????'不被识别为cmdlet、函数、\n脚本文件或可操作程序的名称。 我尝试删除换行符等,但输出仍然相同。再次请问您能否给我一个popen的例子。我的命令有一个管道,所以想知道如何传递它。再次感谢。 - padmaksha roy
嗨Max,是的,我确实尝试了base64。第一行将其转换为一些二进制代码,但当我运行powershell -exe命令时,它会出现上述错误。请指导是否需要修改某些内容。非常感谢! - padmaksha roy
@padmaksharoy 我找到了错误并纠正了我的答案。 - Max
有什么建议吗? - padmaksha roy
嗨Max,无论如何我把命令放在了一个ps1脚本中,一切都正常工作。如果你有时间,请随时告诉我,为什么它没有按照你所说的方式工作。非常感谢。 - padmaksha roy
显示剩余7条评论

0

这里有一个关于如何调用外部应用程序的示例,也可以与Powershell一起使用。从控制台中复制您的工作命令在 { } 之间,不要有额外的分隔符。% Q还使得在情况下进行变量插值变得可能,如果您的命令不总是相同的,它的工作方式与双引号之间的方式相同。

所有输出都通过 "2>&1" 捕获,并逐行在 while 后的块中枚举。

如果捕获了多行,则需要检查显示所需结果的行并返回该结果。

def powershell 
  command = %Q{your command just like you execute it in a console}
  IO.popen(command+" 2>&1") do |pipe|
    pipe.sync = true
    while lijn = pipe.gets
      # do whatever you need with the output of the command
      # return the result
    end
  end
end

如果您不需要插值,可以使用%q{}替代方案,因为插值也可能会出现问题。在与获取PowerShell结果的同一控制台中使用Ruby命令。确保您可以从其中运行PowerShell(必须在路径中)。

但是据我所知,这将为您获取计算机上安装的产品的名称和版本。

为什么不只使用Ruby?它比非常缓慢的Wmi查询快得多。

require 'win32/registry'

Win32::Registry::HKEY_LOCAL_MACHINE.open(
  'Software\Microsoft\Windows\CurrentVersion\Uninstall'
) do |reg|
  reg.each_key do |key|
    k = reg.open(key)
    puts key
    puts k["DisplayName"]    rescue "?"
    puts k["DisplayVersion"] rescue "?"
    puts
  end
end

嗨Peter,非常感谢您的回复。我尝试运行没有任何分隔符的powershell命令,如下所示:command = %Q{Get-WmiObject -Class Win32_Product -ComputerName . -Filter "Name='Java Auto Updater'"|Select-Object -Property version}但它无法执行powershell命令。PS C:\Users\padmaksha.roy\Documents> ruby cmd_test.rb 'Get-WmiObject' is not recognized as an internal or external command,命令可以正常工作。输出如下:

version

2.8.121.13请提供建议。
- padmaksha roy
尝试使用%q{},并查看我添加的建议。我无法运行您使用的PowerShell命令,在控制台中已经出现错误。 - peter
嗨Peter,再次多谢。%q{}会给出相同的错误,无法解释PowerShell命令。你建议的第二件事确实可行,但它并未提供所有产品列表。我需要改变目录才能获取所有安装的产品列表吗?然后我会为我想要的产品添加一些检查。如果你在这方面再提供一些建议,我将不胜感激。再次感谢。 - padmaksha roy
只需使用基本的“powershell.exe Get-WmiObject -Class Win32_Product -ComputerName .”,并在while块中进行过滤和属性选择,但速度会很慢,否则可以先使用ruby方法,在注册表中搜索所需信息所在的键。使用regedit.exe。 - peter
嗨Peter,我可以使用rub win32 Reg进行一些迭代来获取确切的细节。非常感谢你的帮助。 - padmaksha roy
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接