Store files in C# EXE file - c#

It is actually useful for me to store some files in EXE to copy to selected location.
I'm generating HTML and JS files and need to copy some CSS, JS and GIFs.
Snippet
System.IO.File.WriteAllBytes(#"C:\MyFile.bin", ProjectNamespace.Properties.Resources.MyFile);
doesn't work for me!
On "WriteAllBytes" it says:
"cannot convert from 'System.Drawing.Bitmap' to 'byte[]'"
for image and
"cannot convert from 'string' to 'byte[]'"
for text file.
Help!
UPDATE: Solved below.

Add the files you want to your solution and then set their Build Action property to Embedded Resource. This will embed the file into your exe. (msdn)
Then you just need to write the code to write the file out to disk when the exe is executed.
Something like:
File.Copy("resource.bmp", #"C:\MyFile.bin");
Replace resource.bmp with your file name.
Addendum:
If you keep the file in a sub-folder in your solution you need to make the sub-folder part of the path to resource.bmp. Eg:
File.Copy(#"NewFolder1\resource.bmp", #"C:\MyFile.bin");
Also, you may need to set the Copy To Output Directory property to Copy Always or Copy If Newer.

I assume you added the files through the Project Properties window. That does not allow you to add an arbitrary file but it does support TextFiles, Bitmaps and so on.
For an embedded TextFile, use
File.WriteAllText(#"C:\MyFile.bin", Properties.Resources.TextFile1);
For an Image, use
Properties.Resources.Image1.Save(#"C:\MyFile.bin");

You can embed binary files in a .resx file. Put them in the Files section (it looks like you used the Images section instead). It should be accessible as an array of bytes if your .resx file generates a .Designer.cs file.
File.WriteAllBytes(#"C:\foobar.exe", Properties.Resources.foobar);

Add files to project resources and set their "Build Action" as "Embedded Resource".
Now extract any file (text or binary) using this snippet:
WriteResourceToFile("Project_Namespace.Resources.filename_as_in_resources.extension", "extractedfile.txt");
public static void WriteResourceToFile(string resourceName, string fileName)
{
int bufferSize = 4096; // set 4KB buffer
byte[] buffer = new byte[bufferSize];
using (Stream input = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
using (Stream output = new FileStream(fileName, FileMode.Create))
{
int byteCount = input.Read(buffer, 0, bufferSize);
while (byteCount > 0)
{
output.Write(buffer, 0, byteCount);
byteCount = input.Read(buffer, 0, bufferSize);
}
}
}
Don't know how deep is it correct according to this article: http://www.yoda.arachsys.com/csharp/readbinary.html
but it works.

Related

Generating a zipOutputstream from a folder having other .zip files in it

I am trying to convert an entire azure blob storage folder and its contents to a zip file .Inside this folder ,I have different types of files eg, .txt,.mp3,.zip files .But once the folder is converted to zip file I noticed that all the .zip file types got corrupted,.How can I prevent my zip files from corrupted. I am using Ionic.Zip library to generate zip files
Here is the code I am using .Here I am able to generate and download the zip file successfully with all other filetypes except the inner zip files.
var allFiles = directory.ListBlobs(new BlobRequestOptions { UseFlatBlobListing = true }).Where(x => x.GetType() == typeof(CloudBlockBlob)).Cast<CloudBlob>();
string xyzblob = directory.Uri.ToString().TrimEnd('/');
var dBlob = blobClient.GetBlobReference(xyzblob);
byte[] fileBytes = null;
fileBytes = dBlob.DownloadByteArray();
foreach (var file in allFiles)
{
using (var fileStream = new MemoryStream(fileBytes))
{
var entryName = file.Uri.ToString().Replace(directory.Uri.ToString(), "");
zipOutputStream.PutNextEntry(entryName);
fileStream.Seek(0, SeekOrigin.Begin);
int count = fileStream.Read(fileBytes, 0, fileBytes.Length);
while (count > 0)
{
zipOutputStream.Write(fileBytes, 0, count);
count = fileStream.Read(fileBytes, 0, fileBytes.Length);
if (!Response.IsClientConnected)
{
break;
}
Response.Flush();
}
fileStream.Close();
}
}
zipOutputStream.Close();
More details
I am downloading a folder ,."myFolder" and its contents from azure blob as a zip file eg, myfolders.zip.
Here is how the file structure inside "myFolder" /azure blob
MyFolder/mymusic/ test.mp3
MyFolder/mytext/ newtext.txt
MyFolder/MyZipfiles/ myzip.zip
My code I posted above will generate a zip all the contents of the folder to create "MyFolder.zip" and will download automatically .Now if you unzip "MyFolder.zip" file , due to some reason , the myzip.zip is getting corrupted.If I try to open myzip.zip file ,its showing a message "windows cannot open the folder ,the compressed zipped folder "myzip.zip" is invalid"
Please help me find a solution so that the .zip files wont get corrupted
I tried to download to stream ,but same results.,The inner zip files are getting corrupted.all other file types are in good shape.
zipOutputStream.PutNextEntry(entryName);
destBlob.DownloadToStream(zipOutputStream);
I am assuming you already tried downloading one of those zip files and opening it, right?
If that is the case, one thing I would suggest is to eliminate the intermediate fileBytes array completely. Using fileBytes as the buffer to fileStream and then reading from fileStream to fileBytes might be the culprit. On the other hand, you start from offset 0 and write to the beginning of fileBytes anyway, so it might be working just fine.
In any case, a more efficient solution is; you can call PutNextEntry and then call the blob object's DownloadToStream method by passing in the zip stream itself. That would simply copy the entire blob directly into the zip stream without having to manage an intermediate buffer.
When it starts to pick the .zip file ,I added BlobReference to .zip file and this resolved the issue
dBlob = blobClient.GetBlobReference(entryName.EndsWith(".zip") ? file.Uri.ToString() : xyzblob);
zipOutputStream.PutNextEntry(entryName);
dBlob.DownloadToStream(zipOutputStream);

Clarification on Build Action

I have a project that uses an Access DB file for reference tables. This is to be used at work, but I am developing it at home. Up until now, I've simply run the debugger in VS2010, then copied the relevant class files, exe, etc from the /bin folder to a flash drive, and it's worked fine. But with the DB added in, it suddenly crashes on launch.
I know the problem is the file location of the DB file. Originally the Build Action of the DB was sent to Content. I have changed it to Embedded Resource, which as far as I understand means it will be part of the exe file now.
Am I correct in this? If not, what option do I need to select to have the DB become just a compiled part of the exe, or one of the other dll's?
If the db file is embedded, you can't access it to add/removes rows etc.
Why did you change the build action to Embedded Resource ? It'll be better to put as Content, so the db is a separate file than the exe (but still in the same directory), and then build the path to the db file (i.e. using Application.StartupPath).
Anyway, if you want to set it as Embedded you'll need to extract the db at runtime and store it somewhere before using it.
Here is a method that can extract a file from the embedded resources (of course you'll need to change the filename, or pass it as argument):
private void ExtractFromAssembly()
{
string strPath = Application.LocalUserAppDataPath + "\\MyFile.db";
if (File.Exists(strPath)) return; // already exist, don't overwrite
Assembly assembly = Assembly.GetExecutingAssembly();
//In the next line you should provide NameSpace.FileName.Extension that you have embedded
var input = assembly.GetManifestResourceStream("MyFile.db");
var output = File.Open(strPath, FileMode.CreateNew);
CopyStream(input, output);
input.Dispose();
output.Dispose();
System.Diagnostics.Process.Start(strPath);
}
private void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[32768];
while (true)
{
int read = input.Read(buffer, 0, buffer.Length);
if (read <= 0)
return;
output.Write(buffer, 0, read);
}
}
The file will be copied in the local application path, in the user directory. It'll be done the first time the app is started, because otherwise the db file will be overwritten each time the application start (overwritten with the clean db package in the exe)

Adding resources(XML) to DLL in C#

I have follow project structure
/build-out/MyApp.dll
/dependencies/ResFile.xml
/src/MyFile.cs
In MyFile.cs I want to open mine ResFile.xml that is in /dependencies directory and read it for some needs. All works like a charm in Visual Studio but when I make an dll and use it with another apps(as external library) I get an error because it can't find dependencies/ResFile.xml file.
So, how resorce file can be added to result MyApp.dll file?
There are a few articles on StackOverflow about it, but some quick notes and code ...
Make sure you mark the file as an "Embedded Resource" in the properties under Build Action.
I am using some code to read html files from a DLL and this is roughly how I get it into a string. Gives you the general idea I hope.
foreach (string resource in Assembly.GetExecutingAssembly().GetManifestResourceNames())
{
if (resource.EndsWith("Snippet.htm"))
{
Stream s = Assembly.GetExecutingAssembly().GetManifestResourceStream(resource);
byte[] buff = new byte[s.Length];
s.Read(buff, 0, buff.Length);
string snippet = Encoding.UTF8.GetString(buff);
}
}

Embed a Word Document in C#

I want to open a MS Word document from my program. At the moment, it can find it when in designer mode but when i publish my program it can't find the file. I believe I need to embed it into my program but I don't know how to do this. This is my current code to open the document:
System.Diagnostics.Process.Start("Manual.docx");
I think the Word document needs to be embedded into the resources of the .exe but i don't know how to to do this.
Can anyone help with some suggestions?
Aaron is pretty right on adding an embedded resource. Do the following to access an embedded resource:
Assembly thisAssembly;
thisAssembly = Assembly.GetExecutingAssembly();
Stream someStream;
someStream = thisAssembly.GetManifestResourceStream("Namespace.Resources.FilenameWithExt");
More info here:
How to embed and access resources by using Visual C#
Edit: Now to actually run the file you will need to copy the file in some temp dir. You can use the following function to save the stream.
public void SaveStreamToFile(string fileFullPath, Stream stream)
{
if (stream.Length == 0) return;
// Create a FileStream object to write a stream to a file
using (FileStream fileStream = System.IO.File.Create(fileFullPath, (int)stream.Length))
{
// Fill the bytes[] array with the stream data
byte[] bytesInStream = new byte[stream.Length];
stream.Read(bytesInStream, 0, (int)bytesInStream.Length);
// Use FileStream object to write to the specified file
fileStream.Write(bytesInStream, 0, bytesInStream.Length);
}
}
Right click the folder where you want to store the file within the Solution and choose Add -> Existing Item.
Once you add the file you can change the Build Action of the file within your project to be an Embedded Resource, versus a Resource. This can be done by going to the Properties within VS of the file and modifying the Build Action property.
Just include it to your project (add existing item) and from the menu that opens, select all files and select your word document. Also Copy the document into your Bin/Debug folder. If you are using an installer, include the document in the installer and it should work.

File.Copy and WPF

I have a little problem with the File.Copy method in WPF, my code is very simple and I get an exception when I run it,
Could not find a part of the path 'Images\37c31987-52ee-4804-8601-a7b9b4d439fd.png'.
where Images is a relative folder.
Here is my code, as I said simple and the same code works fine in a console application, no problem at all.
string filenamae = System.IO.Path.Combine(images, Guid.NewGuid().ToString() + System.IO.Path.GetExtension(imageFile)); ;
System.IO.File.Copy(imageFile, filenamae);
this.ImageLocation = string.Empty;
So if any can help, thanks.
Does the images folder exist? File.Copy doesn't create it automatically.
Do you know what your current directory is? File open/save boxes can change that. So it's always safer to work with absolute paths.
Do a
Path.GetFullPath(filename)
and see where that points to. Is it the right location?
If you use the absolute instead of the relative path, does it work then?
Before you access a file, you should call System.IO.File.Exists(). It's not clear from your error description if the origin file exists or not before the copy.
If you don't specify an absolute path, your relative path with often be resolved from unexpected places, usually the current working directory of the process. Calling this method may tell you were the process is currently running:
System.IO.Directory.GetCurrentDirectory()
You should never make assumptions about the current working directory of a running process as the user could start your program from anywhere. Even if you think you always control the current working directory, you will be surprised how often you will be wrong.
Do you have a debugger? Why not insert a breakpoint and check the values used at each step?
If the file system says "cannot find file", I wouldn't bother arguing with it...
use \\ for the file path directory if it in local.. if your file exists in network path use \\\\(atfirst).. So that it look for network drive..
Thanks
It is necessary to embed all external files into the executable and change your code to work with these embedded files rather than to expect files on the disk.
To use images or whatever you need files("xml/txt/doc"), you need to set the build action of your file to Embedded Resource, and call the method with the fully qualified name of the file, where the name is assembled like this:
[RootNameSpaceOfTheProject].[NameOfFolderInTheProject].[FileNameWithExtension]
Example:
Call the method:
var b = ResourceOperations.GetResourceAsByteArray("Store.Resources.EmbeddedIcons.toolbox.png");
Now you can write the byte array to a temporary file for example and use this as an image source, or you can build an image from the byte array directly. At least, you've got your data...
and to save this files to a disk we should write a code by #Jon Skeet :
public static void CopyStream(Stream input, Stream output)
{
// Insert null checking here for production
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, bytesRead);
}
}
then call it:
using (Stream input = assembly.GetManifestResourceStream(resourceName))
using (Stream output = File.Create(path))
{
CopyStream(input, output);
}

Categories

Resources