none
Using UpdateResource() to change a string resource RRS feed

  • Question

  • I am trying to change the string associated to a resouce ID using UpdateResouce(), but the string doesn't change with the code below.

    void CMainFrame::UpdateMacroFileName(UINT nID, LPCTSTR szNewName)
    {
    	TCHAR path[_MAX_PATH];
    	GetModuleFileName(NULL, path, sizeof(path));
    
    	HANDLE hRes = BeginUpdateResource(path, FALSE);
    
    	CString sNewString = szNewName;
    	int iCharCount = sNewString.GetLength() + 1;
    	LPWSTR pUnicodeString = new WCHAR[iCharCount];
    
    	wcscpy_s(pUnicodeString, wcslen(pUnicodeString), sNewString);
    
    	UpdateResource(hRes, RT_STRING, MAKEINTRESOURCE(nID), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_UK), (LPVOID*)pUnicodeString, (DWORD)wcslen(pUnicodeString) * sizeof(WCHAR));
    
    	EndUpdateResource(hRes, FALSE);
    
    	//delete[] pUnicodeString;
    
    	// Check if string is updated
    	LPCTSTR szUpdated = MAKEINTRESOURCE(nID);
    	CString strUpdated = szUpdated;
    }

    Could you please let me know any mistake in the code above? By the way I don't know why it crashes at delete[] pUnicodeString.

    Thanks in advance.

    Monday, June 17, 2019 1:33 PM

All replies

  • You can't update the resources of a running application in this manner.
    Monday, June 17, 2019 1:57 PM
  • And the posted code has some errors.  For example ,

    	LPWSTR pUnicodeString = new WCHAR[iCharCount];
    
    	wcscpy_s(pUnicodeString, wcslen(pUnicodeString), sNewString);
    

    Right after allocating the memory with new, pUnicodeString points to uninitialized memory.  So passing that pointer to wcslen is clearly an error.  You already know how many WCHARs to use -- iCharCount.

    Monday, June 17, 2019 2:26 PM
  • Hi RLWA32,

    Many thanks for your suggestion. It can fix the crash.

    void CMainFrame::UpdateMacroFileName(UINT nID, LPCTSTR szNewName)
    {
    	TCHAR path[_MAX_PATH];
    	GetModuleFileName(NULL, path, sizeof(path));
    
    	HANDLE hRes = BeginUpdateResource(path, FALSE);
    
    	CString sNewString = szNewName;
    	int iCharCount = sNewString.GetLength() + 1;
    	LPWSTR pUnicodeString = new WCHAR[iCharCount];
    
    	wcscpy_s(pUnicodeString, iCharCount, sNewString);
    
    	UpdateResource(hRes, RT_STRING, MAKEINTRESOURCE(nID), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_UK), (LPVOID*)pUnicodeString, iCharCount * sizeof(WCHAR));
    
    	delete[] pUnicodeString;
    
    	EndUpdateResource(hRes, FALSE);
    
    	// Check if string is updated
    	LPCTSTR szUpdated = MAKEINTRESOURCE(nID);
    	CString strUpdated = szUpdated;
    }

    Monday, June 17, 2019 4:21 PM
  • 	// Check if string is updated
    	LPCTSTR szUpdated = MAKEINTRESOURCE(nID);
    	CString strUpdated = szUpdated;

    That doesn't do what you think it does.  It does not actually fetch the resource.  MAKEINTRESOURCE just takes the ID number and stores it into a pointer-sized variable.  The next line will crash when the CString constructor tries to use that number as an address.  You need to use LoadString to actually fetch the string itself.


    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

    Monday, June 17, 2019 5:37 PM
  • Updating a string table is more complicated than for other resource types.

    First, read The format of string resources.

    To update a string in a string table resource you must update the "bundle" (as described in the article) that contains the targeted string.  So you must carefully copy all of the strings in the existing bundle into a new buffer, including your new string ( as a counted Unicode string) and then pass your buffer and the bundle ID to UpdateResource.

    And again, you cannot update the resource of an executing program with UpdateResource.

    Monday, June 17, 2019 7:17 PM
  •  you cannot update the resource of an executing program with UpdateResource.

    If the resource is in a separate DLL (such as produced by MUIfication), the app can unload it and then modify.  This is awful anyway ;)

    -- pa

    Tuesday, June 18, 2019 5:45 PM
  • The OP's posted code was calling -

    GetModuleFileName(NULL, path, sizeof(path));
    

    So presumably they were trying to update resources in the .exe. :)

    Tuesday, June 18, 2019 5:48 PM