4

I want to check if a particular file can be successfully "OPEN"ed via ShellExecute, so I'm attempting to use AssocQueryString to discover this.

Example:

DWORD size = 1024;
TCHAR buff[1024];  // fixed size as dirty hack for testing

int err = AssocQueryString(0, ASSOCSTR_EXECUTABLE, ".mxf", NULL ,buff , &size);
openAction->Enabled  = ((err == S_OK) || (err == S_FALSE)) && (size > 0);

Now, this almost works. If there's a registered application, I get the string.

But, there's a catch: On Vista, even if there is no registered application, It returns that the app c:\Windows\System32\shell32.dll is associated, which is the thing that brings up the 100% useless "Windows cannot open this file: Use the Web service to find the correct program?" dialog.

Obviously I want to hide that peice of cr*p from end users, but simply comparing the returned string to a constant seems like an ugly, brute-force and fragile way of doing it.

Also, hacking the registry to totally disable this dialog isn't a great idea.

What's a better option?

Roddy
  • 66,617
  • 42
  • 165
  • 277

2 Answers2

6

I always use FindExecutable() to get the registered application for a given document.

fhe
  • 6,099
  • 1
  • 41
  • 44
  • Thanks - works perfectly, and "fails" correctly if no application is registered. Kicking myself for not finding this one... – Roddy Aug 12 '09 at 14:35
  • Had to revisit this due to Samba performance issues. Posted the answer that I'm now using below. – Roddy Jul 01 '11 at 16:38
4

There is another way to do this, using the ASSOCF_INIT_IGNOREUNKNOWN option flag with AssocQueryString().

int err = AssocQueryString(ASSOCF_INIT_IGNOREUNKNOWN, ASSOCSTR_EXECUTABLE, ".mxf", NULL ,buff , &size);

This has a couple of important advantages over using FindExecutable()

  • It can work with just the file extension, while FindExecutable needs a full path to an existing file of the specified type.
  • Because it's not accessing the file, it's much faster with Samba and other network storage. Calling FindExecutable() on one file in a directory containing ~3000 files via Samba took > 1 second in my tests.
Roddy
  • 66,617
  • 42
  • 165
  • 277
  • 1
    I'm confused. You originally said you had a problem with Vista, and now you say you have a viable solution using the ASSOCF_INIT_IGNOREUNKNOWN flag, which according to MSDN was introduced with Windows 7. http://msdn.microsoft.com/en-us/library/windows/desktop/bb762471(v=vs.85).aspx – RenniePet Jul 26 '12 at 01:24
  • Yes, `AssocQueryString` is more reliable than `FindExecutable` (it also doesn't require an existing file): http://visualstudiomagazine.com/articles/2009/10/13/finding-an-associated-executable.aspx. As for the `ASSOCF_INIT_IGNOREUNKNOWN` flag, if you need pre-Win7 support I actually like your idea in the deleted answer of using some GUID as an extension to get the "no association" handler (actually that was my first thought when I saw your question). – Ohad Schneider Nov 08 '14 at 11:13