Using Substituion

(imported topic written by kwdobbin)

Here are the results from qna:

Q: value “UninstallString” of key “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall{1ED6CA46-633C-46CD-9D0F-2A8AE225E8A6}” of registry

A: MsiExec.exe /X{1ED6CA46-633C-46CD-9D0F-2A8AE225E8A6}%00

The character (%00) at the end of the answer line should not be there. This is preventing variable substitution in my task from executing the command line and related switches correctly. When I run the answer above directly from a pc the command executes, but added switches are ignored. Is there a better way to achieve the desired result other than:

Q: first 52 of (value “UninstallString” of key “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall{1ED6CA46-633C-46CD-9D0F-2A8AE225E8A6}” of registry as string) & " /qn"

A: MsiExec.exe /X{1ED6CA46-633C-46CD-9D0F-2A8AE225E8A6} /qn

I am concerned that the number of characters in the uninstall string will not always be 52 characters.

(imported comment written by BenKus)

Hello,

The “%00” is a percent encoded null character. The easiest way to get rid of it in a general way is to use something like this:

Q: (if (it contains “%00”) then (preceding text of last “%00” of it) else it) of (value “UninstallString” of key “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall{1ED6CA46-633C-46CD-9D0F-2A8AE225E8A6}” of registry as string)

See if that works for you,

Ben

(imported comment written by kwdobbin)

Thanks, Ben. That’s what I needed. This is how I will use it.

Q: preceding text of last “%00” of (value “UninstallString” of keys whose (value “DisplayName” of it as string as lowercase contains “accounting”) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry as string)

A: MsiExec.exe /X{0DB71675-9A65-4793-98BE-F99128FB0977}

(imported comment written by kwdobbin)

Results from qna:

Q: if (exists value “UninstallString” of keys whose (value “DisplayName” of it as string as lowercase contains “tea expense reporting”) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry) then (preceding text of last “%00” of (value “UninstallString” of keys whose (value “DisplayName” of it as string as lowercase contains “travel expense accounting”) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry as string) & " /qn") else “NA”

A: NA

Why does Action fail on wait NA?

Here is the action statement:

wait {if (exists value “UninstallString” of keys whose (value “DisplayName” of it as string as lowercase contains “tea expense reporting”) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry) then (preceding text of last “%00” of (value “UninstallString” of keys whose (value “DisplayName” of it as string as lowercase contains “tea expense reporting”) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry as string) & " /qn") else “NA”}

Action fails when wait NA executes.

(imported comment written by brolly3391)

Your relevance is returning NA - which means that the software is not installed. Then you are running “wait NA” which fails. You only want the action to run on machines where the software is present. First, you need to check for existance in the relevance. Then, once it safely exists you can use it in your action.

Instead of parsing the uninstall string for the MSI PID, try using the key name directly. That way you can avoid worrying about it’s length or any null characters.

Give this a try:

RELEVANCE:

exists key whose (exists value “DisplayName” whose (it as string as lowercase = “tea expense reporting”) of it) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry

ACTION:

wait {(“MsiExec.exe /X " & name of key whose (value “DisplayName” of it as string as lowercase = “tea expense reporting”) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry & " /QN”)}

The only issue I could see with this is if there is more than one entry for “tea expense reporting” under the uninstall keys.

I am not sure what would happen if you send a plural string to the “wait” action. Does it perform the wait on each item in the list, the first item only or does it error out?

(imported comment written by JonFan)

Hi,

One nice way to handle reporting back that a condition does not exist is to use the “nothing” object instead of a string. For example, we could modify the property below to be the following:

q: if (exists value “UninstallString” of keys whose (value “DisplayName” of it as string as lowercase contains “tea expense reporting”) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry) then (preceding text of last “%00” of (value “UninstallString” of keys whose (value “DisplayName” of it as string as lowercase contains “travel expense accounting”) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry as string) & " /qn") else nothing

This will literally return nothing if the key doesn not exist. This is particularly nice in properties, as they will report in the console and will sort a little better than a literal string such as “NA”.

-Jon

(imported comment written by JonFan)

The wait command will fail when a plural result is sent to it. I believe it tries to take the entire feedback from the relevance and run it, which typically results in a failure.

-Jon

(imported comment written by kwdobbin)

The return types from the clauses after then and else must be the same; therefore, use of the nothing object will not work in this case.

