Custom Inventory Rule Escaping Quotes
I have the following Custom Inventory Rule:
ShellCommandTextReturn(powershell.exe $diskdrive = gwmi win32_diskdrive;foreach($drive in $diskdrive){if($drive.model -match 'SSD'){$ssd='SSD'}else{$ssd='HDD'}$partitions=gwmi -Query """ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"""$($drive.DeviceID.replace('\','\\'))`"""} WHERE AssocClass=Win32_DiskDriveToDiskPartition"""; foreach($part in $partitions){$vols=gwmi -Query """ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"""$($part.DeviceID)`"""} WHERE AssocClass = Win32_LogicalDiskToPartition""";foreach($vol in $vols){out-host -InputObject """$ssd $($vol.name)""";}}})
If you strip out the just the ShellCommandTextReturn( and the closing ) the command runs fine in cmd.exe. It does not work in the CIR.
Log:
[Thu May 23 11:11:45 2013] [CDeployController::ExecuteCustomInventoryRule] statement result: ;7150:VHJ1ZQ0K%TEXT, TRUE
[Thu May 23 11:11:45 2013] [CDeployController::ExecuteCustomInventoryRule] issuing rule [ShellCommandTextReturn(powershell.exe $diskdrive = gwmi win32_diskdrive;foreach($drive in $diskdrive){if($drive.model -match 'SSD'){$ssd='SSD'}else{$ssd='HDD'}$partitions=gwmi -Query """ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"""$($drive.DeviceID.replace('\','\\'))`"""} WHERE AssocClass=Win32_DiskDriveToDiskPartition"""; foreach($part in $partitions){$vols=gwmi -Query """ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"""$($part.DeviceID)`"""} WHERE AssocClass = Win32_LogicalDiskToPartition""";foreach($vol in $vols){out-host -InputObject """$ssd $($vol.name)""";}}});]
[Thu May 23 11:11:45 2013] haveTokenLsaPriv returning: 1
[Thu May 23 11:11:45 2013] KLaunchProcess: Call CreateProcess to launch 'KLaunch.exe . -wait -hide -stdout "C:\Windows\TEMP\dkl720B.tmp" powershell.exe $diskdrive = gwmi win32_diskdrive;foreach($drive in $diskdrive){if($drive.model -match 'SSD'){$ssd='SSD'}else{$ssd='HDD'}$partitions=gwmi -Query "\"\"""\"ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`\"""\"\""$($drive.DeviceID.replace('\','\\'))`"\"\"""\"} WHERE AssocClass=Win32_DiskDriveToDiskPartition\"""\"\""; foreach($part in $partitions){$vols=gwmi -Query "\"\"""\"ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`\"""\"\""$($part.DeviceID)`"\"\"""\"} WHERE AssocClass = Win32_LogicalDiskToPartition\"""\"\"";foreach($vol in $vols){out-host -InputObject "\"\"""\"$ssd $($vol.name)\"""\"\"";}}}':
[Thu May 23 11:11:45 2013] KLaunchProcess: Wait for process to complete
[Thu May 23 11:11:48 2013] KLaunchProcess: process completed status=1
[Thu May 23 11:11:48 2013] [CDeployController::ExecuteCustomInventoryRule] statement result: "", FALSE
It appears to be doing automatic escaping for some of the quotes, but I can't figure out how it is determining what to escape.
I have also tried escaping the quotes with a \ manually and it fails as well.
ShellCommandTextReturn(powershell.exe $diskdrive = gwmi win32_diskdrive;foreach($drive in $diskdrive){if($drive.model -match 'SSD'){$ssd='SSD'}else{$ssd='HDD'}$partitions=gwmi -Query \"\"\"ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`\"\"\"$($drive.DeviceID.replace('\','\\'))`\"\"\"} WHERE AssocClass=Win32_DiskDriveToDiskPartition\"\"\"; foreach($part in $partitions){$vols=gwmi -Query \"\"\"ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`\"\"\"$($part.DeviceID)`\"\"\"} WHERE AssocClass = Win32_LogicalDiskToPartition\"\"\";foreach($vol in $vols){out-host -InputObject \"\"\"$ssd $($vol.name)\"\"\";}}})
Log:
[Thu May 23 11:46:21 2013] [CDeployController::ExecuteCustomInventoryRule] statement result: ;7150:VHJ1ZQ0K%TEXT, TRUE
[Thu May 23 11:46:21 2013] [CDeployController::ExecuteCustomInventoryRule] issuing rule [ShellCommandTextReturn(powershell.exe $diskdrive = gwmi win32_diskdrive;foreach($drive in $diskdrive){if($drive.model -match 'SSD'){$ssd='SSD'}else{$ssd='HDD'}$partitions=gwmi -Query \"\"\"ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`\"\"\"$($drive.DeviceID.replace('\','\\'))`\"\"\"} WHERE AssocClass=Win32_DiskDriveToDiskPartition\"\"\"; foreach($part in $partitions){$vols=gwmi -Query \"\"\"ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`\"\"\"$($part.DeviceID)`\"\"\"} WHERE AssocClass = Win32_LogicalDiskToPartition\"\"\";foreach($vol in $vols){out-host -InputObject \"\"\"$ssd $($vol.name)\"\"\";}}});]
[Thu May 23 11:46:21 2013] haveTokenLsaPriv returning: 1
[Thu May 23 11:46:21 2013] KLaunchProcess: Call CreateProcess to launch 'KLaunch.exe . -wait -hide -stdout "C:\Windows\TEMP\dkl1E03.tmp" powershell.exe $diskdrive = gwmi win32_diskdrive;foreach($drive in $diskdrive){if($drive.model -match 'SSD'){$ssd='SSD'}else{$ssd='HDD'}$partitions=gwmi -Query "\"\"""\"ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`\"""\"\""$($drive.DeviceID.replace('\','\\'))`"\"\"""\"} WHERE AssocClass=Win32_DiskDriveToDiskPartition\"""\"\""; foreach($part in $partitions){$vols=gwmi -Query "\"\"""\"ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`\"""\"\""$($part.DeviceID)`"\"\"""\"} WHERE AssocClass = Win32_LogicalDiskToPartition\"""\"\"";foreach($vol in $vols){out-host -InputObject "\"\"""\"$ssd $($vol.name)\"""\"\"";}}}':
[Thu May 23 11:46:21 2013] KLaunchProcess: Wait for process to complete
[Thu May 23 11:46:24 2013] KLaunchProcess: process completed status=1
[Thu May 23 11:46:24 2013] [CDeployController::ExecuteCustomInventoryRule] statement result: "", FALSE
I just can't see where the escape sequence needs to happen. Any help would be appreciated. Thanks.
Answers (2)
I know one of these two problems fixed my concern.
Either the ` or the $($variable) were causing problems. I resolved the need for powershell escaping by creating a powershell quote variable, $q = '"""'; I resolved the $($variable) by doing some matching and other variable manipulation to remove the need for the $().
Hope this helps someone else!
Looks like a good solution, but I don't think it improves the readability of the script :D
I think that the interface for these kind of rules should be improved.
But nevertheless : When I need such a "complicated" query, I just write the info to a registry key or file using a KACE script, and pick up the values from there with a RegistryValueReturn(registryPath, name, type)
That gives me a more granular control on the timing and frequency. Some things just don't need to be updated at every inventory update.