Difficulty running powershell in a for loop due to unquoting and closing of parenthesis

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
shodan
Posts: 89
Joined: 01 May 2023 01:49

Difficulty running powershell in a for loop due to unquoting and closing of parenthesis

#1 Post by shodan » 17 May 2024 02:41

I need to run the following commands in a for loop to capture their output

Code: Select all

powershell -command "Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorID | ForEach-Object { $_.PSObject.Properties | ForEach-Object { if ($_.Name -ne 'CimInstanceProperties') { \"$($_.Name)=$($_.Value)\" }}}"
powershell -command "Get-WmiObject -Namespace root\wmi -Class WmiMonitorBasicDisplayParams | Format-List *"
powershell -command "Get-WmiObject -Namespace root\wmi -Class WmiMonitorDescriptorMethods | Format-List *"
powershell -command "Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.Screen]::AllScreens | ForEach-Object { $_ | Format-List * }"
powershell -command "Get-WmiObject Win32_DesktopMonitor | Format-List *"
powershell -command "$monitors = Get-WmiObject -Namespace root\wmi -Class WmiMonitorDescriptorMethods;foreach ($monitor in $monitors) { $edidData = $monitor.WmiGetMonitorRawEEdidV1Block(0); if ($edidData) { if ($edidData.BlockContent) { $edidArray = $edidData.BlockContent; $edidString = [System.BitConverter]::ToString($edidArray); Write-Output $edidString; } else { Write-Output 'No EDID block content found'; } } else { Write-Output 'No EDID data found'; }}"

I am focusing on this line in particular

Code: Select all

powershell -command "Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorID | ForEach-Object { $_.PSObject.Properties | ForEach-Object { if ($_.Name -ne 'CimInstanceProperties') { \"$($_.Name)=$($_.Value)\" }}}"

I wish to run it inside a for loop as follows

Code: Select all

for /f "tokens=1,* delims=*" %%a in ('powershell -command "rest of command here" ') do if "[%~2]" NEQ "[]" ( set "%~2.%%a=%%b" ) else ( echo %%a:%%b )

I have tried many permutations but I cannot find something that works !

I really want this to be a one-liner with no temp files

Here is what I tried so far

Code: Select all

