Reputation: 8461
I'm having a problem trying to write my resource files to disk (all resource files part of the same project and assembly).
If I add
var temp = Assembly.GetExecutingAssembly().GetManifestResourceNames();
This returns a string[]
in the following format
Gener.OptionsDialogForm.resources
Gener.ProgressDialog.resources
Gener.Properties.Resources.resources
Gener.g.resources
Gener.Resources.reusable.css
Gener.Resources.other.jpg
The last 2 of the array are the only 2 files I want but I assume it's not a guarantee that this will always be the case. The array could come through in another order as code is changed so I cannot explicity call the item at a given index (temp[4]
)
So, I could do
foreach (string item in Assembly
.GetExecutingAssembly()
.GetManifestResourceNames())
{
if (!item.Contains("Gener.Resources."))
continue;
//Do whatever I need to do
}
But this is just horrible! I face another problem with this approach; This doesn't return the file name with the extension, just the Name
and as such, I have no idea what the extension is.
This is the code as it currently is
public void CopyAllFiles()
{
var files = Resources.ResourceManager.GetResourceSet(System.Globalization.CultureInfo.CurrentUICulture, true, true);
//var temp = Assembly.GetExecutingAssembly().GetManifestResourceNames();
foreach (DictionaryEntry item in files)
{
using (var resourceFileStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Gener.Resources." + item.Key.ToString() + ".css")) // this won't work, I can't hard code .css as the extension could be different
{
Stream stream = new FileStream(this.DirPath, FileMode.Create, FileAccess.Write);
resourceFileStream.CopyTo(stream);
stream.Dispose();
}
}
files.Dispose();
}
But this seems... wrong... Is this how any one else would do this, I'm sure I'm missing something and such a task is common that there is a better solution?
Upvotes: 2
Views: 994
Reputation: 8461
This was what I used! Hopefully it will help others. It feels some what hacking, but it works!
/// <summary>
/// Copies all the files from the Resource Manifest to the relevant folders.
/// </summary>
internal void CopyAllFiles()
{
var resourceFiles = Assembly.GetExecutingAssembly().GetManifestResourceNames();
foreach (var item in resourceFiles)
{
string basePath = Resources.ResourceManager.BaseName.Replace("Properties.", "");
if (!item.Contains(basePath))
continue;
var destination = this._rootFolder + "\\" + this._javaScriptFolder + "\\" + item.Replace(basePath + ".", "");
using (Stream resouceFile = Assembly.GetExecutingAssembly().GetManifestResourceStream(item))
using (Stream output = File.Create(destination))
{
resouceFile.CopyTo(output);
}
}
}
Upvotes: 1
Reputation: 942267
The resource names are predictable, you could just pass the name to the Assembly.GetManifestResourceStream() method.
More productively, Visual Studio supports a designer for this so you don't have to guess at the string you need to pass. Use Project + Properties, Resources tab. Click on the dropdown arrow of the Add Resource button and select your file. You can now refer to the resource in your code with a variable name. Like:
File.WriteAllText(path, Properties.Resources.reusable);
Do consider the so-so wisdom of copying resources to files at runtime. You get the exact same outcome by just using an installer or XCopy to copy the files just once. With the significant advantage is that those resources won't eat memory address space anymore and that you won't get in trouble when you don't have write access to the directory. Which is common with UAC enabled.
Upvotes: 3