How to read the string from .resx file in c#? please send me guidelines . step by step
ResourceManager shouldn't be needed unless you're loading from an external resource.
For most things, say you've created a project (DLL, WinForms, whatever) you just use the project namespace, "Resources" and the resource identifier. eg:
Assuming a project namespace: UberSoft.WidgetPro
And your resx contains:
You can just use:
Ubersoft.WidgetPro.Properties.Resources.RESPONSE_SEARCH_WILFRED
This example is from the MSDN page on ResourceManager.GetString():
// Create a resource manager to retrieve resources.
ResourceManager rm = new ResourceManager("items", Assembly.GetExecutingAssembly());
// Retrieve the value of the string resource named "welcome".
// The resource manager will retrieve the value of the
// localized resource using the caller's current culture setting.
String str = rm.GetString("welcome");
Try this, works for me.. simple
Assume that your resource file name is "TestResource.resx", and you want to pass key dynamically then,
string resVal = TestResource.ResourceManager.GetString(dynamicKeyVal);
Add Namespace
using System.Resources;
Open .resx file and set "Access Modifier" to Public.
var <Variable Name> = Properties.Resources.<Resource Name>
Assuming the .resx file was added using Visual Studio under the project properties, there is an easier and less error prone way to access the string.
Expanding the .resx file in the Solution Explorer should show a .Designer.cs file.
When opened, the .Designer.cs file has a Properties namespace and an internal class. For this example assume the class is named Resources.
Accessing the string is then as easy as:
var resourceManager = JoshCodes.Core.Testing.Unit.Properties.Resources.ResourceManager;
var exampleXmlString = resourceManager.GetString("exampleXml");
Replace JoshCodes.Core.Testing.Unit with the project's default namespace.
Replace "exampleXml" with the name of your string resource.
Followed by #JeffH answer, I recommend to use typeof() than string assembly name.
var rm = new ResourceManager(typeof(YourAssembly.Properties.Resources));
string message = rm.GetString("NameOfKey", CultureInfo.CreateSpecificCulture("ja-JP"));
If for some reason you can't put your resources files in App_GlobalResources, then you can open resources files directly using ResXResourceReader or an XML Reader.
Here's sample code for using the ResXResourceReader:
public static string GetResourceString(string ResourceName, string strKey)
{
//Figure out the path to where your resource files are located.
//In this example, I'm figuring out the path to where a SharePoint feature directory is relative to a custom SharePoint layouts subdirectory.
string currentDirectory = Path.GetDirectoryName(HttpContext.Current.Server.MapPath(HttpContext.Current.Request.ServerVariables["SCRIPT_NAME"]));
string featureDirectory = Path.GetFullPath(currentDirectory + "\\..\\..\\..\\FEATURES\\FEATURENAME\\Resources");
//Look for files containing the name
List<string> resourceFileNameList = new List<string>();
DirectoryInfo resourceDir = new DirectoryInfo(featureDirectory);
var resourceFiles = resourceDir.GetFiles();
foreach (FileInfo fi in resourceFiles)
{
if (fi.Name.Length > ResourceName.Length+1 && fi.Name.ToLower().Substring(0,ResourceName.Length + 1) == ResourceName.ToLower()+".")
{
resourceFileNameList.Add(fi.Name);
}
}
if (resourceFileNameList.Count <= 0)
{ return ""; }
//Get the current culture
string strCulture = CultureInfo.CurrentCulture.Name;
string[] cultureStrings = strCulture.Split('-');
string strLanguageString = cultureStrings[0];
string strResourceFileName="";
string strDefaultFileName = resourceFileNameList[0];
foreach (string resFileName in resourceFileNameList)
{
if (resFileName.ToLower() == ResourceName.ToLower() + ".resx")
{
strDefaultFileName = resFileName;
}
if (resFileName.ToLower() == ResourceName.ToLower() + "."+strCulture.ToLower() + ".resx")
{
strResourceFileName = resFileName;
break;
}
else if (resFileName.ToLower() == ResourceName.ToLower() + "." + strLanguageString.ToLower() + ".resx")
{
strResourceFileName = resFileName;
break;
}
}
if (strResourceFileName == "")
{
strResourceFileName = strDefaultFileName;
}
//Use resx resource reader to read the file in.
//https://msdn.microsoft.com/en-us/library/system.resources.resxresourcereader.aspx
ResXResourceReader rsxr = new ResXResourceReader(featureDirectory + "\\"+ strResourceFileName);
//IDictionaryEnumerator idenumerator = rsxr.GetEnumerator();
foreach (DictionaryEntry d in rsxr)
{
if (d.Key.ToString().ToLower() == strKey.ToLower())
{
return d.Value.ToString();
}
}
return "";
}
I added the .resx file via Visual Studio. This created a designer.cs file with properties to immediately return the value of any key I wanted. For example, this is some auto-generated code from the designer file.
/// <summary>
/// Looks up a localized string similar to When creating a Commissioning change request, you must select valid Assignees, a Type, a Component, and at least one (1) affected unit..
/// </summary>
public static string MyErrorMessage {
get {
return ResourceManager.GetString("MyErrorMessage", resourceCulture);
}
}
That way, I was able to simply do:
string message = Errors.MyErrorMessage;
Where Errors is the Errors.resx file created through Visual Studio and MyErrorMessage is the key.
Once you add a resource (Name: ResourceName and Value: ResourceValue) to the solution/assembly, you could simply use "Properties.Resources.ResourceName" to get the required resource.
I added my resource file to my project directly, and so I was able to access the strings inside just fine with the resx file name.
Example: in Resource1.resx, key "resourceKey" -> string "dataString".
To get the string "dataString", I just put Resource1.resourceKey.
There may be reasons not to do this that I don't know about, but it worked for me.
The easiest way to do this is:
Create an App_GlobalResources system folder and add a resource file to it e.g. Messages.resx
Create your entries in the resource file e.g. ErrorMsg = This is an error.
Then to access that entry: string errormsg = Resources.Messages.ErrorMsg
The Simplest Way to get value from resource file.
Add Resource file in the project.
Now get the string where you want to add like in my case it was text block(SilverLight).
No need to add any namespace also.Its working fine in my case
txtStatus.Text = Constants.RefractionUpdateMessage;
Constants is my resource file name in the project.
Create a resource manager to retrieve resources.
ResourceManager rm = new ResourceManager("param1",Assembly.GetExecutingAssembly());
String str = rm.GetString("param2");
param1 = "AssemblyName.ResourceFolderName.ResourceFileName"
param2 = name of the string to be retrieved from the resource file
This works for me.
say you have a strings.resx file with string ok in it. to read it
String varOk = My.Resources.strings.ok
ResourceFileName.ResourceManager.GetString(ResourceFileName.Name)
2.return Resource.ResponseMsgSuccess;
Related
In my Resources folder I have a subfolder for images, I would like to get all the file names of those images from within that folder.
tried several Resources.loadAll methods to afterwards get the .name but without success
was is the right practice to achieve what I'm trying to do here ?
There is no built-in API to do this because the information is not after you build. You cant' even do this with what's in the accepted answer. That would only work in the Editor. When you build the project, your code will fail.
Here's what to do:
1. Detect when the build button is clicked or when a build is about to happen in the OnPreprocessBuild function.
2. Get all the file names with Directory.GetFiles, serialize it to json and save it to the Resources folder. We use json to make it easier to read individual file name. You don't have to use json. You must exclude the ".meta" extension.
Step 1 and 2 are done in the Editor.
3. After a build or during run-time, you can access the saved file that contains the file names as a TextAsset with Resources.Load<TextAsset>("FileNames") then de-serialize the json from TextAsset.text.
Below is very simplified example. No error handling and that's up to you to implement. The Editor script below saves the file names when you click on the Build button:
[Serializable]
public class FileNameInfo
{
public string[] fileNames;
public FileNameInfo(string[] fileNames)
{
this.fileNames = fileNames;
}
}
class PreBuildFileNamesSaver : IPreprocessBuildWithReport
{
public int callbackOrder { get { return 0; } }
public void OnPreprocessBuild(UnityEditor.Build.Reporting.BuildReport report)
{
//The Resources folder path
string resourcsPath = Application.dataPath + "/Resources";
//Get file names except the ".meta" extension
string[] fileNames = Directory.GetFiles(resourcsPath)
.Where(x => Path.GetExtension(x) != ".meta").ToArray();
//Convert the Names to Json to make it easier to access when reading it
FileNameInfo fileInfo = new FileNameInfo(fileNames);
string fileInfoJson = JsonUtility.ToJson(fileInfo);
//Save the json to the Resources folder as "FileNames.txt"
File.WriteAllText(Application.dataPath + "/Resources/FileNames.txt", fileInfoJson);
AssetDatabase.Refresh();
}
}
During run-time, you can retrieve the saved file names with the example below:
//Load as TextAsset
TextAsset fileNamesAsset = Resources.Load<TextAsset>("FileNames");
//De-serialize it
FileNameInfo fileInfoLoaded = JsonUtility.FromJson<FileNameInfo>(fileNamesAsset.text);
//Use data?
foreach (string fName in fileInfoLoaded.fileNames)
{
Debug.Log(fName);
}
Hmm... why not try this.
using System.IO;
Const String path = ""; /file path
private void GetFiles()
{
string [] files = Directory.GetFiles (path, "*.*");
foreach (string sourceFile in files)
{
string fileName = Path.GetFileName (sourceFile);
Debug.Log("fileName");
}
}
I am not sure if I am in the right place to ask this, I am trying to create a table with all the PDF files that I have in a folder into my solution.
And I am trying to retrieve their names and put them in a table to access all of them throughout a link.
I got the following method, however, it not working.
protected void ListFiles()
{
const string MY_DIRECTORY = #"~/HistoricalFiles";
string strFile = null;
foreach (string s in Directory.GetFiles(Server.MapPath(MY_DIRECTORY), "*.*"))
{
strFile = s.Substring(s.LastIndexOf("\\") + 1);
//ListBox1.Items.Add(strFile);
}
}
Is there any way I can access all of them easily and display them in a good way?
By looking at your image, you should change the path of the folder. It is not in your root directory, it is inside Reports\API folder
const string MY_DIRECTORY = #"~/Reports/API/HistoricalFiles";
One option would be to do System.IO.Directory.GetParent() a few times. Is there a more graceful way of travelling a few folders up from where the executing assembly resides?
What I am trying to do is find a text file that resides one folder above the application folder. But the assembly itself is inside the bin, which is a few folders deep in the application folder.
Other simple way is to do this:
string path = #"C:\Folder1\Folder2\Folder3\Folder4";
string newPath = Path.GetFullPath(Path.Combine(path, #"..\..\"));
Note This goes two levels up. The result would be:
newPath = #"C:\Folder1\Folder2\";
Additional Note
Path.GetFullPath normalizes the final result based on what environment your code is running on windows/mac/mobile/...
if c:\folder1\folder2\folder3\bin is the path then the following code will return the path base folder of bin folder
//string directory=System.IO.Directory.GetParent(Environment.CurrentDirectory).ToString());
string directory=System.IO.Directory.GetParent(Environment.CurrentDirectory).ToString();
ie,c:\folder1\folder2\folder3
if you want folder2 path then you can get the directory by
string directory = System.IO.Directory.GetParent(System.IO.Directory.GetParent(Environment.CurrentDirectory).ToString()).ToString();
then you will get path as c:\folder1\folder2\
You can use ..\path to go one level up, ..\..\path to go two levels up from path.
You can use Path class too.
C# Path class
This is what worked best for me:
string parentOfStartupPath = Path.GetFullPath(Path.Combine(Application.StartupPath, #"../"));
Getting the 'right' path wasn't the problem, adding '../' obviously does that, but after that, the given string isn't usable, because it will just add the '../' at the end.
Surrounding it with Path.GetFullPath() will give you the absolute path, making it usable.
public static string AppRootDirectory()
{
string _BaseDirectory = AppDomain.CurrentDomain.BaseDirectory;
return Path.GetFullPath(Path.Combine(_BaseDirectory, #"..\..\"));
}
Maybe you could use a function if you want to declare the number of levels and put it into a function?
private String GetParents(Int32 noOfLevels, String currentpath)
{
String path = "";
for(int i=0; i< noOfLevels; i++)
{
path += #"..\";
}
path += currentpath;
return path;
}
And you could call it like this:
String path = this.GetParents(4, currentpath);
C#
string upTwoDir = Path.GetFullPath(Path.Combine(System.AppContext.BaseDirectory, #"..\..\"));
The following method searches a file beginning with the application startup path (*.exe folder). If the file is not found there, the parent folders are searched until either the file is found or the root folder has been reached. null is returned if the file was not found.
public static FileInfo FindApplicationFile(string fileName)
{
string startPath = Path.Combine(Application.StartupPath, fileName);
FileInfo file = new FileInfo(startPath);
while (!file.Exists) {
if (file.Directory.Parent == null) {
return null;
}
DirectoryInfo parentDir = file.Directory.Parent;
file = new FileInfo(Path.Combine(parentDir.FullName, file.Name));
}
return file;
}
Note: Application.StartupPath is usually used in WinForms applications, but it works in console applications as well; however, you will have to set a reference to the System.Windows.Forms assembly. You can replace Application.StartupPath by
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) if you prefer.
I use this strategy to find configuration and resource files. This allows me to share them for multiple applications or for Debug and Release versions of an application by placing them in a common parent folder.
Hiding a looped call to Directory.GetParent(path) inside an static method is the way to go.
Messing around with ".." and Path.Combine will ultimately lead to bugs related to the operation system or simply fail due to mix up between relative paths and absolute paths.
public static class PathUtils
{
public static string MoveUp(string path, int noOfLevels)
{
string parentPath = path.TrimEnd(new[] { '/', '\\' });
for (int i=0; i< noOfLevels; i++)
{
parentPath = Directory.GetParent(parentPath ).ToString();
}
return parentPath;
}
}
this may help
string parentOfStartupPath = Path.GetFullPath(Path.Combine(Application.StartupPath, #"../../")) + "Orders.xml";
if (File.Exists(parentOfStartupPath))
{
// file found
}
If you know the folder you want to navigate to, find the index of it then substring.
var ind = Directory.GetCurrentDirectory().ToString().IndexOf("Folderame");
string productFolder = Directory.GetCurrentDirectory().ToString().Substring(0, ind);
I have some virtual directories and I cannot use Directory methods. So, I made a simple split/join function for those interested. Not as safe though.
var splitResult = filePath.Split(new[] {'/', '\\'}, StringSplitOptions.RemoveEmptyEntries);
var newFilePath = Path.Combine(filePath.Take(splitResult.Length - 1).ToArray());
So, if you want to move 4 up, you just need to change the 1 to 4 and add some checks to avoid exceptions.
Path parsing via System.IO.Directory.GetParent is possible, but would require to run same function multiple times.
Slightly simpler approach is to threat path as a normal string, split it by path separator, take out what is not necessary and then recombine string back.
var upperDir = String.Join(Path.DirectorySeparatorChar, dir.Split(Path.DirectorySeparatorChar).SkipLast(2));
Of course you can replace 2 with amount of levels you need to jump up.
Notice also that this function call to Path.GetFullPath (other answers in here) will query whether path exists using file system. Using basic string operation does not require any file system operations.
I got a programm that generates .resx resource files. Those resource files are used in other projects, that isnt in the same solution as the project that generates the resource files.
I wonder now, if its possible to generate a designer.cs file from the resource file, so that you can access the resources directly without using the resxresourcereader.
Open the resx file and on its toolbar there's an Access Modifier menu. Set this to Public. This will generate a *.Designer.cs file.
Right click on the Resources.resx and select "Run Custom Tool".
If the file is added to a Visual Studio Project you have to set the Custom Tool property of the .resx file to ResXFileCodeGenerator. Then will VS automatically create the needed designer file.
In one project I made a T4 script that scans the folder within the project for all images and let create a corresponding ressource file at a click.
Here is the needed part out of the T4 script:
var rootPath = Path.GetDirectoryName(this.Host.TemplateFile);
var imagesPath = Path.Combine(rootPath, "Images");
var resourcesPath = Path.Combine(rootPath, "Resources");
var pictures = Directory.GetFiles(imagesPath, "*.png", SearchOption.AllDirectories);
EnvDTE.DTE dte = (EnvDTE.DTE)((IServiceProvider)this.Host)
.GetService(typeof(EnvDTE.DTE));
EnvDTE.Projects projects = dte.Solution.Projects;
EnvDTE.Project iconProject = projects.Cast<EnvDTE.Project>().Where(p => p.Name == "Icons").Single();
EnvDTE.ProjectItem resourcesFolder = iconProject.ProjectItems.Cast<EnvDTE.ProjectItem>().Where(item => item.Name == "Resources").Single();
// Delete all existing resource files to avoid any conflicts.
foreach (var item in resourcesFolder.ProjectItems.Cast<EnvDTE.ProjectItem>())
{
item.Delete();
}
// Create the needed .resx file fore each picture.
foreach (var picture in pictures)
{
var resourceFilename = Path.GetFileNameWithoutExtension(picture) + ".resx";
var resourceFilePath = Path.Combine(resourcesPath, resourceFilename);
using (var writer = new ResXResourceWriter(resourceFilePath))
{
foreach (var picture in picturesByBitmapCollection)
{
writer.AddResource(picture.PictureName, new ResXFileRef(picture, typeof(Bitmap).AssemblyQualifiedName));
}
}
}
// Add the .resx file to the project and set the CustomTool property.
foreach (var resourceFile in Directory.GetFiles(resourcesPath, "*.resx"))
{
var createdItem = resourcesFolder.Collection.AddFromFile(resourceFile);
var allProperties = createdItem.Properties.Cast<EnvDTE.Property>().ToList();
createdItem.Properties.Item("CustomTool").Value = "ResXFileCodeGenerator";
}
I have flattened the above code a little bit, cause in my real solution i use a custom class for each picture instead of the simple filename to also support the same filename in different sub folders (by using a part of the folder structure for the namespace generation). But for a first shot the above should help you.
You can also do this in code:
(Taken from here: msdn)
StreamWriter sw = new StreamWriter(#".\DemoResources.cs");
string[] errors = null;
CSharpCodeProvider provider = new CSharpCodeProvider();
CodeCompileUnit code = StronglyTypedResourceBuilder.Create("Demo.resx", "DemoResources",
"DemoApp", provider,
false, out errors);
if (errors.Length > 0)
foreach (var error in errors)
Console.WriteLine(error);
provider.GenerateCodeFromCompileUnit(code, sw, new CodeGeneratorOptions());
sw.Close();
You need to reference system.design.dll
This also worked for me: double click and open the resx file, add a dummy resource, click save. the .designer.cs file is generated.
If you deleted it or added it to .gitignore because you thought you didn't need it. this is how you regenerate the file.
Go to the Access modifier and change it from (Public/Internal) to "No Code Generation"
Now put it back to Public/Internal.
VS will regenerate the Designer file for you.
Hello everyone and well met! I have tried a lot of different methods/programs to try and solve my problem. I'm a novice programmer and have taken a Visual Basic Class and Visual C# class.
I'm working with this in C#
I started off by making a very basic move file program and it worked fine for one file but as I mentioned I will be needing to move a ton of files based on name
What I am trying to do is move .pst (for example dave.pst) files from my exchange server based on username onto a backup server in the users folder (folder = dave) that has the same name as the .pst file
The ideal program would be:
Get files from the folder with the .pst extension
Move files to appropriate folder that has the same name in front of the .pst file extension
Update:
// String pstFileFolder = #"C:\test\";
// var searchPattern = "*.pst";
// var extension = ".pst";
//var serverFolder = #"C:\test3\";
// String filename = System.IO.Path.GetFileNameWithoutExtension(pstFileFolder);
// Searches the directory for *.pst
DirectoryInfo sourceDirectory = new DirectoryInfo(#"C:\test\");
String strTargetDirectory = (#"C:\test3\");
Console.WriteLine(sourceDirectory);
Console.ReadKey(true);>foreach (FileInfo file in sourceDirectory.GetFiles()) {
Console.WriteLine(file);
Console.ReadKey(true);
// Try to create the directory.
System.IO.Directory.CreateDirectory(strTargetDirectory);
file.MoveTo(strTargetDirectory + "\\" + file.Name);
}
This is just a simple copy procedure. I'm completely aware. The
Console.WriteLine(file);
Console.ReadKey(true);
Are for verification purpose right now to make sure I'm getting the proper files and I am. Now I just need to find the folder based on the name of the .pst file(the folder for the users are already created), make a folder(say 0304 for the year), then copy that .pst based on the name.
Thanks a ton for your help guys. #yuck, thanks for the code.
Have a look at the File and Directory classes in the System.IO namespace. You could use the Directory.GetFiles() method to get the names of the files you need to transfer.
Here's a console application to get you started. Note that there isn't any error checking and it makes some assumptions about how the files are named (e.g. that they end with .pst and don't contain that elsewhere in the name):
private static void Main() {
var pstFileFolder = #"C:\TEMP\PST_Files\";
var searchPattern = "*.pst";
var extension = ".pst";
var serverFolder = #"\\SERVER\PST_Backup\";
// Searches the directory for *.pst
foreach (var file in Directory.GetFiles(pstFileFolder, searchPattern)) {
// Exposes file information like Name
var theFileInfo = new FileInfo(file);
// Gets the user name based on file name
// e.g. DaveSmith.pst would become DaveSmith
var userName = theFileInfo.Name.Replace(extension, "");
// Sets up the destination location
// e.g. \\SERVER\PST_Backup\DaveSmith\DaveSmith.pst
var destination = serverFolder + userName + #"\" + theFileInfo.Name;
File.Move(file, destination);
}
}
System.IO is your friend in this case ;)
First, Determine file name by:
String filename = System.IO.Path.GetFileNameWithoutExtension(SOME_PATH)
To make path to new folder, use Path.Combine:
String targetDir = Path.Combine(SOME_ROOT_DIR,filename);
Next, create folder with name based on given fileName
System.IO.Directory.CreateDirectory(targetDir);
Ah! You need to have name of file, but with extension this time. Path.GetFileName:
String fileNameWithExtension = System.IO.Path.GetFileName(SOME_PATH);
And you can move file (by File.Move) to it:
System.IO.File.Move(SOME_PATH,Path.Combine(targetDir,fileNameWithExtension)
Laster already show you how to get file list in folder.
I personally prefer DirectoryInfo because it is more object-oriented.
DirectoryInfo sourceDirectory = new DirectoryInfo("C:\MySourceDirectoryPath");
String strTargetDirectory = "C:\MyTargetDirectoryPath";
foreach (FileInfo file in sourceDirectory.GetFiles())
{
file.MoveTo(strTargetDirectory + "\\" + file.Name);
}