(imported comment written by JonFan)

“Nothing” will actually work here as it is of type which will let it operate with other types in an if/then/else clause. If you have QnA handy, just drop in the expression I noted. You will not see an answer when you evaluate it, but if you post times as well, you’ll see that it does evaluate but returns nothing. It is a little strange, but is fairly useful.

(imported comment written by kwdobbin)

I get an error:

Q: if (name of operating system as lowercase starts with “Win”) then “yes” else nothing

E: Singular expression refers to nonexistent object.

(imported comment written by JonFan)

Hmmmm, I think you might be using an older version of QnA. In my 5.1 QnA, I get:

Q: if (name of operating system as lowercase starts with “Win”) then “yes” else nothing

E: Singular expression refers to nonexistent object.

T: 708

But in my 6.0 QnA I get:

Q: if (name of operating system as lowercase starts with “Win”) then “yes” else nothing

T: 264

Can you check the version of QnA you’re running? Thanks!

(imported comment written by kwdobbin)

My version of QnA is 5.1.1.50. Don’t think it matters because a task still errors when using the nothing object.

(imported comment written by BenKus)

brolly33’s suggestion is the right way to go.

If you add the relevance, then the action will only run if the key exists. In this case, you won’t have to use an “if” statement because you can be sure the key exists.

This is the power of the relevance+action combination.

Ben

(imported comment written by JonFan)

You can download the new version of QnA at http://support.bigfix.com/fixlet/ under the “Other Tools” section.

Regarding the wait command issue, I think brolly33’s suggestion is the way to go. If we move the detection logic out to a relevance clause in the Task and have the action run the uninstall command by itself (without the if/then/else), that should get around this issue.

(imported comment written by kwdobbin)

Relevance is in both the action and relevance beaucase I have multiple actions that I want to occur based on relevance. I did not think this was a difficult issue. Based on the suggestions this far I am forced to reveal the full complexity of what I am trying to accomplish.

This is working, but I would like to understand why a simple wait nothing or wait “nothing” command produces an error when run in a task message. I intend to use this process again in the very near future.

Action:

wait {if (exists value “UninstallString” of keys whose (value “DisplayName” of it as string as lowercase contains “tea” and value “DisplayVersion” of it as string contains “1.0.0”) of key “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry) then (preceding text of last “%00” of (value “UninstallString” of keys whose (value “DisplayName” of it as string as lowercase contains “tea” and value “DisplayVersion” of it as string contains “1.0.0”) of key “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry as string) & " /qn") else if (exists value “UninstallString” of keys whose (value “DisplayName” of it as string as lowercase contains “tea” and value “DisplayVersion” of it as string contains “1.0.0.0”) of key “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry) then (preceding text of last “%00” of (value “UninstallString” of keys whose (value “DisplayName” of it as string as lowercase contains “tea” and value “DisplayVersion” of it as string contains “1.0.0.0”) of key “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry as string) & " /qn") else if (exists value “UninstallString” of keys whose (value “DisplayName” of it as string as lowercase contains “tea expense reporting”) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry) then (preceding text of last “%00” of (value “UninstallString” of keys whose (value “DisplayName” of it as string as lowercase contains “tea expense reporting”) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry as string) & " /qn") else if (exists value “UninstallString” of keys whose (value “DisplayName” of it as string as lowercase contains “travel expense accounting”) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry) then (preceding text of last “%00” of (value “UninstallString” of keys whose (value “DisplayName” of it as string as lowercase contains “travel expense accounting”) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry as string) & " /qn") else “N/A”}

Relevance:

(name of operating system as lowercase starts with “win”) AND (exists value “UninstallString” of keys whose (value “DisplayName” of it as string as lowercase contains “tea” and value “DisplayVersion” of it as string contains “1.0.0”) of key “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry) OR (exists value “UninstallString” of keys whose (value “DisplayName” of it as string as lowercase contains “tea” and value “DisplayVersion” of it as string contains “1.0.0.0”) of key “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry) OR (exists value “UninstallString” of keys whose (value “DisplayName” of it as string as lowercase contains “tea expense reporting”) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry) OR (exists value “UninstallString” of keys whose (value “DisplayName” of it as string as lowercase contains “travel expense accounting”) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry)

(imported comment written by brolly3391)

Let’s rough out the logic.

