Tips/Support

  • The Old New Thing

    Stupid command-line trick: Counting the number of lines in stdin

    • 42 Comments

    On unix, you can use wc -l to count the number of lines in stdin. Windows doesn't come with wc, but there's a sneaky way to count the number of lines anyway:

    some-command-that-generates-output | find /c /v ""
    

    It is a special quirk of the find command that the null string is treated as never matching. The /v flag reverses the sense of the test, so now it matches everything. And the /c flag returns the count.

    It's pretty convoluted, but it does work.

    (Remember, I provide the occasional tip on batch file programming as a public service to those forced to endure it, not as an endorsement of batch file programming.)

    Now come da history: Why does the find command say that a null string matches nothing? Mathematically, the null string is a substring of every string, so it should be that if you search for the null string, it matches everything. The reason dates back to the original MS-DOS version of find.exe, which according to the comments appears to have been written in 1982. And back then, pretty much all of MS-DOS was written in assembly language. (If you look at your old MS-DOS floppies, you'll find that find.exe is under 7KB in size.) Here is the relevant code, though I've done some editing to get rid of distractions like DBCS support.

            mov     dx,st_length            ;length of the string arg.
            dec     dx                      ;adjust for later use
            mov     di, line_buffer
    lop:
            inc     dx
            mov     si,offset st_buffer     ;pointer to beg. of string argument
    
    comp_next_char:
            lodsb
            cmp     al,byte ptr [di]
            jnz     no_match
    
            dec     dx
            jz      a_matchk                ; no chars left: a match!
            call    next_char               ; updates di
            jc      no_match                ; end of line reached
            jmp     comp_next_char          ; loop if chars left in arg.
    

    If you're rusty on your 8086 assembly language, here's how it goes in pseudocode:

     int dx = st_length - 1;
     char *di = line_buffer;
    lop:
     dx++;
     char *si = st_buffer;
    comp_next_char:
     char al = *si++;
     if (al != *di) goto no_match;
     if (--dx == 0) goto a_matchk;
     if (!next_char(&di)) goto no_match;
     goto comp_next_char;
    

    In sort-of-C, the code looks like this:

     int l = st_length - 1;
     char *line = line_buffer;
    
     l++;
     char *string = st_buffer;
     while (*string++ == *line && --l && next_char(&line)) {} 
    

    The weird - 1 followed by l++ is an artifact of code that I deleted, which needed the decremented value. If you prefer, you can look at the code this way:

     int l = st_length;
     char *line = line_buffer;
     char *string = st_buffer;
     while (*string++ == *line && --l && next_char(&line)) {} 
    

    Notice that if the string length is zero, there is an integer underflow, and we end up reading off the end of the buffers. The comparison loop does stop, because we eventually hit bytes that don't match. (No virtual memory here, so there is no page fault when you run off the end of a buffer; you just keep going and reading from other parts of your data segment.)

    In other words, due to an integer underflow bug, a string of length zero was treated as if it were a string of length 65536, which doesn't match anywhere in the file.

    This bug couldn't be fixed, because by the time you got around to trying, there were already people who discovered this behavior and wrote batch files that relied on it. The bug became a feature.

    The integer underflow was fixed, but the code is careful to treat null strings as never matching, in order to preserve existing behavior.

    Exercise: Why is the loop label called lop instead of loop?

  • The Old New Thing

    Why doesn't the Open Files list in the Shared Folders snap-in show all my open files?

    • 30 Comments

    A customer wanted a way to determine which users were using specific files on their server. They fired up the Shared Folders MMC snap-in and went to the Open Files list. They found that the results were inconsistent. Some file types like .exe and .pdf did show up in the list when they were open, but other file types like .txt did not. The customer asked for an explanation of the inconsistency and for a list of which file types work and which ones don't.

    The customer is confusing two senses of the term open file. From the file system point of view, an open file is one that has an outstanding handle reference. This is different from the user interface concept of "There is an open window on my screen showing the contents of the file."

    The Open Files list shows files which are open in the file system sense, not in the user interface sense.

    Whether a file shows up in the Open Files list depends on the application that is used to open the file (in the user interface sense). Text files are typically opened by Notepad, and Notepad reads the entire contents of the file into memory and closes the file handle. Therefore, the file is open (in the file system sense) only when it is in the process of being loaded or saved.

    There is no comprehensive list of which types of files fall into which category because the behavior is not a function of the file type but rather a function of the application being used to view the file. (If you open a .txt file in Word, I believe it will keep the file system handle open until you close the document window.)

    The customer seemed satisfied with the explanation. They ran some experiments and observed that Hey, check it out, if I load a really big text file into Notepad, I can see it show up in the Open Files list momentarily. They never did come back with any follow-up questions, so I don't know how they went about solving the original problem. (Maybe they used a SACL to audit who was opening the files.)

  • The Old New Thing

    Starting up inside the box

    • 41 Comments

    the shell team received two customer questions about a month apart which seemed unrelated but had the same root cause.

    I found that in Windows Vista, the xcopy command is ten times slower than it was in Windows XP. What is the source of this slowdown, and how can I fix it?
    We have an application which takes a very long time to start up on Windows Vista than it did in Windows XP. We noticed that the slowdown occurs only if we set the application to autostart.

    Let's look at the second one first, since that customer provided a useful piece of information: The slowdown occurs only if they set the program to run automatically at logon. In Windows Vista, programs which are set to run automatically at logon run with reduced priority. This was done in response to the fact that application developers went angling for a bonus and decided to slow down the operating system overall in order to get their program to start up faster. To counteract this tragedy of the commons, the performance team runs these programs inside a job object with reduced CPU, I/O, and paging priority—which the performance team informally calls boxing— for 60 seconds, so that the user isn't forced to sit and wait for all these startup programs to finish doing whatever "really important" stuff they want to do.

    Okay, back to the first customer, the one who reported that xcopy was taking a long time. It took a bit of back-and-forth, but eventually the customer revealed that they were performing the xcopy in a batch file which they placed in the Startup group. Once they volunteered that information, the reason for the slowdown became obvious: Their batch file was running inside the box, and consequently ran with low-priority I/O.

    There is no way to escape the box, but it so happens that logon-triggered scheduled tasks are not placed inside a box. That's your escape hatch. Don't abuse it. (Of course, now that I've told everybody how to avoid being put in a box, everybody will now take advantage of it, because eventually, nothing is special any more.)

    Oh, and if you look more closely at the Delay_Sec setting on a Windows 7 machine, you'll see that it's set to zero, so the boxing behavior is effectively disabled on Windows 7. I guess the performance team gave up. "Fine, if you want your computer to run like a dog when it starts up, then go right ahead. I won't try to save you from yourself any more."

    Bonus chatter: You can explicitly "put yourself inside a box" by using the PROCESS_MODE_BACKGROUND_BEGIN process priority mode. Programs which are intended to run in the background with minimal impact on the rest of the system can use this mode.

  • The Old New Thing

    Why does creating a shortcut to a file change its last-modified time... sometimes?

    • 15 Comments

    A customer observed that sometimes, the last-modified timestamp on a file would change even though nobody modified the file, or at least consciously took any steps to modify the file. In particular, they found that simply double-clicking the file in Explorer was enough to trigger the file modification.

    It took a while to puzzle out, but here's what's going on:

    When you double-click a file in Explorer, Explorer adds it to the Recent Items list. Internally, this is done by creating a shortcut to the item. The nice thing about a shortcut is that it knows how to track its target. That way, if you move an item, then try to open it from the Recent Items list, the shortcut tracking code will try to find where you moved it to. You moved the file. The shortcut still works. Magic.

    Shortcut target tracking magic is accomplished with the assistance of object identifiers, and object identifiers, as we saw earlier, are created on demand the moment somebody first asks for one.

    And that's where the file modification is coming from. If the file is freshly-created, it won't have an object identifier. When you create a shortcut to it (which happens implicitly when it is added to the Recent Items list), that triggers the creation of an object identifier, which in turn updates the last-modified time on the file.

    Frustratingly, the Link­Resolve­Ignore­Link­Info and No­Resolve­Track policies do not prevent the creation of object identifiers. Those policies control whether the tracking information is used during the resolve process, but they don't control whether the tracking information is obtained during shortcut creation. (Who knows, maybe you're creating the shortcut to be used on a machine where those policies are not in effect.) To suppress collecting the volume information and object identifier at shortcut creation time, you need to pass the SLDF_FORCE_NO_LINKINFO and SLDF_FORCE_NO_LINKTRACK flags to the IShell­Link­Data­List::Set­Flags method when you create the shortcut.

  • The Old New Thing

    Why does the Shift+F10 menu differ from the right-click menu?

    • 35 Comments

    The Shift+F10 key is a keyboard shortcut for calling up the context menu on the selected item. but if you look closely, you might discover that the right-click menu and the Shift+F10 menu differ in subtle ways. Shouldn't they be the same? After all, that's the point of being a keyboard shortcut, right?

    Let's set aside the possibility that a program might be intentionally making them different, in violation of UI guidelines. For example, a poorly-designed program might use the WM_RBUTTON­UP message as the trigger to display the context menu instead of using the WM_CONTEXT­MENU message, in which case Shift+F10 won't do anything at all. Or the poorly-designed program may specifically detect that the WM_CONTEXT­MENU message was generated from the keyboard and choose to display a different menu. (This on top of the common error of forgetting to display a keyboard-invoked context menu at the currently selected item.) If somebody intentionally makes them different, then they'll be different.

    Okay, so the program is not intentionally creating a distinction between mouse-initiated and keyboard-initiated context menus. Shift+F10 and right-click both generate the WM_CONTEXT­MENU message, and therefore the same menu-displaying code is invoked. The subtle difference is that when you press Shift+F10, the shift key is down, and as we all know, holding the shift key while calling up a context menu is a Windows convention for requesting the extended context menu rather than the normal context menu.

    You get a different menu not because the program is going out of its way to show you a different menu, but because the use of the shift key accidentally triggers the extended behavior. It's like why when you look at yourself in the mirror, your eyes are always open, or why when you call your own phone number, the line is always busy. To avoid this, use the Menu key (confusingly given the virtual key name VK_APPS) to call up the context menu. (This is the key that has a picture of a menu on it, usually to the right of your space bar.) When you press that key, the code which decides whether to show a normal or extended context menu will see that the shift key is not held down, and it'll go for the normal context menu.

    Of course, you can also press Shift+AppMenu, but then you'll have come full circle.

  • The Old New Thing

    An even easier way to get Windows Media Player to single-step a video

    • 17 Comments

    Since my original article explaining how to get Windows Media Player to single-step a video, I've learned that there's an even easier way.

    • Pause the video.
    • To single-step forward, Ctrl+Click the Play button.
    • To single-step backwrd, Ctrl+Shift+Click the Play button.

    Backward-stepping is dependent upon the codec; some of them will go backward to the previous keyframe.

    The person who tipped me off to this feature: The developer who implemented it.

    Remember: Sharing a tip does not imply that I approve of the situation that led to the need for the tip in the first place.

  • The Old New Thing

    How do I compress files (via NTFS compression) from the command line?

    • 33 Comments

    A customer wanted to know whether there was a way to compress files and directories (in the sense of NTFS compression) from a script or from the command line. They knew about the Properties dialog, but they wanted something scriptable.

    The command-line tool for this is COMPACT.EXE. Type compact /? for usage information.

    The customer liaison was grateful for this information.

    Thanks for the prompt response, and yes, this will meet our customer's need to compress specific files such as *.docx under a particular directory and all its subdirectories.

    Um, *.docx files are already compressed. Compressing them again gains you nothing.

    Bonus reading: Functions for manipulating documents which follow the Open Package Conventions are available in both managed and unmanaged versions. Check out the Packaging Team Blog for more information, including a comparison of the managed and unmanaged versions.

  • The Old New Thing

    How to get Windows Media Player to single-step a video

    • 37 Comments

    I always forget how to do this, so I'm going to write it down so I can look it up later.

    When a video is playing, right-click the volume control slider and select Enhancements, then Play speed settings. (Actually, it also works if you right-click the speaker icon, the Stop button, the Replay button, or the Shuffle button, but the volume control slider is the biggest target.)

    On the Play speed settings dialog, the single-step controls are at the bottom; they look like triangles.

    Update: There's an even easier way.

  • The Old New Thing

    Why do Group Policy settings require me to have a degree in philosophy?

    • 11 Comments

    Josh points out that Group Policy settings often employ double-negatives (and what's the difference between turning something off and not configuring it)?

    Group Policy settings are unusual in that they are there to modify behavior that would continue to exist without them. They aren't part of the behavior but rather a follow-on. Suppose that the default behavior is to do XYZ automatically, but due to requests from corporate customers, a Group Policy is added to alter this behavior. The Group Policy for this might look like this:

    Don't do XYZ automatically




    The template for boolean Group Policy settings is

    Blah blah blah




    Consequently, every boolean Group Policy setting is forced into the above format, even if the setting is reverse-sense, as our sample one is. In general, the three settings for a Group Policy mean

    Enabled Change the behavior as described in the title of the group policy.
    Disabled Do not change the behavior and continue with the default behavior.
    Not configured Let somebody else decide.

    The difference between Disabled and Not configured is that when you disable a Group Policy, then you're saying "Restore default behavior." On the other hand, if you don't configure a Group Policy setting, then you're saying "I have no opinion about whether this Group Policy should be enabled or disabled, so keep looking, because there might be another Group Policy Object that does express an opinion."

    Recall that multiple Group Policy Objects can apply to a specific user. For example, a typical user may be subject to a Local Group Policy, a Non-Administrator Local Group Policy, a series of other Group Policies depending on what security groups the user belongs to, and then a User-Specified Group Policy. You can use the Resultant Set of Policy snap-in to see how all these different Group Policy Objects interact.

    The upshot of this is that Group Policy settings often end up using double negatives if the policy is to disable a default behavior. You "Enable" the setting to disable the default behavior, you "Disable" the setting to enable the default behavior, and you leave the setting "Not configured" if you want to let some other Group Policy Object decide. Even when there is a more clever way of wording the options to avoid the double negative, the people who write Group Policy descriptions are so used to double-negatives that it doesn't even occur to them that a particular setting setting permits an optimization. (Either that, or they figure that system administrators are so used to seeing double-negatives, that when it's not there, they get confused!)

  • The Old New Thing

    Why does Explorer show a thumbnail for my image that's different from the image?

    • 21 Comments

    A customer (via a customer liaison) reported that Explorer somestimes showed a thumbnail for an image file that didn't exactly match the image itself.

    I have an image that consists of a collage of other images. When I switch Explorer to Extra Large Icons mode, the thumbnail is a miniature representation of the image file. But in Large Icons and Medium Icons mode, the thumbnail image shows only one of the images in the collage. I've tried deleting the thumbnail cache, but that didn't help; Explorer still shows the wrong thumbnails for the smaller icon modes. What is wrong?

    The customer provided screenshots demonstrating the problem, but the customer did not provide the image files themselves that were exhibiting the problem. I therefore was reduced to using my psychic powers.

    My psychic powers tell me that your JPG file has the single-item image as the camera-provided thumbnail. The shell will use the camera-provided thumbnail if suitable.

    The customer liaison replied,

    The customer tells me that the problem began happening after they edited the images. Attached is one of the images that's demonstrating the problem.

    Some image types (most notable TIFF and JPEG) support the EXIF format for encoding image metadata. This metadata includes information such as the model of camera used to take the picture, the date the picture was taken, and various camera settings related to the photograph. But the one that's interesting today is the image thumbnail.

    When Explorer wants to display a thumbnail for an image, it first checks whether the image comes with a precalculated thumbnail. If so, and the thumbnail is at least as large as the thumbnail Explorer wants to show, then Explorer will use the image-provided thumbnail instead of creating its own from scratch. If the thumbnail embeded in the image is wrong, then when Explorer displays the image-provided thumbnail, the result will be incorrect. Explorer has no idea that the image is lying to it.

    Note that the decision whether to use the image-provided thumbnail is not based solely on the view. (In other words, the conclusion is not "Explorer uses the image-provided thumbnail for Large Icons and Medium Icons but ignores it for Extra Large Icons.) The decision is based on both the view and the size of the image-provided thumbnail. If the image-provided thumbnail is at least the size of the view, then Explorer will use it. For example, if your view is set to 64 × 64 thumbnails, then the image-provided thumbnail will be used if it is at least 64 × 64.

    The Wikipedia page on EXIF points out that "Photo manipulation software sometimes fails to update the embedded information after an editing operation." It appears that some major image editing software packages fail to update the EXIF thumbnail when an image is edited, which can result in inadvertent information disclosure: If the image was cropped or otherwise altered to remove information, the information may still linger in the thumbnail. This Web site has a small gallery of examples.

Page 5 of 22 (212 items) «34567»