Don’t be helpless: At least look at the function you’re using


Sometimes I see people ask a question and get an answer, but the answer doesn't quite work. But instead of trying to understand the answer in order to see why it doesn't work and develop a better solution, they just play stupid. Here's an example. The names have been changed but the story's the same.

How do I get a handle to a bright pink elephant? We have a dialog box that talks about elephants, and we'd like to put some information about the bright pink ones on it.

An answer came back rather quickly.

Use GetElephantHandle(EPHNT_BRIGHTPINK).

Some time later, the customer came back with a follow-up question.

I can't get it to work. I get a compiler error:

error C2065: 'EPHNT_BRIGHTPINK' : undeclared identifier

Am I missing a header file?

(So much for people knowing what to do when they get this error message.)

Don't be helpless. Your head isn't just for looks. At least pretend to try to understand what you're doing. In this case, the function is GetElephantHandle, and you're having trouble because the EPHNT_BRIGHTPINK value we want isn't defined. Why not check out the values that are defined?

#define EPHNT_DUMBO         0
#define EPHNT_BABAR         1
#define EPHNT_WHITE         2
#define EPHNT_BRIGHT_PINK   3

Wow, I bet the person who wrote EPHNT_BRIGHTPINK really meant EPHNT_BRIGHT_PINK.

Armed with this new skill, perhaps you can solve this person's problem:

Somebody recommended that I add the DS_SHELLEXT style to my property sheet dialog template to fix a sizing problem, but when I try that, I get an error that tells me that DS_SHELLEXT is not defined. Is there a file I have to include?

