powershellbatch-filecmdescapingwmi-query

An embarrassing error appears in a .bat file and not in CMD


I'm actually working on a "Computer Info Dumper" and I need to get the ram name + capacity, the problem is that the line that make this: it works in CMD, but not in a .bat file.

Here is the 'command': powershell -command "GWmi CIM_PhysicalMemory|%{\"\"+ ([int]$_.banklabel.Replace('BANK ','') + 1) + \") \" + ($_.capacity/1GB)+\"GB from \"+($_.manufacturer)}"

In CMD, it gives me the wanted result:

8GB from Corsair
4GB from Kingston
8GB from Corsair
4GB from Kingston

But in a .bat file, it gives me this error: (it will be translated because it's in French so the translation won't be perfect)

To character Line:1 : 25

+ ... sicalMemory|{""+ ([int]$_.banklabel.Replace('BANK ','') + 1) + ") " + ...

Expressions are only allowed as the first element of a pipeline.

+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException

+ FullyQualifiedErrorId : ExpressionsMustBeFirstInPipeline

Can anyone help me on that?


Solution

  • As requested, my comment as an answer:

    In a the % character has a special meaning, so a literal character would require escaping. The escape character for a percent is another, i.e. %%.

    @%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NoProfile -Command "Get-CimInstance CIM_PhysicalMemory | %% { \"\" + ([Int]$_.BankLabel.Replace('BANK ','') + 1) + \") \" + ($_.Capacity / 1GB) + \"GiB from \" + ($_.Manufacturer) }"
    

    Or preferably, don't use the % alias for ForEach-Object in a , and then you can match your Command Prompt code withn your script.

    @%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NoProfile -Command "Get-CimInstance CIM_PhysicalMemory | ForEach-Object { \"\" + ([Int]$_.BankLabel.Replace('BANK ','') + 1) + \") \" + ($_.Capacity / 1GB) + \"GiB from \" + ($_.Manufacturer) }"
    

    You will see that I have more correctly allocated the Capacity units as GiB, and that I have replaced your GWmi alias for Get-WmiObject, with the recommended PowerShell v3.0+ alternative Get-CimInstance, (alias gcim).