Checking if resource file exists - c#

I have an image file in my project's folder in visual studio and it is set to build action "resource" so it is included in my exe file.
I can link to this file in xaml no problem, for example <Image Source="images/myimage.png"> and it works.
But if I try to check the existence of the file, with File.exists("images/myimage.png") it always returns false. What am i doing wrong here?

If you do not want to have it bundled to the output folder additionally - you do not have to do anything. It is build into your exe, not need to check. Would always be true.
Okay, I understand because you dynamically build the name of your embedded resource you want to check it.
See here: WPF - check resource exists without structured exception handling
They basically check against Assembly.GetExecutingAssembly().GetManifestResourceNames()
You can use that as a starting point. But note that the resource name is not images/myimage.png but constructed from your namespace like YourApp.images.myimage.png. You might like to take a look at the contents of the built resourceNames array from that answer.

Xamarin.Forms
From a working code, checks if auto-generated filename exists in embedded resources in the shared project (as described here https://developer.xamarin.com/guides/xamarin-forms/user-interface/images/#Embedded_Images)
var assembly = typeof(App).GetTypeInfo().Assembly;
var AssemblyName = assembly.GetName().Name;
var generatedFilename = AssemblyName+".Images.flags.flag_" + item.CountryCode?.ToLower() + #".png";
bool found = false;
foreach (var res in assembly.GetManifestResourceNames())
{
if (res == generatedFilename)
{
found = true;
break;
}
}
if (found)
UseGeneratedFilename();
else
UseSomeOtherPlaceholderImage;

Have you set the "Copy to the Output" property to "Always"? And make sure that you use the correct path. The path of your executing assembly can be detected by using following code:
private string GetExecutingAssemblyPath()
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);
}
Cheers.

Related

How to access a file in runtime from output directory from a different project folder

