I have had a lot of trouble finding information on this topic and being unable to figure out the code myself I am hoping that someone can explain it once and for all. I would think this would be a more common problem.
I have an executable with a resource file in it. I want to update that resource file on the clients machine. How?
This is what I have found http://msdn.microsoft.com/en-us/library/ms648008(VS.85).aspx but obviously that is pretty confusing stuff. I have tried this but can't get it to work. I'm not sure if I am using the wrong variables or if it just can't be done in C# or what. I guess I am dumb but I have no idea how to accomplish this seemingly simple task.
What I am asking for is a no BS, easy to follow, very basic guide to updating (or creating) a file in a .exe's resource file.
Loading
Sam HobbsPosted Feb 17, 2010, 2:27 AM
"The Resource File Generator converts text (.txt or .restext) files and XML-based resource format (.resx) files to common language runtime binary (.resources) files that can be embedded in a runtime binary executable or compiled into satellite assemblies."
There is a lot more documentaton about the newer format of resources and I think it is a better investment to learn about that. Hopefully the newer formats are documented better and are more flexible.
Sean McHughPosted Feb 16, 2010, 3:12 PM
The idea behind all of this is so that the entire program comes in only one file. I could easily have program B just read from a file but I want that file to be inside of program B so that the entire program and all of its supporting files are in a single .exe.
I looked up the message compiler and I'm not sure if it's what I need. The application I presented was just a test application to try and get this working on the most basic level. However, the final application still only needs to update strings.
I couldn't find comprehensive information on the resource compiler and link editors but if they allow me to add resource data to an already compiled executable I am interested. That said, I want my friends and potential employers to be able to use program A to "create" program B so if the resource compiler and link editor must be installed on the machine that runs program A that won't really work.
I'm not positive that I need resources but they are the best idea I have come up with so far. I have also thought of just appending the data onto the end of program B and then having B read from itself to get the settings information but that won't work because if you open any .exe in notepad and change anything (and even change it back exactly how it was) you will break it. So I can't do that. Another option was to include the settings information in the executable's metadata but I think you have to include the metadata when the program is compiled not after it is compiled. Which brings me to the other thing I thought of as just having program A actually compile program B but if this program is going to be running on my friends computers and hiring managers computers it is unlikely that they will have a compiler installed on it. Yet another option that has been suggested to me is to write a PE parser which I might be able to do but like I said I can't change anything in B's .exe without breaking it permanently. So... updating the resource file of B's .exe seems to be the best option to me because every other idea has something wrong with it. At least Microsoft has some documentation on how to do it even if is no longer supported. I think it would work if I just understood what variables to provide to UpdateResource(). But I am very open to an easier solution.
A Resource-Only DLL would be another file I would have to send along with the program so that wouldn't really help.
Does that explain the problem a little better?
Sam HobbsPosted Feb 16, 2010, 12:39 PM
Are you familiar with the Message Compiler? It is an old tool that was used by Windows programs to create messages. It was used to create messages for event logs. I don't know if it is still used for managed applications. I think the Message Compiler is also used to create messages in various languages.
You can use the resource compiler to compile resources, but the link editor is needed for putting the resources into an executable, so that option might not be available; I don't know enough details about your requirements.
Are you sure you must use resources? Certainly there are more modern tools available.
Note that the "program B" can be a resource-only DLL. That does not matter much but it is the typical way of doing things in the past at least.
I know that resources are not formatted in a logical manner. Now that I know that it is only strings that you need help with, we can find help with that. I know that there are articles available that can help. For one thing, the format of string resources is often used during execution, and those samples I think would also be relevant. So please resond to the questions above here and if you still need help with updating resoruces, we can do that.
Sean McHughPosted Feb 15, 2010, 11:49 PM
I want program A to "create" program B. Program A wouldn't actually create program B though. Program B will just be in Program A's resource file. What program A actually does is accepts input for the settings of program B and then saves those settings in program B's resource file. Then program A saves the newly configured program B on the users hard drive so they have a custom copy of program B.
So I have a .exe on my desktop that when it runs it reads from message.txt in its resource file. How do I write a program to change the text in that .exe?
------------------
Here is the code I have at the moment... It will run without error but does not update anything.
using System.Text;
using System.Windows.Forms;
using Microsoft.Win32;
namespace WindowsFormsApplication1
{
static class Program
{
///
/// The main entry point for the application.
///
[STAThread]
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr BeginUpdateResource(string pFileName, bool bDeleteExistingResources);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool UpdateResource(IntPtr hUpdate, string lpType, string lpName, ushort wLanguage, IntPtr lpData, uint cbData);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool EndUpdateResource(IntPtr hUpdate, bool fDiscard);
static unsafe void Main()
{
string path = "c:\\users\\sean\\desktop\\testApp.exe";
/**/IntPtr hResource = BeginUpdateResource(path, false);
if (hResource.ToInt32() == 0)
throw new Exception("File Not Found");
string newMessage = File.ReadAllText("c:\\users\\sean\\desktop\\newMessage.txt");
Byte[] bytes = new ASCIIEncoding().GetBytes(newMessage);
GCHandle bHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
IntPtr ptr = bHandle.AddrOfPinnedObject();
ushort id = (ushort)Language.MakeLanguageID();
/**/
if (UpdateResource(hResource, "FILE", "text.txt", id, ptr, (uint)bytes.Length))
{
if (!EndUpdateResource(hResource, false))
throw new Win32Exception(Marshal.GetLastWin32Error());
}
else // unable to update resource
{
MessageBox.Show("COULD NOT UPDATE RESOURCE");
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
}
}
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
namespace WindowsFormsApplication1
{
public static class Language
{
public static int MakeLanguageID()
{
CultureInfo currentCulture = CultureInfo.CurrentCulture;
int pid = GetPid(currentCulture.LCID);
int sid = GetSid(currentCulture.LCID);
return (((ushort)pid) << 10) | ((ushort)sid);
}
public static int GetPid(int lcid)
{ return ((ushort)lcid) & 0x3ff; }
public static int GetSid(int lcid)
{ return ((ushort)lcid) >> 10; }
}
}
Sam HobbsPosted Feb 15, 2010, 4:03 PM
Do you need to be able to update the resource in a program or can you do it in an editor such as Visual Studio? That is not clear in your question. Also, what type of resource? The type of resource is likely relevant to the solution. Is it a string resiorce that needs to be updated? Or a dialog? Or is it a custom resource? Do you have the source code for the application that has the resource? I assume not, but it would help if we could establish that explicitly.