how to programmatically get a list of resource file names in solution explorer [modified]
-
If my C# code knows the name and path of a resource file in the solution explorer, I know how to read the resource file into a byte[] and then write it out somewhere else in the file system. In otherwords, export the resource file. But suppose all I know in code is the path to a folder in the solution explorer, for example Resources/InterestingFiles. How can I iterate through all the resource file names in that solution folder? If I could do that, I wouldn't need a hard-coded list of files embedded in my C# code, but could just iterate through a list of names and export all of them somewhere into the file system. I don't want a bunch of resource file names hard-coded in my C# code. I want a nice, tight loop where I can get one resource file name after another, something like the System.IO.Directory.GetFiles() static function within .NET that returns a string[] object containing all the file names within a directory.
modified on Saturday, April 3, 2010 6:08 AM
-
If my C# code knows the name and path of a resource file in the solution explorer, I know how to read the resource file into a byte[] and then write it out somewhere else in the file system. In otherwords, export the resource file. But suppose all I know in code is the path to a folder in the solution explorer, for example Resources/InterestingFiles. How can I iterate through all the resource file names in that solution folder? If I could do that, I wouldn't need a hard-coded list of files embedded in my C# code, but could just iterate through a list of names and export all of them somewhere into the file system. I don't want a bunch of resource file names hard-coded in my C# code. I want a nice, tight loop where I can get one resource file name after another, something like the System.IO.Directory.GetFiles() static function within .NET that returns a string[] object containing all the file names within a directory.
modified on Saturday, April 3, 2010 6:08 AM
-
If my C# code knows the name and path of a resource file in the solution explorer, I know how to read the resource file into a byte[] and then write it out somewhere else in the file system. In otherwords, export the resource file. But suppose all I know in code is the path to a folder in the solution explorer, for example Resources/InterestingFiles. How can I iterate through all the resource file names in that solution folder? If I could do that, I wouldn't need a hard-coded list of files embedded in my C# code, but could just iterate through a list of names and export all of them somewhere into the file system. I don't want a bunch of resource file names hard-coded in my C# code. I want a nice, tight loop where I can get one resource file name after another, something like the System.IO.Directory.GetFiles() static function within .NET that returns a string[] object containing all the file names within a directory.
modified on Saturday, April 3, 2010 6:08 AM
-
Hi, When I tried to place files within a subfolder as you are suggesting they were not embedded into the assembly. Have you examined your assembly with a hex editor to see what you have in there? Alan.
Alan N wrote:
When I tried to place files within a subfolder as you are suggesting they were not embedded into the assembly.
I presume you set the resource file's Build Action to Embedded Resource, or at least Resource. If so, it will certainly be there.
Alan N wrote:
Have you examined your assembly with a hex editor to see what you have in there?
Don't need to do that because I know they're there. I have a list of them embedded in the code and use the following code to successfully get at them and then export them to the file system:
Uri uri = new Uri("Resources/" + resourceFile, UriKind.Relative);
StreamResourceInfo sri = Application.GetResourceStream(uri);
Stream componentStream = sri.Stream;I just don't want to have to remember to update that hard-coded list every time I add a new file to the Resources folder. It should be enough to put them into the folder through the solution explorer and set the Build Action to Resource. You shouldn't have to do anything more than that. My request in asking for help is, how can I pull out a list of relative paths so I can build the Uri for each embedded resource without hard coding the list in my C# code? I've subsequently done a lot of sifting through MSDN on various classes such as Assembly, looking for something that would give me a collection of paths like Resources/InterestingFile but I haven't found anything that does the job.
-
Been there, done that. The array I got back had one entry in it: the path of my executable.
-
Been there, done that. The array I got back had one entry in it: the path of my executable.
that does not fit the name of the method, nor my earlier experience with it. I suggest you show actual code and give a detailed problem description. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
-
that does not fit the name of the method, nor my earlier experience with it. I suggest you show actual code and give a detailed problem description. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
Okay, my memory failed me slightly. It must have been one of my other experiments that returned the name of my executable. However, I did try the one you suggested and it didn't return anything obviously useful either. It returned the following two strings: PhdBetaInstall.g.resources PHDInstallation.Properties.Resources.resources What am I supposed to do with those? I want strings returned like this: Resources/InterestingFile1.dll Resources/InterestingFile2.dll etc. etc. To get those, I'd have two DLL's embedded with the specified names. Now maybe you can tell me what I'm supposed to do with the two strings that GetManifestResourceNames() did return that would produce what I want. But the MSDN reference you provided wasn't very helpful and I'd found it and tried it before starting this thread. The code that produced the two strings from GetManifestResourceNames() is the following:
Assembly assembly = Assembly.GetExecutingAssembly();
string[] resourceNames = assembly.GetManifestResourceNames(); -
Okay, my memory failed me slightly. It must have been one of my other experiments that returned the name of my executable. However, I did try the one you suggested and it didn't return anything obviously useful either. It returned the following two strings: PhdBetaInstall.g.resources PHDInstallation.Properties.Resources.resources What am I supposed to do with those? I want strings returned like this: Resources/InterestingFile1.dll Resources/InterestingFile2.dll etc. etc. To get those, I'd have two DLL's embedded with the specified names. Now maybe you can tell me what I'm supposed to do with the two strings that GetManifestResourceNames() did return that would produce what I want. But the MSDN reference you provided wasn't very helpful and I'd found it and tried it before starting this thread. The code that produced the two strings from GetManifestResourceNames() is the following:
Assembly assembly = Assembly.GetExecutingAssembly();
string[] resourceNames = assembly.GetManifestResourceNames();code such as:
Module module=type.Module; Assembly assembly=module.Assembly; log("Embedded resources for assembly "+assembly.ToString()); string\[\] sa=assembly.GetManifestResourceNames(); foreach (string s in sa) log(" "+s);
shows a list of embedded resources, i.e. data structures that reside inside an EXE or DLL (in this case the one holding the definition for Type type). The result could be:
Explorer.resources.winLP.jpg Explorer.resources.LPExplorer.ico
Such information can be used like so to instantiate an object:
Bitmap bitmap=new Bitmap(type, resourceName); Icon icon=new Icon(type, resourceName);
One way of getting such resources into your EXE/DLL file is by adding image/icon/whatever files to your solution, then setting their "Build Action" property to "Embedded Resource". Your solution might contain other files as well, those would not become resources and not be listed by GetManifestResourceNames(). EXE and DLL files themselves are not considered resources. Also, you can add any file you want to a solution, even ones not needed for a successful build; and the resulting EXE/DLL typically does not know at all what files were used to get built. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
-
code such as:
Module module=type.Module; Assembly assembly=module.Assembly; log("Embedded resources for assembly "+assembly.ToString()); string\[\] sa=assembly.GetManifestResourceNames(); foreach (string s in sa) log(" "+s);
shows a list of embedded resources, i.e. data structures that reside inside an EXE or DLL (in this case the one holding the definition for Type type). The result could be:
Explorer.resources.winLP.jpg Explorer.resources.LPExplorer.ico
Such information can be used like so to instantiate an object:
Bitmap bitmap=new Bitmap(type, resourceName); Icon icon=new Icon(type, resourceName);
One way of getting such resources into your EXE/DLL file is by adding image/icon/whatever files to your solution, then setting their "Build Action" property to "Embedded Resource". Your solution might contain other files as well, those would not become resources and not be listed by GetManifestResourceNames(). EXE and DLL files themselves are not considered resources. Also, you can add any file you want to a solution, even ones not needed for a successful build; and the resulting EXE/DLL typically does not know at all what files were used to get built. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
Just a quick reply to this. I'll get back to a full response to your post later. I just want to note that it is precisely EXE and DLL files that I'm adding to my Resources folder that I want to export, because I'm "rolling my own" installation program, and the installation program has all the installation files of the application being installed embedded as resources so that I can distribute a single executable file that exports all the DLL and EXE files to the installation folder of the application being installed. So I'm not sure how this relates to this statement of yours. Perhaps you can elaborate:
Luc Pattyn wrote:
EXE and DLL files themselves are not considered resources.
-
Alan N wrote:
When I tried to place files within a subfolder as you are suggesting they were not embedded into the assembly.
I presume you set the resource file's Build Action to Embedded Resource, or at least Resource. If so, it will certainly be there.
Alan N wrote:
Have you examined your assembly with a hex editor to see what you have in there?
Don't need to do that because I know they're there. I have a list of them embedded in the code and use the following code to successfully get at them and then export them to the file system:
Uri uri = new Uri("Resources/" + resourceFile, UriKind.Relative);
StreamResourceInfo sri = Application.GetResourceStream(uri);
Stream componentStream = sri.Stream;I just don't want to have to remember to update that hard-coded list every time I add a new file to the Resources folder. It should be enough to put them into the folder through the solution explorer and set the Build Action to Resource. You shouldn't have to do anything more than that. My request in asking for help is, how can I pull out a list of relative paths so I can build the Uri for each embedded resource without hard coding the list in my C# code? I've subsequently done a lot of sifting through MSDN on various classes such as Assembly, looking for something that would give me a collection of paths like Resources/InterestingFile but I haven't found anything that does the job.
Hi again, Yes setting the build action to embedded resource does make a difference. With the source file structure of
Resources (directory)
hidden (directory)
file1.txt
file2.txt
TfDll.dll
file3.txt
file4.txtThe following code
private void ShowResources2() {
Assembly a = Assembly.GetEntryAssembly();
foreach (String s in a.GetManifestResourceNames()) {
Console.WriteLine("NAME {0}", s);
if (s.Contains("TfDll.dll")) {
using (Stream rs = a.GetManifestResourceStream(s)) {
using (FileStream fs = File.Create("TfDll2.dll")) {
Byte[] buff = new Byte[8192];
Int32 read;
while ((read = rs.Read(buff, 0, buff.Length)) > 0) {
fs.Write(buff, 0, read);
}
}
}
}
}
}outputs
NAME TfSync.MainForm.resources
NAME TfSync.Properties.Resources.resources
NAME TfSync.Resources.file3.txt
NAME TfSync.Resources.file4.txt
NAME TfSync.Resources.hidden.file1.txt
NAME TfSync.Resources.hidden.file2.txt
NAME TfSync.Resources.hidden.TfDll.dllwhere TfSync and MainForm are the project's namespace and form. I also recreate an identical copy of TfDll.dll as TfDll2.dll. Alan.
-
Hi again, Yes setting the build action to embedded resource does make a difference. With the source file structure of
Resources (directory)
hidden (directory)
file1.txt
file2.txt
TfDll.dll
file3.txt
file4.txtThe following code
private void ShowResources2() {
Assembly a = Assembly.GetEntryAssembly();
foreach (String s in a.GetManifestResourceNames()) {
Console.WriteLine("NAME {0}", s);
if (s.Contains("TfDll.dll")) {
using (Stream rs = a.GetManifestResourceStream(s)) {
using (FileStream fs = File.Create("TfDll2.dll")) {
Byte[] buff = new Byte[8192];
Int32 read;
while ((read = rs.Read(buff, 0, buff.Length)) > 0) {
fs.Write(buff, 0, read);
}
}
}
}
}
}outputs
NAME TfSync.MainForm.resources
NAME TfSync.Properties.Resources.resources
NAME TfSync.Resources.file3.txt
NAME TfSync.Resources.file4.txt
NAME TfSync.Resources.hidden.file1.txt
NAME TfSync.Resources.hidden.file2.txt
NAME TfSync.Resources.hidden.TfDll.dllwhere TfSync and MainForm are the project's namespace and form. I also recreate an identical copy of TfDll.dll as TfDll2.dll. Alan.
Thanks, Alan. The reason my first attempt didn't work was because I had the Build Action of my resource files set to Resource and not Embedded Resource (an oversight on my part). When I made that change, The following code worked for me:
// Generate the list of installation files.
InstallationFiles = new List<string>();
Assembly a = Assembly.GetEntryAssembly();
foreach (String s in a.GetManifestResourceNames())
{
if (s.StartsWith("PHDInstallation.Resources."))
{
string fileName = s.Replace("PHDInstallation.Resources.", "");
InstallationFiles.Add(fileName);
}
}