Comments (61)
  1. S says:

    error C8000: ‘User’ : unable to write code

  2. FlorianW says:

    If people won’t have the habit to delegate responsibility, there were no market for horoscopes.

  3. Rick C says:

    Was this a trick question?  There’s no DS_SHELLEXT.

  4. Rick C says:

    Ooh, and look at that, I’m guilty of doing the same thing. :)

  5. Rick C says:

    And I guess the fuller answer can be gleaned from here: http://blogs.msdn.com/oldnewthing/archive/2005/02/08/369090.aspx, which is to say that the user most likely wanted DS_SHELLFONT, viz, "Ah, but now there is a new flag, DS_SHELLFONT. Starting in Windows 2000, if you specify the DS_SHELLFONT dialog style for your DIALOGEX dialog template, then the dialog dimensions are taken relative to the font you specified in your template (which is probably what you wanted) rather than relative to the property sheet frame font. If you leave off the flag (as older programs will), then the property sheet measurement code remains bug-for-bug compatible with previous versions."

  6. Frogger says:

    If MSDN wasn’t so pathetic with their index nowadays, finding identifiers like this would be simpler.

    MSDN prior to 2001 was MUCH better.

    Seems that if you don’t write in Managed Code these days, you’re on your own.

  7. Adam says:

    Agreed, but don’t you sound grumpy today?

  8. Jules says:

    "If MSDN wasn’t so pathetic with their index nowadays, finding identifiers like this would be simpler."

    There’s a reason the SDK doesn’t ship with only preparsed headers.  If you don’t have ‘grep’, find a copy now.  Seriously: grepping headers is substantially faster than looking at documentation to find the name of a constant you can’t quite remember…

    From the question: "Is there a file I have to include?"

    Almost invariably.  To find out "grep [constant] [path to SDK]/include/*.h".

    If only there were an easy way of doing the same thing with symbols in libraries. :(

  9. John says:

    Of course it would help if Windows had some useful utilities… like, say, grep…

  10. John says:

    Well. You learn something new every day.

  11. baldmountain says:

    My first C# program was rgrep. :)

  12. Mike Dimmick says:

    The venerable ‘find’ command works well enough. Can’t do regular expressions, obviously, but it does work if you just need to find a string.

    Otherwise, most good editors have a find-in-files command, and many support regular expressions. All common versions of Visual Studio (6.0, 2002, 2003, 2005) have the feature, as does my favourite slim-line editor, TextPad.

    You’ve got no business operating a C++ compiler if you can’t find the definition of a macro or constant you’re using. The Platform SDK doesn’t call out where the macro or constant definitions live – only the function or structure – but they’re not that hard to find. Likewise writing P/Invoke declarations in C# or VB.

  13. Of course it would help if Windows had some useful utilities… like, say, grep…

    There’s the Cygwin tools, or if you don’t care to spend several hundred megs on downloading and installing them, you can always just look for Win32 builds of grep — there are a million of them.

    And yeah, findstr is okay, I guess, but I’m used to *nix tools.

  14. Ben Fulton says:

    You’re going to have to do a lot of grepping to find DS_SHELLEXT :)

  15. Brian says:

    I’m fond of windows grep (http://www.wingrep.com/), I even registered a copy!

    I agree, the new version of MSDN (the one that shipped with VS 2005) is almost completely worthless for C/C++ Win32 development.  I get documentation for just about everything except what I’m looking for.  Though I have a feeling this isn’t Raymond’s fault.

  16. Yes Raymond!  Get mad!  Seriously, let the Hulk out.

  17. Buxley says:

    Don’t be helpless. Your head isn’t just for looks. At least pretend to try to understand what you’re doing.

    Heh. Raymond does not suffer fools gladly. Good on him.

    -Buxley

  18. ChrisMcB says:

    “There’s a reason the SDK doesn’t ship with only preparsed headers.  If you don’t have ‘grep’, find a copy now.  Seriously: grepping headers is substantially faster than looking at documentation to find the name of a constant you can’t quite remember…”

    How does one grep for a constant who’s name they can’t quite remember? Is this like looking in a dictionary to find the correct spelling of a word you don’t remember how to spell?

    the great thing about documentation is I can usually remember the name of the function that takes the parameter I can’t remember how to spell. I can also remember how to find the documentation. Its always at http://www.google.com.

    [You don’t grep for it. You say, “Gosh, somebody told me to use this dialog style, but it’s not valid. Could be a typo. I wonder what the valid dialog styles are. Maybe the one I need is on that list.” Suppose somebody says, “Please go into the kitchen and bring me the book titled Cooking for Engineers.” You go into the kitchen and, oh no, there is no book by that name! Do you go to Book In Print and start searching for book whose names are similar to Cooking for Engineers? Or do you look at the books in the kitchen and say, “Hey, here’s The Engineer’s Cookbook, that’s probably the one they wanted.” From the comments here, I’m starting to believe you folks would start grepping through Books in Print. -Raymond]
  19. Alexei Lebedev says:

    This post strikes me as preachy, and not constructive at all. There is two lines worth of information here:

    Q: I get an error "DS_SHELLEXT is not defined". Is there a file I have to include?

    A: The define is called DS_SHELL_EXT

    The bigger problem is that searching headers for approximate bits of knowledge is not easy. IntelliSense could suggest replacements based on a partial match with one of the identifiers in the database.

  20. ChrisMcB says:

    "This post strikes me as preachy, and not constructive at all. There is two lines worth of information here:

    Q: I get an error "DS_SHELLEXT is not defined". Is there a file I have to include?

    A: The define is called DS_SHELL_EXT"

    Are you sure about that? Perhaps you should reread the post, ignore the preachy tone of it, and listen to the moral of the story.

  21. Frz says:

    What about Visual Assist X. It can check the define for you and also autocomplete it. All in all a very primitive example.

  22. Merus says:

    "If MSDN wasn’t so pathetic with their index nowadays, finding identifiers like this would be simpler."

    MSDN prior to 2001 was MUCH better."

    I chiefly use the online versions, which suffer the same problems, but can be gotten around using Google.

    It always amuses me that I’m using Google to find stuff on the MSDN site.

  23. josh says:

    Windows *does* have grep, it’s called findstr.

  24. Arlie Davis says:

    > If only there were an easy way of doing the same thing with symbols in libraries. :(

    Oh, act like a man.

    link /dump /symbols %systemroot%system32*.dll > exports.txt

    findstr /i SomeSymbol exports.txt

    You can also write a trivial shell script (yes, evne in cmd.exe’s wretched language) for dumping each DLL to a separate file, and then using "findstr /i SomeSymbol *.txt", which will give you the name of the DLL very easily.  For example:

    for %i in (%systemroot%system32*.dll) do (link /dump /exports %i >%~ni.txt)

    Then later:

    findstr /i SomeSymbol *.txt

  25. Maurits says:

    Hmmm… maybe I misinterpreted your comment.

    I read it to be "there’s no point in searching for DS_SHELLEXT – you won’t find it, it’s not there, that’s why you got the error."

    But now that I reread it, I see that you more likely meant it as "I assume the user searched for DS_SHELLEXT and didn’t find it; the logical next step from the user’s perspective would be to look for other DS_ constants"?  If so, I agree… I retract my cats-have-four-legs comment.

  26. Igor says:

    God, some people are so slow when it comes to brain activity, they would pass under the radar or read as "DEAD FISH".

  27. MadQ says:

    In Visual Studio you could also type DS_ and then hit Alt+Right for autocompletion. Alternatively, if there’s already a DS_SOMETHING in nearby code, right-click on it and select Go to definition.

    As for grep, doesn’t anyone use Indexing Service? I wrote a VS add-in to search using Indexing Service years ago. I even have separate catalogs for different SDK/DDK versions, the Rotor versions, just my projects, etc. pp.

  28. Bob says:

    Yeah, the MSDN index sucks. Pretty much any time I ask for a function like, say, GetWindowPlacement, I end up getting sent to the modified MFC version and the useless CE documentation. Anyone know how to disable WinCE documentation? (Note: Not Raymond’s fault, not implying that it is, not implying that he can go thwack the MSDE people on the head and get them to change this stupid behavior.)

  29. Cheong says:

    [quote]How does one grep for a constant who’s name they can’t quite remember? Is this like looking in a dictionary to find the correct spelling of a word you don’t remember how to spell?[/quote]

    Always find ApiViewer2004 handly for this purpose.

    Type a function name, right-click then click reference. And you have a list of constants to choose from. :)

    http://www.activevb.de/rubriken/apiviewer/index-apiviewereng.html

  30. Norman Diamond says:

    If this is the customer’s first or second time to write Windows programs, I think they deserve a bit more patience.  If they’ve been doing it for a few years then this complaint is spot-on.  It could be pretty hard to guess which situation this is, just from reading these questions in a newsgroup.

    Even for Windows-experienced programmers, it can be hard to figure out why _WIN32_WINNT has to be defined sometimes but not other times, it can be hard to figure out why right-clicking an identifier and choosing "go to definition" doesn’t do so, etc.  Then figure out which of 20 "Include" directories is the correct directory to look in, and which rat’s nest of #includes leads to the .h file that has the declaration.  It’s doable, but we should have different responses to different programmers depending on their experience.

  31. Norman Diamond says:

    Wednesday, May 09, 2007 10:48 PM by Bob

    the modified MFC version and the useless CE documentation

    What’s useless on one half of a project is crucial on the other half.  Yeah it would be nice to have that fine-grained filtering, for example "this search needs MFC and CE but not desktop Win32" etc.  But in my experience, if a search came close enough to find one of those pages in the first place, I only need one or two extra mouse clicks and an additional 10 seconds or so in order to find the other pages.

  32. An says:

    the modified MFC version and the useless CE documentation

    I always think it’s so very Microsoft that if you click on the Windows CE version of a Win32 function, it’s almost always identical to the desktop version even though Windows CE is a completely separate code base (as far as I know). If you know CWnd::ApiFunction(foo,bar) is usually either ApiFunction(m_hWnd,foo,bar) or behaves very much like it, the MFC version is ok too.

  33. Maurits says:

    It’s all very well to talk about suffering fools and whatnot, but there are two hidden assumptions here that are likely wrong.

    1) The user didn’t bother to try to solve the problem himself.

    The user may have been scouring his tree looking for DS_SHELLEXT, reading the documentation for property sheet dialog templates, and perhaps even working on other issues while he waited for a response to his email question.

    2) If I know an easy way to find the answer, finding the answer is easy.

    Finding the answer is easy *when you know what it is.*  There are any number of false clues here that are potential time sinks.

    [Obviously if you search for DS_SHELLEXT you won’t find anything; that’s why you’re getting the message “undeclared identifier” in the first place. One would hope the next step would be “Well, what dialog styles are defined?” -Raymond]
  34. Maurits says:

    > Obviously if you search for DS_SHELLEXT you won’t find anything; that’s why you’re getting the message "undeclared identifier" in the first place.

    Thank you for illustrating my point.  (As an aside, I’ve noticed that the phrases "obviously", "clearly", "it goes without saying" etc. usually precede a logic error.)

    Your argument is:

    * The user got an "undeclared identifier" message.

    * Misspelled identifiers will result in "undeclared identifier" messages.

    Therefore, the identifier was misspelled.

    This argument is flawed, though its conclusion happens to be correct in this instance.  (Obligatory "cats have four legs" analogy left to the reader.)

    > One would hope the next step would be "Well, what dialog styles are defined?"

    *A* perfectly reasonable next step, indeed.  I, too, would hope that the customer would (eventually) pursue this admirable troubleshooting strategy.

    Alas, there are many ways to be wrong, and comparatively few ways to be right…

  35. Norman Diamond says:

    Thursday, May 10, 2007 12:42 AM by An

    I always think it’s so very Microsoft that if

    you click on the Windows CE version of a Win32

    function, it’s almost always identical to the

    desktop version

    Yes Almost, Almost, Almost.  Like English and American, almost the same but just enough different to deceive you into writing something that doesn’t mean what you thought it meant.

    Even for the 75% of descriptions which are accurate, you have to read the correct page and you have to exclude your memories of what you read for the other version.  Examples:

    The parameters to a DllMain function.

    The return value of EnumWindows when you found what you were looking for.

    The return value of GetMessage when it fails.

    Bob’s wish is half-right.  Meanwhile, if you have to make one or two extra mouse clicks to get the page you really need, you’d better do it.

  36. _crn says:

    I guess what he really wants to do is fix the sizing problem of his dialog box. The sizing problem caused by less information about the used font. Measurement of the dialog box depends on the used font. The dialog box template needs information about that. This can either be through DS_SETFONT and/or DS_SHELLFONT. DS_SHELLFONT is easy to use cause it tells the system to use the system font. But whats about that DS_SHELLEXT? Just a suggestion: What he wanted to write is DS_SHELLTEXT (there is no Ext-Style that gives a solution) and what he meant is DS_SHELLFONT. But it doesnt matter.

  37. AndyB says:

    "It always amuses me that I’m using Google to find stuff on the MSDN site"

    Oh! So, so, so, true.

    I find this thread interesting in that its been hijacked by people complaining about MSDN (since 2001 !!!). Either we all jus harken back to the gold old days when help was help and not xml/html/webservice/online nonsense, or it truly has become a worse user interface over the years.

    It used to be CE links everywhere in MSDN, now its all managed stuff, and why is it every time I install it it seems to have a different underlying technology. I expect next year it’ll have a special Vista-aware UI to replace the one i’ve just gotten used to (again).

  38. Michael J says:

    Compiler error on DS_SHELLEXT occurs.

    1.  Open MSDN to CDialog.Create() or whatever you are using to create the dialog.
    2.  Look for list of valid styles.

    Phew.  Made it.  Do you guys need help tieing your shoes as well?  Windows programming is for the big boys (and girls).  Kindergarten is down the hall.

  39. DriverDude says:

    "How does one grep for a constant who’s name they can’t quite remember? Is this like looking in a dictionary to find the correct spelling of a word you don’t remember how to spell?"

    grep is better. If you only know the first and last chars:

    grep "DS_.*EXT" blah/*.h

    Visual Studio’s Find also understands regular expressions (look for the checkbox)

  40. Maurits says:

    Most index searches (MSDN, Google, etc.) work on tokens; so they wouldn’t help here, unless you knew the name of one of the other constants beforehand.  (Well, once this blog post is indexed, it might help.)

    “Find” in the correct file would work, presuming that you knew which was the correct file beforehand.

    grep/findstr for DS_ would work admirably, presuming you knew that they existed, and were confident that the “DS_” was not the misspelled part of the identifier.

    [I don’t know why everybody is so fixated on grep. Grep is not the answer. The answer is, “Gosh, what are the valid parameters here? Let me look among those.” -Raymond]
  41. BA says:

    Q: I get an error "DS_SHELLEXT is not defined".

    Is there a file I have to include?

    >

    A: The define is called DS_SHELL_EXT"’

    I thought the answer to the question would be "No, there is no file to include".

    The question is wrong.

  42. Bob says:

    In general, you can make a CE-style help page out of an ordinary Win32 document by simply removing half of the defined constants and changing all pointer types after the first to "must be NULL."

    Norman: That’s just it. I’m not wishing for fancy UI at this point, because it’ll never happen. All the filtering options that were half-right in 7.x got the axe in 8.0 because "no one used them." These days, I’m just getting increasingly tempted to learn the registry formats necessary to deindex CE documentation before I go in and start deleting files.

  43. Mikkin says:

    My usual answer to the problem of suffering fools gladly:  There are always going to be fools anyway, so the alternative of suffering them miserably is a poor choice.  Just who is going to be miserable, anyway?

    Raymond’s solution is better:  To suffer fools gleefully.  If he draws a little fire for poking fun, it only provides more opportunity to laugh at fools.

  44. Cooney says:

    [I don’t know why everybody is so fixated on grep. Grep is not the answer. The answer is, "Gosh, what are the valid parameters here? Let me look among those." -Raymond]

    It’s simple, really:

    find /usr/include -follow -name ‘*.h’ |xargs grep DS_|grep SHELL

    find, xargs, and grep are the most useful bits of unix I know of. That and custom shell scripts to plug into xargs that mostly reorder args.

  45. Rick C says:

    Cooney:  and you continue to miss the point.  IF DS_SHELLEXT appears not to exist (google returns no hits, MSDN the same) then the smartest thing to do is, as Raymond said, figure out what the actual constants that are available are, and try to figure out what the right one was, which, in this case, I assume is DS_SHELLFONT, altho Raymond never actually answered that, and to be honest, which the right constant is isn’t the point of the article; the point is the mindset of being willing to go looking for the right information, rather than hoping someone will come along and tell you.

  46. Cooney says:

    No, Rick, you’re missing this rather large point: the find thing I posted is an efficient method for locating all the DS_ stuff in the include files, with an intelligent guess at a pattern to narrow the results. I’m handing you a tool.

  47. Nawak says:

    I think the "next logical step" depends on the user. From this user’s point of view, grep is the next logical step:

    His program does not compile because of an unknown identifier => his experience tells him it is certainly because he did not include a header file (compilers like to do that to beginners, whine constantly about headers… gosh, can’t they do what I mean?? :) ) => the next step is to grep all include files to find the correct one.

    Of course at this point, when he doesn’t find anything and when google only shows the forum where he got the response, the user SHOULD start to question what he is looking for!!

    And start looking for valid identifiers, where they are defined etc.

    I tend to agree with Norman that it all depends on the experience the user has. When you begin, you usually don’t question what "experts" tell you, and that’s why you end up looking for "missing header file" instead of "list of valid identifiers which shall include the one I am looking for".

  48. Dewi Morgan says:

    I hate giving absolute solutions, because it makes people come back to me with minor questions, and I become a pre-reference resource. A friendly but slightly indirect pointer to the solution helps ensure that they read the reference, and that they read it before asking me in future. I *like* getting intelligent questions.

    "Doesn’t work, eh? Clearly it needs more ninja. Take a peek at the available constants for the function, to see if there are any containing the word ‘ninja’." Problem usually sorts itself out. This is a variant of the "blow dust out of the connector" help strategy.

    If I feel that they really need to read the page on the function, I may deliberately mis-specify the function parameters, and add "this will not work, as I do not have the function documentation in front of me: you can find the right syntax for the function in the docs, and while you’re there, check out the section on pirate-handling, too."

    All this also has the advantage that you get the reputation as a wizard. Wizards never speak in straight lines.

  49. Michael Puff says:

    The general problem is, the youth of today isn’t used to help themselves because they haven’t learned it. Instead of trying to find a solution on their own (Which might need some thinging.), they put their question in a message board. That is much easier: "Let other solve my problem." That works up to a special degree. But one day you will cross that line and then you will be lost.

    Whn I was young there was not internet, there were no message boards. How does a for loop work in BASIC? OK, go ask dad. OK, doesn’t no it, so I had to find it out myself.

    Sometimes I wonder, if the internet would break down completely, would they be able to survive? ;)

  50. Edagr Friendly says:

    How hard would it be to have a spell-checker in the compiler, so that the error includes something like: "did you mean EPHNT_BRIGHT_PINK?"  It won’t always work, and will occasionally have false positives, but would help with many typos like this.

  51. njkayaker says:

    I kind of doubt that Raymond would have no real problem with the user using grep or whatever.

    The key here is that the user should do something rather than expect other people to do all of their work.

  52. njkayaker says:

    Another value of looking at the header or the help for the function, is that you might learn more than just the answer to your question.

  53. Rick C says:

    Cooney–and now your tool, which might be of use in some cases, shows you that DS_SHELLEXT doesn’t exist.  Now what?

    Hopefully you do what I did first:  google or search MSDN, find out that there’s no such thing, and then…try to find out what the valid parameters are.  (And I’ll usually just do a search in Windows Explorer before I resort to grep, anyway.)

  54. Igor says:

    Real men don’t grep, they findstr :)

  55. Aidan Thornton says:

    Rick C: no, you’re missing the point. The command Cooney gave finds all DS_ constants, so that you can pick out the correct one. (IMO, Raymond Chen is also missing the point – sure, "Gosh, what are the valid parameters here? Let me look among those" is sensible, but how are you supposed to figure out what the valid parameters are in the first place?)

  56. Neil says:

    Cooking for Engineers and The Engineer’s Cookbook will be indexed sufficiently far apart for me not to notice the mistake, but then I’m just lazy.

  57. Fink says:

    Yeehaw, I tried the search route, but I wasn’t paying any attention when the whole "property sheet" thing was being discussed (I’m here for the zinghappy repartee in the comments section, more than the win32 stuff).

    Can ya throw me a function name so I can follow along with the bouncing ball and feel like I learned something? The docs said I should probably understand what I was doing before starting (http://msdn2.microsoft.com/en-us/library/ms652415.aspx), but what do they know? ( "Everyone knows MSDN docs are going downhill" blah blah blah :-)

  58. Sunny Lee says:

    "Real men don’t grep, they findstr"

    Real men don’t actually use Windows. Just because somthing is stupid doesn’t make it manly. It helps, though.

    Real men don’t actually use computers, they just stare at them until the computers comply out of fear.

  59. 640k says:

    > I kind of doubt that Raymond would have no real problem with the user using grep or whatever.

    >

    Raymond’s problem is that he may not embrace a utility which isn’t approved by microsoft. He probably would like the user to use grep, but cannot say that officially.

    [I like how people just make up stuff and state it as fact. -Raymond]
  60. Dean Harding says:

    Raymond’s problem is that he may not embrace a utility which isn’t approved by microsoft.

    Jealous?

  61. Cooney says:

    "Real men don’t grep, they findstr"

    Nah, those are nancyboys. Real men find|xargs grep|awk|unholy.pl before breakfast.

    [I like how people just make up stuff and state it as fact. -Raymond]

    Raymond’s still in the kernel configurator changelog, dontchaknow.

Comments are closed.