Embedding Text File in Resources C# - c#

I'm attempting to do two things. I want to embed a text file into my project so that I can utilise it and modify it, but at the same time I don't want to have to package it when I send the project out to users (I.E included in the exe file).
I've had a look around and there's been multiple questions already but I just cant seem to get any to work. Here's the steps I've taken so far;
Added the text file to my "Resources Folder"
Build action to "Content" and output directory to "Do not copy"
I then try to access the file in my code;
if (File.Exists(Properties.Resources.company_map_template))
{
MessageBox.Show("Test");
var objReader = new StreamReader(Properties.Resources.company_map_template);
string line = "";
line = objReader.ReadToEnd();
objReader.Close();
line = line.Replace("[latlong]", latitude + ", " + longitude);
mapWebBrowser.NavigateToString(line);
}
The MessageBox never appears which to me means that it cannot find the file and somewhere somehow I've done something wrong. How can I add the file into my project so I don't need to distribute with an exe whilst being able to access it in code?

I would use the following:
BuildAction to None (not needed)
and add your file to Resources.resx under files (using DragAndDrop from SolutionExplorer to opened Resources.resx)
Access to your Text:
using YOURNAMESPACE.Configuration.Properties;
string fileContent = Resources.company_map_template;
Then you're done. You don't need to access through StreamReader

Related

cannot find the path to the resource file c#

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.

avoid overwriting of file and content with each run or request with executable directory

