{"id":8233,"date":"2012-02-24T07:00:00","date_gmt":"2012-02-24T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2012\/02\/24\/why-does-windows-keep-showing-the-old-indirect-strings-even-after-i-update-the-binary\/"},"modified":"2012-02-24T07:00:00","modified_gmt":"2012-02-24T07:00:00","slug":"why-does-windows-keep-showing-the-old-indirect-strings-even-after-i-update-the-binary","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20120224-00\/?p=8233","title":{"rendered":"Why does Windows keep showing the old indirect strings even after I update the binary?"},"content":{"rendered":"<p>\nIf your application uses indirect localized string resources,\nand you update the application, you may find that Windows\nkeeps using the old string from the previous version of the\napplication.\n<\/p>\n<p>\nFor example,\nsuppose that you set the localized name for a shortcut to\n<code>@C:\\Program Files\\Contoso\\Contoso.exe,-1<\/code>,\nand in version&nbsp;1 of your program,\nyou have\n<\/p>\n<pre>\nLANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL\nSTRINGTABLE\nBEGIN\n1 \"Contoso Document Services\"\nEND\nLANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL\nSTRINGTABLE\nBEGIN\n1 \"Contoso Dokumentdienste\"\nEND\n<\/pre>\n<p>\nFor version&nbsp;2, your marketing team decides that the\nprogram should really be called\n<i>Contoso Document <u>System<\/u><\/i>,\nso you change the resource file to read\n<\/p>\n<pre>\nLANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL\nSTRINGTABLE\nBEGIN\n1 \"Contoso Document System\"\nEND\nLANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL\nSTRINGTABLE\nBEGIN\n1 \"Contoso Dokumentsystem\"\nEND\n<\/pre>\n<p>\nThe user upgrades to version&nbsp;2 of your program, but the\nshortcut on the Start menu still reads\n<i>Contoso Document Services<\/i>.\nWhat&#8217;s going on?\n<\/p>\n<p>\nThe shell keeps a cache of indirect localized strings because\nloading a DLL just to read a string out of it is pretty expensive.\nThis cache is keyed by the string location specifier,\nand since your string location specifier hasn&#8217;t changed\nfrom its previous value of\n<code>@C:\\Program Files\\Contoso\\Contoso.exe,-1<\/code>,\nthe shell continues using the value it stored away in its cache,\nwhich if the user had previously been using version&nbsp;1 of your\nprogram, is the string <i>Contoso Document Services<\/i>.\n<\/p>\n<p>\nSome people, having discovered this behavior, have tried to go in\nand tinker with the shell&#8217;s internal cache of indirect localized strings,\nbut such a technique is doomed to failure because the location of that\ncache changes pretty regularly,\nand besides, it&#8217;s an internal implementation detail.\n(And even if you find it and manage to fiddle with it,\nyou only fix the problem for the current user.\nOther users will still have the stale cache entry.)\n<\/p>\n<p>\nThe best solution is to treat indirect strings as locked:\nOnce you decide what a string should say, you can&#8217;t change it.\nWhen you issue version&nbsp;2 of <code>Contoso.exe<\/code>,\nyou can create a second string\n<\/p>\n<pre>\nLANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL\nSTRINGTABLE\nBEGIN\n1 \"Contoso Document Services\" \/\/ shortcuts from version 1.0 use this\n2 \"Contoso Document System\" \/\/ shortcuts from version 2.0 use this\nEND\nLANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL\nSTRINGTABLE\nBEGIN\n1 \"Contoso Dokumentdienste\" \/\/ shortcuts from version 1.0 use this\n2 \"Contoso Dokumentsystem\" \/\/ shortcuts from version 2.0 use this\nEND\n<\/pre>\n<p>\nand have the installer for version&nbsp;2.0 create a shortcut\nwhose indirect localized string specifier is\n<\/p>\n<pre>\n@C:\\Program Files\\Contoso\\Contoso.exe,-<font COLOR=\"red\">2<\/font>\n<\/pre>\n<p>\nI admit that this method is rather clumsy and requires more attention\non the part of the developer.\nEverybody wants the &#8220;cheap&#8221; way out, where the definition of &#8220;cheap&#8221;\nis not &#8220;cheapest for the customer&#8221; but rather &#8220;cheapest for me,\nthe developer, because there&#8217;s a new episode of\n<i>Doctor Who<\/i>\ntonight and I don&#8217;t want to miss it.&#8221;\n<\/p>\n<p>\nWe saw last time that\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2012\/02\/23\/10271263.aspx\">\nthe format for indirect localized string resources<\/a>\nhas room for a comment.\nAnd it&#8217;s the comment that we can take advantage of here.\nThe shell uses the entire string location specifier as the key for\nits cache lookup, and that string <i>includes the comment<\/i>.\nTherefore, if you simply change the comment, that results in a cache\nmiss, and the shell will go and re-fetch the string.\n<\/p>\n<p><pre>\n@C:\\Program Files\\Contoso\\Contoso.exe,-1<font COLOR=\"red\">;v2<\/font>\n<\/pre>\n<p>\nBy appending a <code>;v2<\/code> to the string, you made it different\nfrom its predecessor, which means that the string cached by the\npredecessor won&#8217;t be used.\n<\/p>\n<p>\nAs I noted, this is cheap for the developer, but not necessarily\ncheap for the customer.\nSuppose the customer copied the shortcut to Contoso version&nbsp;1\nto their desktop,\nthen upgraded to version&nbsp;2.\nThe upgrade replaces the shortcut in the Start menu, but the\ncopy on the desktop remains unchanged.\nYou now have a shortcut on the desktop whose indirect string is\n<\/p>\n<pre>\n@C:\\Program Files\\Contoso\\Contoso.exe,-1\n<\/pre>\n<p>\nand a shortcut on the Start menu whose indirect string is\n<\/p>\n<pre>\n@C:\\Program Files\\Contoso\\Contoso.exe,-1;v2\n<\/pre>\n<p>\nSince the shortcut on the desktop was created while version&nbsp;1\nwas still installed on the computer,\nits name will read <i>Contoso Document Services<\/i>\nbecause that was the contents of string&nbsp;1.\nOn the other hand, the shortcut on the Start menu will read\n<i>Contoso Document System<\/i> because its use of the <code>;v2<\/code>\nforced the shell to go back and look again,\nand this time it sees the revised string.\nSo far so good.\n<\/p>\n<p>\nBut then the user does something which causes the cache to be pruned,\nlike, say,\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2006\/04\/24\/582153.aspx\">\nchanging their UI language to German<\/a>.\nThe shell says,\n&#8220;Okay, the UI language changed, I need to go reload all these\nindirect strings because MUI is going to change them to the new language.&#8221;\nThe shell sees the shortcut on the Start menu, reads string&nbsp;1\nout of <code>Contoso.exe<\/code>, and gets\n<i>Contoso Dokumentsystem<\/i>.\nThe shell then sees the shortcut on the desktop, reads string&nbsp;1\nout of <code>Contoso.exe<\/code>, and gets&#8230;\n<i>Contoso Dokumentsystem<\/i>.\nNot <i>Contoso Dokumentdienste<\/i>.\n<\/p>\n<p>\nNotice that the name of the shortcut on the desktop was silently\nupgraded to Contoso version&nbsp;2.\n<\/p>\n<p>\nEven if the user changes the language back to English in an attempt\nto get things back to the way they were, it won&#8217;t work.\nThe shell sees the shortcut on the Start menu, reads string&nbsp;1\nout of <code>Contoso.exe<\/code>, and gets\n<i>Contoso Document System<\/i>.\nThe shell then sees the shortcut on the desktop, reads string&nbsp;1\nout of <code>Contoso.exe<\/code>, and gets\n<i>Contoso Document System<\/i>,\nnot <i>Contoso Document Service<\/i>.\nThe original string from the first version of <code>Contoso.exe<\/code>\nis already gone; the only way to get it back is to reinstall\nContoso version&nbsp;1.\n<\/p>\n<p>\nBut at least you didn&#8217;t miss your TV show.\n<\/p>\n<p>\n<b>Bonus chatter<\/b>:\nThe one case I can think of where the cheap way out is\nacceptable is when you are issuing a prerelease version.\nFor your prerelease versions, you can append\n<code>;prerelease build xxxxx<\/code> to your string\nlocation specifier (where <code>xxxxx<\/code> is the build number),\nso that each time the user upgrades\nto a new build, the string is reloaded from scratch.\nThis still has the same problem described above if the user\nhas data left over from a previous build, but since it&#8217;s\na prerelease build, you can just declare that as not a\nsupported configuration.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If your application uses indirect localized string resources, and you update the application, you may find that Windows keeps using the old string from the previous version of the application. For example, suppose that you set the localized name for a shortcut to @C:\\Program Files\\Contoso\\Contoso.exe,-1, and in version&nbsp;1 of your program, you have LANGUAGE LANG_ENGLISH, [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[26],"class_list":["post-8233","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-other"],"acf":[],"blog_post_summary":"<p>If your application uses indirect localized string resources, and you update the application, you may find that Windows keeps using the old string from the previous version of the application. For example, suppose that you set the localized name for a shortcut to @C:\\Program Files\\Contoso\\Contoso.exe,-1, and in version&nbsp;1 of your program, you have LANGUAGE LANG_ENGLISH, [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/8233","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=8233"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/8233\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=8233"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=8233"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=8233"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}