if any of these applications are installed then uninstall them with the MSIExec.exe /X {PID} /QN command where we will retrieve the PID from the uninstall key of the registry.

tea version 1.0.0

tea version 1.0.0.0

tea expense reporting (any version)

travel expense accounting (any version)

note: since you are using contains, if the first line is true then so is the second line and the third line

So we want a fixlet that will uninstall all 4 different applications if any one of them is present. If it were my task, I would write 4 fixlets, one for each different application, but lets try and do it in one.

If you are on BES 6, just use the If Then flow control in action language to only run the wait actions that are applicable.

If you are on BES 5 then we need to get tricky with the substitution.

RELEVANCE:

exists key whose ((exists value “DisplayName” whose (it as string as lowercase contains “tea” ) of it AND exists value “DisplayVersion” whose (it as string contains “1.0.0” ) of it) OR (exists value “DisplayName” whose (it as string as lowercase contains “tea” ) of it AND exists value “DisplayVersion” whose (it as string contains “1.0.0.0” ) of it) OR (exists value “DisplayName” whose (it as string as lowercase contains “tea expense reporting” ) of it) OR (exists value “DisplayName” whose (it as string as lowercase contains “travel expense accounting” ) of it)) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry

a: true if any of the 4 applications are installed. Will be false and thus non-relevant once our action runs or if none of the applications are installed.

ACTION:

wait "MsiExec.exe /X " & {IF (exists key whose (exists value “DisplayName” whose (it as string as lowercase contains “tea”) of it AND exists value “DisplayVersion” whose (it as string contains “1.0.0”)of it) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry) THEN (name of key whose (exists value “DisplayName” whose (it as string as lowercase contains “tea”) of it AND exists value “DisplayVersion” whose (it as string contains “1.0.0”)of it) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry as string & “}”) ELSE “”} & /QN

wait "MsiExec.exe /X " & {IF (exists key whose (exists value “DisplayName” whose (it as string as lowercase contains “tea”) of it AND exists value “DisplayVersion” whose (it as string contains “1.0.0.0”)of it) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry) THEN (name of key whose (exists value “DisplayName” whose (it as string as lowercase contains “tea”) of it AND exists value “DisplayVersion” whose (it as string contains “1.0.0.0”)of it) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry as string & “}”) ELSE “”} & /QN

wait "MsiExec.exe /X " & {IF (exists key whose (exists value “DisplayName” whose (it as string as lowercase contains “tea expense reporting”) of it) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry) THEN (name of key whose (exists value “DisplayName” whose (it as string as lowercase contains “tea expense reporting”) of it) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry as string & “}”) ELSE “”} & /QN

wait "MsiExec.exe /X " & {IF (exists key whose (exists value “DisplayName” whose (it as string as lowercase contains “travel expense accounting”) of it) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry) THEN (name of key whose (exists value “DisplayName” whose (it as string as lowercase contains “travel expense accounting”) of it) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry as string & “}”) ELSE “”} & /QN

Notice the funky & “}” to double the final curly bracket on the PID if it exists. (page 10 in action guide)

Also notice that I took the MsiExec.exe /X and /QN parts out of the substitution and concatenated them instead.

When you run “MsiExec.exe /X NA /QN” on a command line, notice that the error that MSI would throw is suppressed by the /QN. But if you run “NA” at a command line it throws “Windows cannot find NA” error.

so simplified it looks like:

wait “MsiExec.exe /X “& { relevance here} &” /QN”

instead of

wait “{relevance here}”

If you do wait “MsiExec.exe /X NA /QN” then MSI exits quietly with a suppressed error and the actions continue.

If you do wait “NA” then the error is sensed up by the wait command and the actions fails.

If you already have the PIDs for the MSIs that you want to uninstall here is a slick alternative to the mess above:

RELEVANCE

(exists key “{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx1}” of it or exists key “{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx2}” of it or exists key “{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx3}” of it or exists key “{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx4}” of it) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of registry

ACTION:

wait “MsiExec.exe /X {”{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx1}}"} /QN"

wait “MsiExec.exe /X {”{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx2}}"} /QN"

wait “MsiExec.exe /X {”{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx3}}"} /QN"

wait “MsiExec.exe /X {”{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx4}}"} /QN"

Funky curly brackets again as per page 10 of action script guide…

Brolly