Relevance for Installation

I’ve checked a number of relevance topics but have yet to find one that relates to what I am trying to do. I have a relevance statement that would install Qualys agent if it is not in the registry. This is not working as expected. I have 7 servers that show up as relevant when there should be about 50+ servers that show up. Those 7 that show up shouldn’t be there if the remaining servers are not there either. Statement below. I am still pretty new to this since I do not have to do this very often

exist key whose (value “DisplayName” of string does not contain “Qualys Cloud Security Agent”) of key “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” “of native registry”

Is it because you are not looking at both 32 and 64 registries?

We used this recently

exists (it as string) whose(it contains "Edge") of values "DisplayName" of keys of keys "HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall" of (x64 registries; x32 registries)

You could also try to look for the service

NOT exists service whose (service name of it as string contains "QualysAgent")

Or if you still want to use the registry

NOT exists key "HKEY_LOCAL_MACHINE\SOFTWARE\Qualys\QualysAgent" of native registry

1 Like

we use the service name often. Works best for us.

We avoid case sensitivity also…

NOT exists service whose (service name of it as string as lowercase = "qualysagent")

1 Like

I like the other responses here, especially looking for the service, but I like a good relevance challenge so I’d like to dig into this anyway

This is a good example for a short Relevance lesson. It’s often very useful to use the Fixlet Debugger, to split the statement into smaller pieces and find the error (WebUI Query App is also useful for things like this, especially where you get “some” of the expected results but not others)

Let’s throw that statement into the Fixlet Debugger:


First thing we see is that all the quotes are in Red. That’s because these are “Smart Quotes” and not "Normal Quotes". That may be an artifact from Forum formatting, which is why we highlight the code and use the ‘Format as Code’ button to fix the formatting and quotes:

After fixing those quotes, we end up with

q: exist key whose (value "DisplayName" of string does not contain "Qualys Cloud Security Agent") of key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" "of native registry"
E: The operator "key" is not defined.

This is because “of native registry” is quoted and it should not be - we’re looking for the ‘native registry’ object, not a literal string “of native registry”

q: exist key whose (value "DisplayName" of string does not contain "Qualys Cloud Security Agent") of key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" of native registry
E: The operator "string" is not defined.

Now the error is that there is no “string” operator … I see the error here but let’s stick with the process of finding the error. To do that I would start splitting up the query, which usually works from right to left. Starting from the right, let’s see if ‘native registry’ is valid

q: native registry
E: This expression evaluates to an unrepresentable object of type "registry"

This is a “good” error message. It tells us that we did find a ‘registry’ object, there’s just no string to display a default value for it. Let’s move on to the next object

q: key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" of native registry
A: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
T: 18.649 ms
I: singular registry key

Good so far, we found the “Uninstall” registry key. Moving further to the left…

q: key whose (value "DisplayName" of string does not contain "Qualys Cloud Security Agent") of key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" of native registry
E: The operator "string" is not defined.

This gives an error, so let’s remove the filter and see whether that’s where the error was

q: key of key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" of native registry
A: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip
E: Singular expression refers to non-unique object.

We get a partial result and then an error…this is because we’re retrieving a singular ‘key’ but are getting multiple ‘keys’ results. We also know now that the string error is inside the whose() block. So, to test that let’s try the plural “keys” to remove the singular expression error, and try to pull that “DisplayName” property out of each key…

q: values "DisplayName" of keys of key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" of native registry
A: 7-Zip 21.06 (x64)
A: Microsoft SQL Server 2019 (64-bit)
A: Microsoft SQL Server 2019 (64-bit)
A: Notepad++ (64-bit x64)
A: OpenSSL 3.0.0 Light (64-bit)
A: Sublime Text
A: SQL Server Management Studio for Reporting Services
...

So, we can pull DisplayNames…what was wrong with our whose () filter?

whose (value "DisplayName" of string does not contain "Qualys Cloud Security Agent")
simply that value "DisplayName" of string does not exist…this is trying to retrieve an object named “string” and pulling a “DisplayName” property…when what we need is the DisplayName property of the registry key which we refer to as “it”. This filter should have been whose (value "DisplayName" of it as string does not contain "Qualys Cloud Security Agent")

So now that we know all the syntax errors, we can put together the whole query as

q: exist keys whose (value "DisplayName" of it as string does not contain "Qualys Cloud Security Agent") of key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" of native registry
A: True
T: 15.630 ms

But, I’m afraid now you’ll still get a whole lot of Relevant machines; in fact nearly every Windows machine will be relevant, regardless of whether Qualys is installed or not. Now we have a much more difficult problem to debug - it’s not a syntax problem, but a logic problem.

What this query is doing, is checking every Uninstall key, and looking for any key that does not contain “Qualys Cloud Security Agent” in the DisplayName. If there are 3 uninstall keys, one of which is for Qualys, the other two keys that don’t contain Qualys would make this True. If there are three uninstall keys, and none were for Qualys, it would still return True.

I’m not sure what you’re trying to return from the original query, but it should be either “a machine which has Qualys” or “a machine without Qualys”. These queries boil down to either “there is at least one DisplayName containing Qualys” or “there are no DisplayNames with Qualys”, which can be written as one of

q: exist keys whose (value "DisplayName" of it as string contains "Qualys Cloud Security Agent") of key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" of native registry

or

q: not exist keys whose (value "DisplayName" of it as string contains "Qualys Cloud Security Agent") of key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" of native registry
4 Likes

that was very helpful to learn.

Excellent explanation!

But like @D.Dean said earlier, I always use “as lowercase” to avoid case sensitivity. Just in case (no pun intended)

q: exist keys whose (value "DisplayName" of it as string as lowercase contains "qualys cloud security agent") of key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" of native registry