for /f "tokens=1,* delims=*" %%a in ('powershell -command "Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorID | ForEach-Object { $_.PSObject.Properties | ForEach-Object { if ($_.Name -ne 'CimInstanceProperties') { \"$_.Name=$_.Value\" } } }"') do if "[%~2]" NEQ "[]" ( set "%~2.%%a=%%b" ) else ( echo %%a:%%b )
for /f "tokens=1,* delims==" %%a in ('powershell -Command "Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorID ^| ForEach-Object { $_.PSObject.Properties ^| ForEach-Object { if ($_.Name -ne ''CimInstanceProperties'') { ''$($_.Name)=$($_.Value)'' } } }"') do if "[%~2]" NEQ "[]" ( set "%~2.%%a=%%b" ) else ( echo %%a:%%b )
for /f "tokens=1,* delims==" %%a in ('powershell -Command "Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorID ^| ForEach-Object { $_.PSObject.Properties ^| ForEach-Object { if ($_.Name -ne ''CimInstanceProperties'') { \"\"$($_.Name)=$($_.Value)\"\" } } } "') do if "[%~2]" NEQ "[]" ( set "%~2.%%a=%%b" ) else ( echo %%a:%%b )
for /f "tokens=1,* delims==" %%a in ('powershell -Command "Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorID ^| ForEach-Object { $_.PSObject.Properties ^| ForEach-Object { if ($_.Name -ne \"CimInstanceProperties\") { \"\"$($_.Name)=$($_.Value)\"\" } } } "') do if "[%~2]" NEQ "[]" ( set "%~2.%%a=%%b" ) else ( echo %%a:%%b )
for /f "tokens=1,* delims==" %%a in ('powershell -Command "Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorID | ForEach-Object { $_.PSObject.Properties | ForEach-Object { if ($_.Name -ne ''CimInstanceProperties'') { \"\"$($_.Name)=$($_.Value)\"\" } } }"') do if "[%~2]" NEQ "[]" ( set "%~2.%%a=%%b" ) else ( echo %%a:%%b )
for /f "tokens=1,* delims==" %%a in ('powershell -Command "Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorID | ForEach-Object { $_.PSObject.Properties | ForEach-Object { if ($_.Name -ne \"CimInstanceProperties\") { \"\"$($_.Name)=$($_.Value)\"\" } } }"') do if "[%~2]" NEQ "[]" ( set "%~2.%%a=%%b" ) else ( echo %%a:%%b )
for /f "tokens=1,* delims==" %%a in ('powershell -command "Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorID ^| ForEach-Object { $_.PSObject.Properties ^| ForEach-Object { if ($_.Name -ne ''CimInstanceProperties'') { ''$($_.Name)=$($_.Value)'' }}}"') do if "[%~2]" NEQ "[]" ( set "%~2.%%a=%%b" ) else ( echo %%a:%%b )
for /f "tokens=1,* delims==" %%a in ('powershell -command "Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorID ^| ForEach-Object { $_.PSObject.Properties ^| ForEach-Object { if ($_.Name -ne ''CimInstanceProperties'') { if ($_.Value -is [System.Array]) { ''$($_.Name)=''+($_.Value -join '' '')+'' } else { ''$($_.Name)=$($_.Value)'' } } } }"') do if "[%~2]" NEQ "[]" ( set "%~2.%%a=%%b" ) else ( echo %%a:%%b )
for /f "tokens=1,* delims==" %%a in ('powershell -command "Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorID | ForEach-Object { $_.PSObject.Properties | ForEach-Object { if ($_.Name -ne ''CimInstanceProperties'') { if ($_.Value -is [System.Array]) { ''$($_.Name)=''+($_.Value -join '' '')+'' } else { ''$($_.Name)=$($_.Value)'' } } }}"') do if "[%~2]" NEQ "[]" ( set "%~2.%%a=%%b" ) else ( echo %%a:%%b )
for /f "tokens=1,* delims==" %%a in ('powershell -command "Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorID | ForEach-Object { $_.PSObject.Properties | ForEach-Object { if ($_.Name -ne 'CimInstanceProperties') { \"$($_.Name)=$($_.Value)\" }}}"') do if "[%~2]" NEQ "[]" ( set "%~2.%%a=%%b" ) else ( echo %%a:%%b )
for /f "tokens=1,* delims==" %%a in ('powershell -command "Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorID | ForEach-Object { $_.PSObject.Properties | ForEach-Object { if ($_.Name -ne 'CimInstanceProperties') { \"\"$($_.Name)=$($_.Value)\"\" } } }"') do if "[%~2]" NEQ "[]" ( set "%~2.%%a=%%b" ) else ( echo %%a:%%b )
for /f "tokens=1,* delims==" %%a in ('powershell -command "Invoke-Expression \"Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorID ^| ForEach-Object { $_.PSObject.Properties ^| ForEach-Object { if ($_.Name -ne 'CimInstanceProperties') { \\\"$($_.Name)=$($_.Value)\\\" } } }\""') do if "[%~2]" NEQ "[]" ( set "%~2.%%a=%%b" ) else ( echo %%a:%%b )
for /f "tokens=1,* delims==" %%a in ('powershell -command "Invoke-Expression \"Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorID | ForEach-Object { $_.PSObject.Properties | ForEach-Object { if ($_.Name -ne 'CimInstanceProperties') { \\\"$($_.Name)=$($_.Value)\\\" } } }\""') do if "[%~2]" NEQ "[]" ( set "%~2.%%a=%%b" ) else ( echo %%a:%%b )
for /f "usebackq tokens=1,* delims==" %%a in (`powershell -Command "Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorID ^| ForEach-Object { $_.PSObject.Properties ^| ForEach-Object { if ($_.Name -ne 'CimInstanceProperties') { '^"$($_.Name)=$($_.Value)'^" } } }"`) do if "[%~2]" NEQ "[]" ( set "%~2.%%a=%%b" ) else ( echo %%a:%%b )
for /f "usebackq tokens=1,* delims==" %%a in (`powershell -Command "Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorID ^| ForEach-Object { $_.PSObject.Properties ^| ForEach-Object { if ($_.Name -ne 'CimInstanceProperties') { ^"$($_.Name)=$($_.Value)^" } } }"`) do if "[%~2]" NEQ "[]" ( set "%~2.%%a=%%b" ) else ( echo %%a:%%b )
for /f "usebackq tokens=1,* delims==" %%a in (`powershell -Command "Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorID | ForEach-Object { $_.PSObject.Properties | ForEach-Object { if ($_.Name -ne 'CimInstanceProperties') { \"\$($_.Name)=$($_.Value)\" } } }"`) do if "[%~2]" NEQ "[]" ( set "%~2.%%a=%%b" ) else ( echo %%a:%%b )

