I need to save a set of 20 txt files into my solution so they will be included into the exe file. In such a way I will be able to send to the final users only the executable file and anything else.
I need to use the following function:
File.Copy( sourcePath, #path + "\\FileName.txt");
to copy one of the 20 files into another directory (according to the request of the user). In order to include the 20 txt files into the solution, I created a new folder into the Solution Explorer and I put them into it. Then I selected "Resources" into the option of the single txt file. Let's suppose the name of the folder is FOO and the file is NAME01, then I'm assuming the local address of the single txt file is "\FOO\NAME01.txt". But this is not working, I'm getting an arror from the File.Copy function related to the sourcePath.
Do you have any suggestions? I'm stacked on this problem and I cannot find any solution on the web. Many thanks!
Step 1: add the files to your project
Step 2: make them embedded resource
Step 3: export them to filesystem at runtime:
using System.Reflection;
namespace ConsoleApplication1
{
class Program4
{
public static void Main(string[] args)
{
using(var stream = Assembly.GetExecutingAssembly()
.GetManifestResourceStream("ConsoleApplication1.Files.TextFile1.txt"))
using (var filestream = System.IO.File.OpenWrite("target.txt"))
{
stream.CopyTo(filestream);
filestream.Flush();
filestream.Close();
stream.Close();
}
}
}
}
"ConsoleApplication1.Files.TextFile1.txt" comes from:
ConsoleApplication1: default namespace of the project containing the files
Files.TextFile1.txt: relative path, dotted, inside the dll (look # screenshot 1)
Related
I am trying to make a simple c# program which opens a file in dotnet core 5 using visual studio, however, it transpires that it is looking for the file relative to where the .exe is stored, not my source files. Is there any way I can change this? So that the file can be stored with my source files?
I have tried using Directory.GetCurrentDirectory(), however, this takes me to .exe file, and I need it to open using a relative path rather than the absolute one.
The code is copied and pasted from the Microsoft C# docs here (In the image I have a './' before the filename, I have tried without, it was just something I tried to get it to work.
Code:
using System;
using System.IO;
namespace Test_File_Opening
{
class Program
{
static void Main(string[] args)
{
String line;
try
{
//Pass the file path and file name to the StreamReader constructor
StreamReader sr = new StreamReader("Sample.txt");
//Read the first line of text
line = sr.ReadLine();
//Continue to read until you reach end of file
while (line != null)
{
//write the lie to console window
Console.WriteLine(line);
//Read the next line
line = sr.ReadLine();
}
//close the file
sr.Close();
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine("Exception: " + e.Message);
}
finally
{
Console.WriteLine("Executing finally block.");
}
}
}
}
Exception: Could not find file 'C:\Users\callu\source\repos\Test_File_Opening\Test_File_Opening\bin\Debug\net5.0\Sample.txt'.
Executing finally block.
The running executable has no knowledge of or connection to the original source code files. They may be moved or deleted entirely for all it knows.
Use an absolute path for your file:
var sr = new StreamReader(#"C:\Some\Path\To\Your\File.txt");
I need it to open using a relative path rather than the absolute one.
No you don't. Because there is no universal relative path between a compiled executable and the source code from which it was compiled.
But a comment on the question offers an alternative:
it needs to be able to run on another machine
That's what config files are for... environment-specific settings. (Alternatively, if your plan all along was to distribute the source code for your users to compile and run themselves then they could simply edit it to their file location anyway.)
If you're using the older App.config style settings, add an App.config to your application and put the file path in the appSettings:
<appSettings>
<add key="FilePath" value="C:\Some\Path\To\Your\File.txt"/>
</appSettings>
Then use that setting in the code:
var sr = new StreamReader(System.Configuration.ConfigurationManager.AppSettings["FilePath"]);
Or, if you're using something newer like appsettings.json then there is documentation for that as well. But the principal is still the same.
You could even roll your own way of maintaining application configuration. Hell, you could even skip a config file entirely and provide the file name as a command line argument when running the application. The point is that any given environment would need a way to tell the application where the file is.
firstly apology if this has already been answered and I am duplicating the question. I have tried to find the answer to my issue but have failed and none of the auto-suggestions answers my problem.
I have my main project (XAML) and also a class library project called FileStore for files. The class library project is referenced into the main project and I have images and icon file in the class library project that I can access with no issues in my main project, however, I struggle to get the content of a txt file from the CL project to display in a label on the main project. I get the error: the system could not find the file and from the error, I can see that it is trying to look for a file in the main project bin\debug folder
I tried to follow this previous post which seemed to partly answer my issue but to no avail sadly.
Get relative file path in a class library project that is being referenced by a web project
The txt file Build action is set to: Resource and Copy to Output Directory set to: Copy Always.
As I mentioned I have the FileStore project referenced in my main project and the images work fine.
Below is the code I am using, I have tried different variations such as:
\Resources\textFile.txt and \textFile.txt, still no luck.
'''
public static string ReadFileinClLibr()
{
var buildDir =
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var filePath = buildDir + #"\textFile.txt";
return File.ReadAllText(filePath);
}
'''
For comparition here is the path for the image files that works, but I cannot get it to work with the txt file, as the error reads: the given paths format is not supported..
'''
#"pack://application:,,,/FileStore;component/Resources\textFile.txt"
'''
I want to be able to input the content of the text file from the class library project to the label in the main xaml project.
At the moment compiler keeps looking for this file in a debug folder of the main project, what I want is, for the compiler to look for the txt file in a CL FileStore project
In order to access the file all the time, we have to have the file copied to the debug folder. Right click the file from solution explorer change the properties then try to access the file from the executing assembly location.
StringBuilder bodyContent = new StringBuilder();
string fileName = "myfile.txt";
try
{
string filePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), fileName);
using (StreamReader sr = new StreamReader(filePath))
{
// Read the stream.
bodyContent.Append(sr.ReadToEnd());
}
}
catch(Exception ex)
{
Console.WriteLine(String.Format("{0} # {1}", "Exception while reading the file: " + ex.InnerException.Message, DateTime.Now));
throw ex;
}
Thanks to the post from #Sreekanth Gundlapally I have managed to fix my issues. I have mostly drawn on from the answer provided by #Sreekanth Gundlapally but there is one important bit missing. The string fileName should include any subfolders that the resource file is within in the Class Library Project, for example in my case the folder was named 'Resources' so the code should look like this:
string fileName = #"Resources/myfile.txt";
try
{
string filePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), fileName);
using (StreamReader sr = new StreamReader(filePath))
{
// Read the stream.
bodyContent.Append(sr.ReadToEnd());
}
I have also cleaned and rebuilt solution after which it all worked a charm.
Also a side note, anyone trying this and getting funny characters make sure your file's encoding is set to UTF-8 as this is the default encoding used by StreamReader, otherwise your file content may not be read correctly if it contains signs such as apostrophe.
The code below is working fine in creating a zip file but the file created is having a folder IIS Deploy >>>WebService... then the text file and not just the text file.
How can I just add the text files to the zip file?
ZipFile z = ZipFile.Create("C:\\IIS Deploy\\WebServiceTest\\WebServiceTest\\Accident.zip");
//initialize the file so that it can accept updates
z.BeginUpdate();
//add the file to the zip file
z.Add("C:\\IIS Deploy\\WebServiceTest\\WebServiceTest\\test1.txt");
z.Add("C:\\IIS Deploy\\WebServiceTest\\WebServiceTest\\test2.txt");
z.Add("C:\\IIS Deploy\\WebServiceTest\\WebServiceTest\\test3.txt");
//commit the update once we are done
z.CommitUpdate();
//close the file
z.Close();
If you have everything within same folder then the easiest option is to use CreateFromDirectory class.
static void Main()
{
// Create a ZIP file from the directory "source".
// ... The "source" folder is in the same directory as this program.
// ... Use optimal compression.
ZipFile.CreateFromDirectory("source", "destination.zip",
CompressionLevel.Optimal, false);
// Extract the directory we just created.
// ... Store the results in a new folder called "destination".
// ... The new folder must not exist.
ZipFile.ExtractToDirectory("destination.zip", "destination");
}
http://www.dotnetperls.com/zipfile
Please note that it is applicable to .NET Framework 4.6 and 4.5
How can I bundle a folder with a one click application and reference those files/folders after?
Seems rather simple but I just can't figure out how.
As in, I had the file index.html in the folder UI and I wanted to package that with the application, then I want to get the stream for that file with the string "/UI/index.html" but instead of just index.html, an entire website.
Add the folder to your VS Project, right-click on it and select "embed as resource". That will make the files in the folder be embedded in the .NET assembly. To get the file contents in your program, you can use something like this:
public class ReadResource
{
public string ReadInEmbeddedFile (string filename) {
// assuming this class is in the same assembly as the resource folder
var assembly = typeof(ReadResource).Assembly;
// get the list of all embedded files as string array
string[] res = assembly.GetManifestResourceNames ();
var file = res.Where (r => r.EndsWith(filename)).FirstOrDefault ();
var stream = assembly.GetManifestResourceStream (file);
string file_content = new StreamReader(stream).ReadToEnd ();
return file_content;
}
}
In the above function I assume your files a text/html files; if not, you can change it not to return string but byte[], and use a binary stream reader for that.
I also select the files by file.EndsWith() which is enough for my needs; if your folder has a deep nested structure you need to modify that code to parse for folder levels.
Perhaps there is a better way, but given the content is not too large you can embed binaries directly into your program as a base64 string. In this case it would need to be an archive of the folder. You would also need to embed the dll used for unzipping that archive (If I understood correctly you want to have single .exe and nothing more).
Here is a short example
// create base64 strings prior to deployment
string unzipDll = Convert.ToBase64String(File.ReadAllBytes("Ionic.Zip.dll"));
string archive = Convert.ToBase64String(File.ReadAllBytes("archive.zip"));
string unzipDll = "base64string";
string archive = "probablyaverylongbase64string";
File.WriteAllBytes("Ionic.zip.dll", Convert.FromBase64String(unzipDll));
File.WriteAllBytes("archive.zip", Convert.FromBase64String(archive);
Ionic.Zip.ZipFile archive = new Ionic.Zip.ZipFile(archiveFile);
archive.ExtractAll("/destination");
The unzipping library is DotNetZip. It's nice because you need just a single dll. http://dotnetzip.codeplex.com/downloads/get/258012
Edit:
Come to think of it, as long as you write the Ionic.dll to the working directory of the .exe you shouldn't need to use the dynamic dll loading so I removed that part to simplify the answer (it would still need to be written before you reach the method it is in though).
I have an exe that already creates a csv file. If I save the exe in C:/EXE, then the cvs file automatically gets created in C:/EXE folder.
C# code uses StreamWriter to accomplish this:
using (TextWriter log = new StreamWriter(errorLog + errorBatchNumber.ToString("000") + ".csv", true))
{
if (errorCount == 0)
{
log.WriteLine("Error message");
}
log.WriteLine(link.StatusMessage);
log.Close();
}
What I need to add:
A folder needs to be created first where the csv file will be saved.
This folder will be created where the EXE was saved, in this example: C:/EXE
After folder and cvs file was created, it needs to be zipped thru code. (But I need to accomplish first 1 and 2)
Any ideas?
Thanks in advance guys! :)
If you know the path where the EXE will be saved then
Directory.CreateDirectory(path + folderName) to create folder
To zip items use SharpZipLib at
http://www.icsharpcode.net/opensource/sharpziplib/ or http://wiki.sharpdevelop.net/SharpZipLib_MainPage.ashx
Would be something like
DirectoryInfo di = new DirectoryInfo(#"C:\exe");
if(!di.Exists)
di.Create();
Then you can use di.FullName to get the directory to save your file into.
Syntax might be a bit off but it should be enough to get you started. You can check out the MSDN on DirectoryInfo as well.