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.

0 Comments   [ + ] Show Comments

Comments

Please log in to comment

Answers

0

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!

Answered 05/23/2013 by: dimitris
Purple Belt

Please log in to comment
0

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.

Answered 05/24/2013 by: Magnum_
Orange Senior Belt

Please log in to comment
Answer this question or Comment on this question for clarity

Share