The issue is inside of this part

Code: Select all

{ \"$($_.Name)=$($_.Value)\" }
Batch does not recognize the powershell escaping of the doublequote \"
So it thinks the rest is unquoted. Then the parenthesis gets closed.
Strangely, we are still inside the single quoting at this point. But it seem that still closes this part of the for loop early

Code: Select all

for %%a in () <-- 

miskox
Posts: 631
Joined: 28 Jun 2010 03:46

Re: Difficulty running powershell in a for loop due to unquoting and closing of parenthesis

#2 Post by miskox » 17 May 2024 03:59

Wouldn't it be easier for you to use a temporary file and process this temporary file with FOR loop?

Saso

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Difficulty running powershell in a for loop due to unquoting and closing of parenthesis

#3 Post by penpen » 17 May 2024 16:13

You have to escape the characters, that are not encapsulated within double quotes, which in the example should be everything colored red:
powershell -command "Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorID | ForEach-Object { $_.PSObject.Properties | ForEach-Object { if ($_.Name -ne 'CimInstanceProperties') { \"$($_.Name)=$($_.Value)\" }}}"

So the following might help you (untested; i changed the content of the for loop so you can use that as a test whether or not i escaped all relevant characters):

Code: Select all

for /f "tokens=1,* delims=*" %%a in ('powershell -command "Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorID | ForEach-Object { $_.PSObject.Properties | ForEach-Object { if ($_.Name -ne 'CimInstanceProperties') { \"$($_.Name^)=$($_.Value^)\" }}}"') do (
	echo(%%~a   -----   %%~b
)

penpen

shodan
Posts: 89
Joined: 01 May 2023 01:49

Re: Difficulty running powershell in a for loop due to unquoting and closing of parenthesis

#4 Post by shodan » 17 May 2024 19:07

That's a bingo

Thank you @penpen

Code: Select all

Active   -----   True
InstanceName   -----   DISPLAY\DELD092\4&dead9271&0&UID21beef_0
ManufacturerName   -----   68 69 76 0 0 0 0 0 0 0 0 0 0 0 0 0
ProductCodeID   -----   68 48 57 50 0 0 0 0 0 0 0 0 0 0 0 0
SerialNumberID   -----   57 80 DE AD BE EF 52 80 DE AD BE EF 0 0 0 0
UserFriendlyName   -----   68 69 76 76 32 80 49 57 49 55 83 0 0
UserFriendlyNameLength   -----   13
WeekOfManufacture   -----   12
YearOfManufacture   -----   2018
PSComputerName   -----
CimClass   -----   root/wmi:WmiMonitorID
CimSystemProperties   -----   Microsoft.Management.Infrastructure.CimSystemProperties
Active   -----   True
InstanceName   -----   DISPLAY\DELD092\4&dead9271&0&UID21beef_0
ManufacturerName   -----   68 69 76 0 0 0 0 0 0 0 0 0 0 0 0 0
ProductCodeID   -----   68 48 57 50 0 0 0 0 0 0 0 0 0 0 0 0
SerialNumberID   -----   57 80 DE AD BE EF 52 80 DE AD BE EF 0 0 0 0
UserFriendlyName   -----   68 69 76 76 32 80 49 57 49 55 83 0 0
UserFriendlyNameLength   -----   13
WeekOfManufacture   -----   12
YearOfManufacture   -----   2018
PSComputerName   -----
CimClass   -----   root/wmi:WmiMonitorID
CimSystemProperties   -----   Microsoft.Management.Infrastructure.CimSystemProperties
Active   -----   True
InstanceName   -----   DISPLAY\DELD092\4&dead9271&0&UID21beef_0
ManufacturerName   -----   68 69 76 0 0 0 0 0 0 0 0 0 0 0 0 0
ProductCodeID   -----   68 48 57 50 0 0 0 0 0 0 0 0 0 0 0 0
SerialNumberID   -----   57 80 DE AD BE EF 52 80 DE AD BE EF 0 0 0 0
UserFriendlyName   -----   68 69 76 76 32 80 49 57 49 55 83 0 0
UserFriendlyNameLength   -----   13
WeekOfManufacture   -----   12
YearOfManufacture   -----   2018
PSComputerName   -----
CimClass   -----   root/wmi:WmiMonitorID
CimSystemProperties   -----   Microsoft.Management.Infrastructure.CimSystemProperties

Post Reply