IF-Then-Else Relevance

Is there a better way to write the following relevance?

if exists file ((value of variable "ALLUSERSPROFILE" of environment) & "\Microsoft\Windows\Start Menu\Programs\xxx Customer Service\ANA Workflow.lnk") whose (sha1 of it = "6ff49f96a093096ec5ec060d910509df40a48a05") then "2.0" else if exists file ((value of variable "ALLUSERSPROFILE" of environment) & "\Microsoft\Windows\Start Menu\Programs\xxxx Customer Service\ANA Workflow.lnk") whose (sha1 of it = "75c8b9b75a23c1892c9b93031952529a5dbcc72e") then "1.0" else if exists file ((value of variable "ALLUSERSPROFILE" of environment) & "\Start Menu\Programs\xxxx Customer Service\ANA Workflow.lnk") whose (sha1 of it = "6ff49f96a093096ec5ec060d910509df40a48a05") then "2.0" else if exists file ((value of variable "ALLUSERSPROFILE" of environment) & "\Start Menu\Programs\xxxx Customer Service\ANA Workflow.lnk") whose (sha1 of it = "75c8b9b75a23c1892c9b93031952529a5dbcc72e") then "1.0" else "none"

Note that there are extra if-then-else statements to account for the difference between Windows 10 and Windows 7.

I can’t check at the moment, but I think there is an easier approach using csidl folders. These are a mapping that uses Microsoft’s ‘well-known folders’ definitions, that work across all versions of Windows. There is an MSDN article describing these constants; in the debugger you can look them up via

(it, pathnames of csidl folders(it)) of integers in (0, 255)

I believe one of those will map directly to the All User’s Start Menu folder.

1 Like

Looks like csidl folder 23 gets the path you’d need…

q: pathname of csidl folder 23
A: C:\ProgramData\Microsoft\Windows\Start Menu\Programs

Lots of different ways to do it though. You could take advantage of the fact that Windows 10 uses symlinks under the “All Users” profile, so you can reference the folder as either path (and use the Windows 7 style path alone). Substituting your query for a folder that exists on my start menu, I can refer to it either way…

q: folders ("Microsoft\Windows\Start Menu\Programs\Visual Studio 2017\Visual Studio Tools";"Start Menu\Programs\Visual Studio 2017\Visual Studio Tools") of folders (value of variable "ALLUSERSPROFILE" of environment)
A: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio 2017\Visual Studio Tools
A: C:\ProgramData\Start Menu\Programs\Visual Studio 2017\Visual Studio Tools
T: 0.362 ms
I: plural folder

As usual, there are several ways to do it. Suppose you were looking for files in some other set of folders that didn’t have a neat, direct mapping to csidl folders? The original statement can still be simplified (again, using a file that exists on my system instead):

q: (if exists files "Debuggable Package Manager.lnk" whose (sha1 of it = "e018eed217fb176c1241454b49b81139fda41d10") of it then "2017" else if exists files "Debuggable Package Manager.lnk" whose (sha1 of it = "xxxxx") of it then "2016" else "None") of folders ("Microsoft\Windows\Start Menu\Programs\Visual Studio 2017\Visual Studio Tools";"Start Menu\Programs\Visual Studio 2017\Visual Studio Tools") of folders (value of variable "ALLUSERSPROFILE" of environment)
A: 2017
A: 2017
T: 0.661 ms
I: plural string

I get a duplicate entry because I can actually find the file at both paths. If the file doesn’t exist, but the path does, I’d get “none”. If the folder didn’t exist at all, I’d get an empty result.

Maybe I don’t want the duplicates…I could substitute prefix “unique values of”. What if an empty result isn’t sufficient, and I really need the explicit “none” result? I can load the results in a set and check the size of it, to handle both cases.

q: (if size of it = 0 then "none" else elements of it ) of set of (if exists files "Debuggable Package Manager.lnk" whose (sha1 of it = "e018eed217fb176c1241454b49b81139fda41d10") of it then "2017" else if exists files "Debuggable Package Manager.lnk" whose (sha1 of it = "xxxxx") of it then "2016" else "None") of folders ("Microsoft\Windows\Start Menu\Programs\Visual Studio 2017\Visual Studio Tools";"Start Menu\Programs\Visual Studio 2017\Visual Studio Tools") of folders (value of variable "ALLUSERSPROFILE" of environment)
A: 2017
T: 0.727 ms
I: plural string

In fact, taking advantage of the fact that a missing folder causes the ( if ) block to not evaluate at all, and an empty result leads a set of size 0 and a result of “none”, we can shorten the if block a bit, moving the filename out of the block (if it doesn’t exist, our set size is still 0 and we still get the ‘none’):

q: (if size of it = 0 then "none" else elements of it ) of set of (if sha1 of it = "e018eed217fb176c1241454b49b81139fda41d10" then "2017" else if sha1 of it = "xxxxx" then "2016" else nothing) of files "Debuggable Package Manager.lnk" of folders ("Microsoft\Windows\Start Menu\Programs\Visual Studio 2017\Visual Studio Tools";"Start Menu\Programs\Visual Studio 2017\Visual Studio Tools") of folders (value of variable "ALLUSERSPROFILE" of environment)
A: 2017
T: 0.697 ms
I: plural string

Another option is to remove the ’ ( if ) ’ block entirely, and build a whose() clause to compare the file sha1 to a list of known sha1 values, and return only the version/description matching that sha1; this makes it a bit easier to add more versions later by preventing the if/then/elseif/then/else from grown too much…this is actually the form I think I’d prefer, now that I look at it a little more closely, as it’s easier to extend.

q: (if size of it = 0 then "none" else elements of it ) of set of items 0 of (("2017", "e018eed217fb176c1241454b49b81139fda41d10", it); ("Other Version", "xxxxx", it )) whose (item 2 of it = item 1 of it) of sha1s of files "Debuggable Package Manager.lnk"  of folders ("Microsoft\Windows\Start Menu\Programs\Visual Studio 2017\Visual Studio Tools";"Start Menu\Programs\Visual Studio 2017\Visual Studio Tools") of folders (value of variable "ALLUSERSPROFILE" of environment)
A: 2017
T: 0.715 ms
I: plural string
2 Likes

Thank Jason! It works and helps me to understand relevance a little better, but I have a long way to go before I could come up with this on my own. Here is what I ended up with based on your preferable solution.

(if size of it = 0 then "none" else elements of it) of set of items 0 of (("1.0", "75c8b9b75a23c1892c9b93031952529a5dbcc72e", it) ; ("2.0", "6ff49f96a093096ec5ec060d910509df40a48a05", it)) whose (item 2 of it = item 1 of it) of sha1s of files "ANA Workflow.lnk" of folders ("Microsoft\Windows\Start Menu\Programs\XXXXXX Customer Service") of folders (value of variable "ALLUSERSPROFILE" of environment)

Using csidl makes it even more concise.

(if size of it = 0 then "none" else elements of it) of set of items 0 of (("1.0", "75c8b9b75a23c1892c9b93031952529a5dbcc72e", it) ; ("2.0", "6ff49f96a093096ec5ec060d910509df40a48a05", it)) whose (item 2 of it = item 1 of it) of sha1s of files "ANA Workflow.lnk" of folder (pathname of csidl folder 23 & "\XXXXXXX Customer Service")

I did not know we had an inspector for CSIDL folders. This one goes into my permanent collection!

1 Like