I am using CodeDom Compiler and Microsoft.CSharp, I am trying to embed a resource and call it. The reason I don't try to call properties is because I always get an error saying Properties does not exist in the current context. So I want to know if doing
Parameters.EmbeddedResources.Add("C:/Users/User1/Music/sample.mp3"); is actually helpful or if I should be doing it another way. This is what I have now in the compiler source:
Extract("TestCompiler", "C:/Users/User1/Downloads", "", "Music.mp3");
private static void Extract(string NameSpace, string OutputDir, string InternalPath, string ResourceName){
Assembly assembly = Assembly.GetCallingAssembly();
using (Stream s = assembly.GetManifestResourceStream(NameSpace + "." + (InternalPath == "" ? "" : InternalPath + ".") + ResourceName))
using (BinaryReader r = new BinaryReader(s))
using (FileStream fs = new FileStream(OutputDir + "\\" + ResourceName, FileMode.OpenOrCreate))
using (BinaryWriter w = new BinaryWriter(fs))
w.Write(r.ReadBytes((int)s.Length));
}
When I do this and run the compiled exe this is the exception/error I get:
Unhandled Exception: System.ArgumentNullException: Value cannot be null.
Parameter name: input
at System.IO.BinaryReader..ctor(Stream input, Encoding encoding, Boolean leaveOpen)
at TestCompiler.Program.Extract(String NameSpace, String OutputDir, String InternalPath, String ResourceName)
at TestCompiler.Program.Main(String[] args)
I also have tried doing Extract("TestCompiler", "C:/Users/User1/Downloads", "Resources", "Music.mp3"); but I get the same error.
Is calling a embedded resource possible or should I give up? I've been at this for 3 days.
To answer my own question, I had to get all of the resources by doing this:
string[] Resources = Assembly.GetExecutingAssembly().GetManifestResourceNames();
and to reference and extract them I did this:
foreach(string Resource in Resources)
WriteResources(Resources[Resource], "C:\\Test\\example.mp3");
public static void WriteResources(string Name, string Output){
using(var Resource = Assembly.GetExecutingAssembly().GetManifestResourceStream(Name))
using(var File = new FileStream(Output, FileMode.Create, FileAccess.Write))
Resource.CopyTo(File);
}
Luckily I was able to finish my project after some solid days.
Related
I have a Save ActionResult in my Controller that is set up to use StreamWriter. The code works perfectly, for saving to a file that exists.
Save Action
[HttpPost]
[ValidateInput(false)]
public ActionResult Save(string fileName, string startTemplateUrl, string html)
{
string directoryname = Path.GetDirectoryName(fileName);
string filename = Path.GetFileName(fileName);
var lines = html;
var helper = (Server.MapPath(directoryname));
using (StreamWriter outputFile = new StreamWriter(Path.Combine(helper, filename)))
{
outputFile.WriteLine(lines);
return View();
}
}
I am now working on a file creation and from what i have read you can do this with StreamWriter although when I try to implement it, it says it cannot be found. Which tells me it is looking for a file instead of creating it.
So I tried to implement this using FileInfo. It appears that it has everything it needs but just doesn't save it. Below is my latest code. It does not like the
fs.Write(lines);
I had a try catch block. on this and it had the same results. That it cannot find it.
[HttpPost]
[ValidateInput(false)]
public ActionResult Create (string fileName, string startTemplateUrl, string html)
{
string directoryname = Path.GetDirectoryName(fileName);
string filename = Path.GetFileName(fileName);
var lines = html;
var helper = (Server.MapPath(directoryname));
var file = "Test\\" + filename;
var pathString = System.IO.Path.Combine(helper, "Test\\", filename);
FileInfo fi = new FileInfo(pathString);
if (fi.Exists)
{
fi.Delete();
}
using (FileStream fs = fi.Create())
{
fs.Write(lines);
return View();
}
}
Thanks for your help!
Update:
This is the message I get. Below the message I have the actual string to the directory copied from folder explorer..
Exception thrown: 'System.IO.DirectoryNotFoundException' in mscorlib.dll
An exception of type 'System.IO.DirectoryNotFoundException' occurred in mscorlib.dll but was not handled in user code
Could not find a part of the path 'C:\Users\Scott\source\repos\HMIBuilder\HMIBuilder\Files\HMIBuider\Test\Test2.html'.
C:\Users\Scott\source\repos\HMIBuilder\HMIBuilder\Files\HMIBuilder\Test
Update:
I need to look at my code better! This is fixed.. The code at the very top works perfectly for both save and create. The problem was in the javascript code variables that i was feeding it. A Typo... If you look at the above comparison, which I did not catch myself, too many long nights I suppose, HMIBuilder is spelled HMIBuider... in the error.
using (StreamWriter outputFile = new StreamWriter(Path.Combine(path, "filename.txt")))
would create a new file, if needed.
Your problem may be the Test directory and CreateDirectory is here to help.
DirectoryInfo di = Directory.CreateDirectory(path);
If we put the writing to the file and creating directories together it could look like the following snippet.
var path = "./MyFiles/SpecialFiles";
var filename = "thisIsAVerySpecialFile.txt";
Directory.CreateDirectory(path);
//Create a new file or overwrite existing (i.e. *not* append)
using (var f = new StreamWriter(Path.Combine(path, filename)))
{
f.WriteLine("Hello world!");
}
Without Directory.CreateDirectory the code results in System.IO.DirectoryNotFoundException with 'Could not find a part of the path '(...)'.
I have tried multiple solutions on here but non of them I can get to work. All i want to do is read a text file from my resources folder rather than the actual local folder.
File name: TextFile.txt
Set to embedded resource.
"Local File" Code that works:
string[] spaces = File.ReadAllLines("C:\\Users\\a\\source\\repos\\a\\bin\\Debug\\TextFile.txt");
Current Code:
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "TextFile.txt";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
string result = reader.ReadToEnd();
}
string[] spaces = File.ReadAllLines(resourceName);
But I am getting the following error:
System.ArgumentNullException: 'Value cannot be null.
Parameter name: stream'
On this line:
using (StreamReader reader = new StreamReader(stream))
EDIT1 Tried this as per link (Why does GetManifestResourceStream returns null while the resource name exists when calling GetManifestResourceNames?) and this NULL ERROR:
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "programname.TextFile.txt";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
string result = reader.ReadToEnd();
}
string[] spaces = File.ReadAllLines(resourceName);
Same error, am I putting the namespace bit in the wrong place?
Edit 2, tried this:
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "programname.Resources.TextFile.txt";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
string result = reader.ReadToEnd();
}
string[] spaces = File.ReadAllLines(resourceName);
New error:
System.IO.FileNotFoundException: 'Could not find file 'C:\Users\a\source\repos\a\bin\Debug\programname.Resources.TextFile.txt'.'
Location of TextFile.txt
programname
Resources
TextFile.txt
Got this to work by opening Resources.resx, Setting Access Modifier to Public Then adding the file in there.
Then replaced:
string[] spaces = File.ReadAllLines("C:\\Users\\a\\source\\repos\\a\\bin\\Debug\\TextFile.txt")
With:
var resourceText = Properties.Resources.TextFile;
var Lines= resourceText.Replace("\r", "").Split('\n');
A little background:
MSDN:
If you add a resource to your project in the normal way, it will
automatically provide a typesafe wrapper for that resource.
For example, in the Solution Explorer, expand the "Properties" node
and double click the "Resources.resx" entry. Then add an image via the
"Add Resource" button. Give that resource a name, say "MyImage".
You will then be able to programmatically access that image via
"Properties.Resources.MyImage"
This is the simple and recommended way; it will let you edit the name in the resource file and will check while coding that the name is correct.
Note that the names are stripped of the extension and, as other c# names, are case-sensitive!
The other way doesn't register the resources with the .resx file but only add them to the resource folder and marks them as embedded.
To use them you can't use a code as simple as the one above. Instead you need to find out the name (Intellisense will not help you there) and them use calls to the Reflection namespace.
Note that here the names are __not_- stripped of the extension but still are case-sensitive!
Example:
If we don't know the exact name we can search in the assembly:
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var ress = assembly.GetManifestResourceNames()
.Where(x => x.Contains(somepattern)).First();
Usually the 1st way is much recommended. Typesafety and Intellisense support alone are well worth mainainting the resx file!
Now we can open a stream to read the resource:
List<string> results = new List<string>(); ;
using (Stream stream = assembly.GetManifestResourceStream(ress))
using (StreamReader reader = new StreamReader(stream))
{
while (reader.Peek()>=0) results.Add(reader.ReadLine());
}
This function will return the correct resource name for your file:
string resourceName = assembly.GetManifestResourceNames()
.Single(str => str.EndsWith("TextFile.txt"));
2nd issue:
For string[] spaces = File.ReadAllLines(resourceName);
You can't use the same resourceName (embedded resource). If you need to read text line by line use for example:
using (StreamReader reader = new StreamReader(stream))
{
while (reader.Peek() >= 0)
{
Console.WriteLine(reader.ReadLine());
}
}
I have a dll which stores image resources , font resources etc...
I have a class in the assembly which has a return method that I want to be able to pull resources from the dll and return them as an abject which I can then convert to its respective type .
here is the code I have so far.
public class GetResource
{
public static T LoadDllResource<T>(string ResourceFolder, string resourceName, string Extension, int width = 10, int height = 10)
{
Assembly myAssembly = Assembly.GetExecutingAssembly();
Stream myStream = myAssembly.GetManifestResourceStream(myAssembly.GetName().Name + "." + ResourceFolder + "." + resourceName + "." + Extension);
// convert stream to object by doing something like this (I'm not sure)
//return (T)Convert.ChangeType(EndResultOFStreamConversion, typeof(object));
}
}
and use it this way
Font SomeFont1= GetResource.LoadDllResource<Font>("Resources","Splash","ttf")
UnityEngine.Texture2D SomeImage2= GetResource.LoadDllResource<UnityEngine.Texture2D>("Resources","SnowImage","png")
Let me know if there is a problem with the question. Thanks for any help !
I am working in the Unity Engine which does not nicely support mixed assemblies using System.Drawing
You can use the Image.FromStream Method within the System.Drawing namespace to convert a stream to an image (be sure to add a reference to System.Drawing.dll to your assembly first). I'm not quite sure what you mean by 'font resources' but I'd do it this way:
public class GetResource
{
public Image GetImageFromResource(string resourceFolder, string resourceName, string extension)
{
return Image.FromStream(this.GetStreamFromResource(resourceFolder, resourceName, extension), true);
}
private Stream GetStreamFromResource(string ResourceFolder, string resourceName, string Extension)
{
Assembly myAssembly = Assembly.GetExecutingAssembly();
return myAssembly.GetManifestResourceStream(myAssembly.GetName().Name + "." + ResourceFolder + "." + resourceName + "." + Extension);
}
}
I have four resource files embedded in my C# executable, 1 python script and 3 perl scripts. I could extract all three perl scripts successfully. But I am not able to extract the python script. I tried so many ways. Could someone please have a look ? Thank you.
public static string ExtractResource(string resourceName)
{
string destFile = "";
//look for the resource name
foreach (string currentResource in System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames() )
if (currentResource.LastIndexOf(resourceName) != -1)
{
string subPath = Common_Utilities.GetTempPath() + "SCRIPTS";
bool isExists = System.IO.Directory.Exists(subPath);
if (!isExists)
System.IO.Directory.CreateDirectory(subPath);
string strFile = subPath + "\\" + resourceName;
string path = System.IO.Path.GetDirectoryName(strFile);
string rootName = System.IO.Path.GetFileNameWithoutExtension(strFile);
destFile = path + #"\" + rootName + System.IO.Path.GetExtension(currentResource);
System.IO.Stream fs = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream( currentResource ) ;
byte[] buff = new byte[fs.Length];
fs.Read(buff, 0, (int)fs.Length);
fs.Close();
System.IO.FileStream destStream = new System.IO.FileStream(destFile, FileMode.Create);
destStream.Write(buff, 0, buff.Length);
destStream.Close();
}
return destFile;
// throw new Exception("Resource not found : " + resourceName);
}
Not sure why the Python script can't be extracted.... couple points though:
I would recommend to use Path.Combine() to stick together path and file name - don't do this yourself, too many chances for error!
Since those are (text-based) scripts, you could do the whole copying much simpler:
System.IO.Stream fs = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(currentResource);
string scriptContents = new StreamReader(fs).ReadToEnd();
File.WriteAllText(destFile, scriptContents);
With this approach, you should be easily able to see in debugging whether or not the script is properly loaded from resources. If not - check your resource name etc. (is the script really set to "embedded" resource?). If you have subdirectories for your resources, be aware that the resource name will contain those subdirectories as part of the fully qualified name - but separated by a dot (.), not a backslash like a physical path!
easy way you can mod your code with
Binary files -> File.WriteAllBytes(Path, Properties.Resources.filename);
Text files -> File.WriteAllText(Path, Properties.Resources.filename);
I have a few methods which work with MemoryMappedFiles for writing/reading data. They work alright if I use simple string for file name, for example "file.mmf". However if I use full directory path the above mentioned exception is being thrown -
Exception has been thrown by the target of an invocation.
With inner exception - {"Could not find a part of the path."}. Here is how my method looks like:
public void WriteToFile(string fileName, string value)
{
string newFileName = CombineDirectory(fileName);
byte[] newValue = Encoding.UTF8.GetBytes(value);
long capacity = newValue.Length + INT_MAXVALUE_TO_BYTEARRAY_LENGTH;
using (var mmf = MemoryMappedFile.CreateFromFile(newFileName, FileMode.Create, newFileName, capacity))
{
using (var accesor = mmf.CreateViewAccessor())
{
byte[] newValueLength = BitConverter.GetBytes(value.Length);
accesor.WriteArray(0, newValueLength, 0, newValueLength.Length);
accesor.WriteArray(INT_MAXVALUE_TO_BYTEARRAY_LENGTH, newValue, 0, newValue.Length);
}
}
}
My path looks like this :
"C:\\Users\\MyUser\\Documents\\Visual Studio 2012.mmf"
And I am using
Path.Combine
The exception occurs on the first 'using' line. If I try to create a file using the same file path with
File.Create
the file is being created with no problem.
If anyone has any suggestions, that would be great.
Regards
You need to make sure that the mapName argument (i.e. the third argument in your call to CreateFromFile) is not identical to the file path. It will throw a PathNotFound exception if you do. Not really helpful in figuring out why it is failing, I agree.
So your options for choosing a map name value:
Generate some unique key, e.g. Guid.NewGuid().ToString()
Use a constant value, e.g. "MySpecialMapForThings"
Use some convention, e.g. generate a unique key that you also use for just the file name part of the mapped file.
An example for the last option:
public static Tuple<FileInfo, string> GenerateMapInfo(string mapDirectory, string fileExtension)
{
var uniqueMapName = Guid.NewGuid().ToString();
var fileName = Path.Combine(mapDirectory, Path.ChangeExtension(uniqueMapName, fileExtension));
return Tuple.Create(new FileInfo(fileName), uniqueMapName);
}
public void WriteToFile(Tuple<FileInfo, string> mapInfo, string value)
{
byte[] newValue = Encoding.UTF8.GetBytes(value);
long capacity = newValue.Length + INT_MAXVALUE_TO_BYTEARRAY_LENGTH;
using (var mmf = MemoryMappedFile.CreateFromFile(mapInfo.Item1.FullName, FileMode.Create, mapInfo.Item2, capacity))
using (var accesor = mmf.CreateViewAccessor())
{
byte[] newValueLength = BitConverter.GetBytes(value.Length);
accesor.WriteArray(0, newValueLength, 0, newValueLength.Length);
accesor.WriteArray(INT_MAXVALUE_TO_BYTEARRAY_LENGTH, newValue, 0, newValue.Length);
}
}