We have set of Test projects under one solution in Visual Studio. I want to read a Json file which is copied to the output directory from a different project folder in runtime. It's a test project. I can get the current project directory. But not sure how to get the other assembly's directory.
Solution looks as below
Project1 -> Sample.json (this file is set to copy to output directory)
Project2
While running my test in Project2 I want to access the file in Project1 from the output directory.
I used to access files in the same project folder with code as mentioned. But not sure how to get for a different project file. Now with replace I am able to achieve it. But sure this is not the right way
var filePath = Path.Combine("Sample.json");
var fullPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), filePath).Replace("Project1", "Project2");
Not sure how to get from other project. I am sure I can't use GetExecutingAssembly(), but what is the alternative. Somehow I can access it using the above dirty way of replacing the assembly name.
To get the location of another assembly, you get use a type from that assembly to get to the right Assembly instance, and thus its location:
typeof(FromOtherAssembly).Assembly.Location
First, I suggest that you could find the dll path in the solution.
Second, you can filter the json file from the path.
The next is my working code.
Please install Microsoft.Build and Microsoft.Build.Framework nugetpackages first.
string path= string.Empty;
var solutionFile =SolutionFile.Parse(#"D:\test.sln");// Your solution place.
var projectsInSolution = solutionFile.ProjectsInOrder;
foreach (var project in projectsInSolution)
{
if(project.ProjectName=="TestDLL") //your dll name
{
path = project.AbsolutePath;
DirectoryInfo di = new DirectoryInfo(string.Format(#"{0}..\..\", path));
path = di.FullName;
foreach (var item in Directory.GetFiles(path,"*.json")) // filter the josn file in the correct path
{
if(item.StartsWith("Sample"))
{
Console.WriteLine(item);// you will get the correct json file path
}
}
}
}
You can use the below code to do it in a better way
//solutionpath will take you to the root directory which has the .sln file
string solutionpath = Path.Combine(Directory.GetParent(Directory.GetCurrentDirectory()).Parent.Parent.FullName);
string secondprojectname = #"SecondProjectName\bin";
string finalPath = Path.Combine(solutionpath, secondprojectname);
you can use CopyToOutputDirectory in MSBuild

How do I get the path to the current C# source code file?

How do I get the path to the current C# source code file, or the directory the file is stored in? (I'm answering this question myself because I didn't find anything on it with a Google search.)
(Note: This is not asking for Assembly.GetEntryAssembly().Location, which gives the path to the executable, nor Directory.GetCurrentDirectory(), which gives the directory the process was invoked from.)
Do this:
using System.Runtime.CompilerServices;
private static string GetThisFilePath([CallerFilePath] string path = null)
{
return path;
}
var path = GetThisFilePath(); // path = #"path\to\your\source\code\file.cs"
var directory = Path.GetDirectoryName(path); // directory = #"path\to\your\source\code"
How it works: Roslyn specially recognizes the CallerFilePath, CallerLineNumber, and CallerMemberName attributes (the last one might look familiar to you if you've done some MVVM programming). At compile-time, it populates parameters marked with these attributes with the actual file path / line number / member name of the caller. If you compile and decompile the above code, the assignment to path will look like
var path = GetThisFilePath(#"path\to\your\source\code\file.cs");

Loading files in default Internet browser programmatically

I used this to load a file (html_file.html) from Resources
//string myFile = "C:\\Users\\...\\Resources\\html_file.html"; // this works
var myFile = Path.GetFullPath("html_file.html"); // this doesn't works
//myFile = myFile.ToString();
//myFile = myFile.Replace(#"\", #"\\");
//MessageBox.Show(myFile);
try
{
Process.Start(myFile);
}
catch (Win32Exception noBrowser)
{
if (noBrowser.ErrorCode == -2147467259)
MessageBox.Show(noBrowser.Message);
}
catch (System.Exception other)
{
MessageBox.Show(other.Message);
}
Can someone tell me what's wrong?
EDIT : This works
Build Action = Embedded Resource and Copy to Output Directory = Copy always
string myFile = #".\Resources\html_file.html";
but I still need to have the path Resources with the file. Is there any way to have the 'html_file' inside my .EXE file?
Quite obviously it cannot find the file in the current directory. Make sure the following are correct:
The file is included in your project and its Copy to Output Directory property is set to Copy always or Copy if newer.
Use Application.StartupPath to make sure you are pointing to correct directory, so the first line would become:
Code:
var myFile = Path.Combine(Application.StartupPath, "html_file.html");
In the first method you specify the exact path to your file.
In the second one you ask the framework to create a fullpath.
The framework need to start from somewhere and it choose to start from your current directory but the file is not present there

How to give path to an text file in Solution using XDocument?

I want to load a xml document Swedish.xml which exists in my solution. How can i give path for that file in Xamarin.android
I am using following code:
var text = File.ReadAllText("Languages/Swedish.txt");
Console.WriteLine("text: "+text);
But i am getting Exception message:
Could not find a part of the path "//Languages/swedish.txt".
I even tried following lines:
var text = File.ReadAllText("./Languages/Swedish.txt");
var text = File.ReadAllText("./MyProject/Languages/Swedish.txt");
var text = File.ReadAllText("MyProject/Languages/Swedish.txt");
But none of them worked. Same exception message is appearing. Build Action is also set as Content. Whats wrong with the path? Thanks in advance.
Just try with this
string startupPath = Path.Combine(Directory.GetParent(System.IO.Directory.GetCurrentDirectory()).Parent.Parent.FullName, "Languages", "Swedish.txt");
var text = File.ReadAllText(startupPath);
Try...
Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments)+"/Languages/Swedish.txt"
If you mark a file as Content Type, it will be included in the app bundle with the path that you are using within your project file. You can inspect the IPA file (it's just a renamed zip) that is created to verify that this is happening.
var text = File.ReadAllText("Languages/Swedish.txt");
should work. The file path is relative to the root of your application. You need to be sure that you are using the exact same casing in your code that the actual file uses. In the simulator the casing will not matter, but on the device the file system is case sensitive, and mismatched casing will break the app.
I've looked into this before and never found any solution to access files in this way. All roads seem to indicate building them as "content" is a dead end. You can however place them in your "Assets" folder and use them this way. To do so switch the "Content" to "AndroidAsset".
After you have done this you can now access the file within your app by calling it via
var filename = "Sweedish.txt";
string data;
using
(var sr = new StreamReader(Context.Assets.Open(code)))
data = sr.ReadToEnd();
....

How to access batch file that I saved as a resource?

I saved some batch file as a resource on my application.
I want to access this file on run time - so I trying to file this file on the Resource folder but I get an exception that the
"resource folder is not there"
I trying to find the resource file by this code
var allBatchFiles = Directory.GetFiles( string.Format( #"..\..\Resources\" ) );
So how to make this work ?
Note that, when you run your application in Visual Studio, it is executed from the bin subfolder, which changes relative paths.
However, if you want to embed the batch file into your application, you are entirely on the wrong track. The resource is compiled into your EXE, and you need to use a different method to retrieve it. The following MSDN article gives an example on how this can be done:
How to embed and access resources by using Visual C#
There are at least two types of resources you might be referring to.
First, if you are referring to a RESX file, then usually you can access resources directly. So if you have a RESX file called "MyRes.resx" with a resource in it called "MyString" then you can use:
string contents = Resources.MyRes.MyString;
If you are adding files to the solution and marking them as Embedded Resources, then you can use Assembly.GetManifestResourceStream to access the data. Here's the utility functions I use:
public static Stream GetResourceStream(string pathName, string resName, Assembly srcAssembly = null)
{
if (srcAssembly == null) srcAssembly = Assembly.GetCallingAssembly();
var allNames = srcAssembly.GetManifestResourceNames();
return srcAssembly.GetManifestResourceStream(pathName + "." + resName);
}
public static string GetResourceString(string pathName, string resName, Assembly srcAssembly = null)
{
if (srcAssembly == null) srcAssembly = Assembly.GetCallingAssembly();
StreamReader sr = new StreamReader(GetResourceStream(pathName, resName, srcAssembly));
string s = sr.ReadToEnd();
sr.Close();
return s;
}
The pathName is a bit tricky - it's the name of the project plus any folder names in your project. So if you have a project "MyApp" with a folder called "MyResources" with a file called "Batch.txt" marked as a resource, then you would access the contents with:
string contents = GetResourceString("MyApp.MyResources", "Batch.txt");

Categories