Hello I’m trying to create directory folder with text document for my windows form application executable. Now I must make it available locally for other users.
I'm doing it this way:
string dir = "%ProgramData%\\MyAppName\\doc.txt";
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(Path.GetDirectoryName(dir));
var stream = File.CreateText(dir);
stream.Close();
}
and here is my access path from executable directory inside the code:
const string mypath = (#"%ProgramData%\MyAppName\doc.txt");
On the one stage of implementation I have also separate creation of document, but I almost sure that has no connection with problem, because creates it once and never overwrites if file exist, keeps content of text document with each new run of program, adding of data or request to it. Only if I delete it by hand, in this case creates new one:
if (File.Exists(mypath))
wordsTyped.AddRange(File.ReadAllLines(mypath));
and works perfect with local path to debug folder like this:
const string tetdb = ("doc.txt");
So code for executable must work same way, if directory, folder, file with content exist don't do nothing with it. But with code above, it rewrites everything with every request to it, not only with new run of program, with folder, text document and content inside.
but must be as follows: if folder is created once, if directory, file, document exist, no netter with code of executable, or with press enter, or it was already there. keep content inside the text document with every start of program or request to it of adding to it.
I've tried create only folder to executable path, to create text document separately as it shown above, but I got same result. So how to avoid this problem, what I'm doing wrong?
The test for !Directory.Exists is the cause of your problem.
You pass a filename to the method, thus the method returns false (a directory with that name doesn't exist).
This means that you always enter the if and calling File.Create over an existing file overwrite the content of the file
string file = "%ProgramData%\\MyAppName\\doc.txt";
if (!Directory.Exists(Path.GetDirectoryName(file)))
{
....
}

Download all files of a given type(.dll) from a http path in C#

There are similar questions regarding this which were asked earlier. But I couldn't find a proper solution yet.
I have an application which uses a user defined dll library(Cplus_Function_Library.dll). Imagine that the application is launched already to customers. And if there's a new version of the dll available the application will automatically download it and replaces the old one. There's no problem there.
Now I want to create new dll libraries(a lot) and upload it in the sameplace where the Cplus_Function_Library.dll new version exsists(ex: http path/FTP server). And then I can add them by reference in the Cplus_Function_Library.dll. It's also clear. But my question is how can I download all the dll files in this path without giving the file names one by one inside my updater function? Because when I launch the app these files are not known.(updater function is included inside the application.)Is there an easy way to download all the dll files from a specified path without much hassle?
My current update function can be seen below.
Uri pathToNewVerNo = new Uri("//....../New_version.txt"); //Path to the new version number
Uri pathToCurrentVerNo = new Uri("...../Current_version.txt"); //Path to the current version number
Uri pathToDownload = new Uri(".....new_library.dll");
StreamReader readNewVer; //To read the new version number
StreamReader readCurVer; //To read the current version number
StreamWriter writeToCurVer;
WebClient verNew = new WebClient(); //will be used to download the New_version .txt file
WebClient verCur = new WebClient(); //will be used to download the Current_version .txt file
WebClient update = new WebClient(); //will be used to download the new dll file
verNew.DownloadFile(pathToNewVerNo, "New_version.txt"); //Download the New_version .txt file
readCurVer = new StreamReader("Current_version.txt"); //open Current_version.txt file to read
current_Version = readCurVer.ReadLine(); //assign the value to a string
readCurVer.Close(); //close the file
readNewVer = new StreamReader("New_version.txt"); //open New_version.txt file to read
new_Version = readNewVer.ReadLine(); //assign the value to a string
readNewVer.Close(); //close the file
current_ver_doub = Convert.ToDouble(current_Version); //convert the string value to a double
new_ver_doub = Convert.ToDouble(new_Version);
if (new_ver_doub > current_ver_doub) //check if the new version number is greater than the current version number
{
obj.SBO_Application.StatusBar.SetText("Please wait update in process", BoMessageTime.bmt_Medium, BoStatusBarMessageType.smt_Warning);
writeToCurVer = new StreamWriter("Current_version.txt"); //open the current_version.txt to write
writeToCurVer.Write(new_Version); //update with new version number
writeToCurVer.Close(); //close the file
update.DownloadFile(pathToDownload, "new_library.dll"); //download the new .dll file
//*************There will be a roll back functionality added in the future in case if the updated dll file is currupted.*****************
File.Replace("new_library.dll", "Cplus_Function_Library.dll", "Cplus_Function_Library.dll.bac", false); //make a back up file of the old .dll file and replace it
obj.SBO_Application.MessageBox("Update Successful. Please restart the AddOn", 1, "Ok");
try
{
foreach (Process proc in Process.GetProcessesByName("cplus_Global"))
{
proc.Kill();
proc.WaitForExit();
}
}
catch (Exception ex)
{
obj.SBO_Application.MessageBox(ex.Message, 1, "Ok");
}
}
else
{
// SBO_Application.MessageBox("No Update Available", 1, "Ok");
}
}//End of updater_cplus function */
First of all you need to ask yourself whether you absolutely want to reinvent the wheel, and are ready to tackle all problems you will encounter while doing that, such as the problem you now ran into. There are plenty of existing solutions to include installers and updaters with your software.
Anyway, to answer your question:
how can I download all the dll files in this path without giving the file names one by one inside my updater function?
You casually mention it should work over HTTP and FTP. The former has no formal "directory listing" command, so you'll have to invent that yourself. The latter does, but requires the directory to only contain relevant files, or you need to create a whitelist and/or blacklist to include or exclude certain files.
The easiest solution would be to define your version file format so as to include the list of files to download. Then you fetch the version file, interpret it and request the files mentioned in it.
Acording to CodeCaster's idea I put all my dll files inside one folder and the new_version text file in another folder. This way I made sure different file formats won't get mixed up.
The next step was to read the new_version.txt from the ftp server and compare the value with the current version. If it's greater than the later I took all the file names of dll files to a list. Then easily you can download the files one by one to your desired location.

Accessing a text file in a WPF project

I feel like I'm missing something obvious here...
I've got a text file in my WPF application which is located in a subfolder, so apologies for advance for the terrible ASCII.
+Project
+--+Subfolder
| +--TextFile.txt
|
+--App.config
+--App.xaml
+--etc.
The build action on this text file is Resource and I'm trying access the content as a string in my program, but I have absolutely no idea what I'm doing.
Trying to access the file through Properties.Settings.Default doesn't work, apparently there's only a ConnectionString resource in my program.
I can't do it in XAML because for whatever reason there's no Source property
<!-- somewhere up the top of App.xaml... -->
xmlns:clr="clr-namespace:System;assembly=mscorlib"
<clr:String Source="pack://application:,,,/Subfolder/Textfile.txt"/>
The FindResource method can't find it either.
FindResource("Usage.txt"); //ResourceReferenceKeyNotFoundException
All I'm trying to do is reference the text file, read it as a string and use that string. Otherwise I have to embed a 50 line verbatim string in the method call. Because that's totally a good idea. /s
In WinForms it was as simple as: Properties.Settings.Default.TextFile.ToString(); but nothing seems to work here.
I should point as well that this file shouldn't be included in the output directory, it needs to be embedded in the application or whatever the term is.
How should I be doing this?
This should work:
var uri = new Uri("pack://application:,,,/Subfolder/TextFile.txt");
var resourceStream = Application.GetResourceStream(uri);
using (var reader = new StreamReader(resourceStream.Stream))
{
var text = reader.ReadToEnd();
...
}
Try that:
using (StreamReader sr = new StreamReader(System.AppDomain.CurrentDomain.BaseDirectory + "/Subfolder/TextFile.txt"))
{
String line = sr.ReadToEnd();
Console.WriteLine(line);
}
You can do like this:
string file = #"pack://application:,,,/" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Name + ";component/Subfolder/TextFile.txt";
using (var sr = new StreamReader(System.Windows.Application.GetResourceStream(new Uri(file)).Stream))
{
var data= sr.ReadToEnd();
}
For example, this is your project structure
+ProjectName
+--+imagesFolder
| +--amogus.png
|
+--App.xaml
+--MainWindow.xaml
+--etc.
and you want to access the to amogus.png in your xaml window,
You have two ways:
note this way the imagesFolder will be visible in the release build to users
to set amogus.png Build Action to Content and
Copy to Output Directory to Copy always more info,
then rebuild from the build menu, then add this to the window xaml
<Image Source="pack://siteoforigin:,,/imagesFolder/amogus.png" ></Image>
note this way the imagesFolder will be not visible in the release build to users
to set amogus.png Build Action to Resource and
Copy to Output Directory to Do not copy or blank more info,
then rebuild from the build menu, then add this to the window xaml
<Image Source="/imagesFolder/amogus.png" ></Image>
more detail

Access to Resources

I've C# project and it has Resources folder. This folder has some of txt files. This files have various file names.
I'm taking file names from any source as string variable. For example I have fileName string variable and test.txt file in Resources folder:
string fileName = "test.txt";
When I want to access this file as like below, I can:
WpfApplication.Properties.test.txt;
But, When I want to access it by this code, I can't.
WpfApplication.Properties.fileName;
I want to use fileName string variable and access this text file.
What can I do to access it?
Thanks in advance.
Edit :
I change form of this question:
I've string variable assigned any text file name. For example; I have a.txt, b.txt, c.txt, d.txt, etc.. I'm taking this file name as string variable (fileName) via some loops. So, I took "c.txt" string. And, I can access this file by code in below:
textName = "c.txt";
fileName = "../../Resources\\" + textName;
However, when I build this project as Setup Project and install .exe file to any PC, there is no "Resources" folder in application's folder. So,
../../Resources\
is unavailable.
How can I access Resources folder from exe file's folder?
You need to add a Resource File to your project wich has the extension .resx/.aspx.resx. You will then be able to double click on this file and edit the required resources/resource strings. To do this right click on Project node in Solution Explorer > Add > New Item > Resource File. Let us assume you have added a file called ResourceStrings.resx to the Properties folder and added a resource string with key name MyResourceString, to access these strings you would do
string s = Properties.ResourceStrings.MyResourceString;
I hope this helps.
I would strongly recommend you taking a look at: http://msdn.microsoft.com/en-us/library/aa970494.aspx
If your text files have build action set as Resource you can locate them in code like:
(assuming the file name is fileName and its located in Resources folder)
Uri uri = new Uri(string.Format("Resources/{0}", fileName), UriKind.Relative);
System.Windows.Resources.StreamResourceInfo info = Application.GetResourceStream(uri);
Then you can access info.Stream to get access to your file.

Categories