Loading image from code using relative path in Windows Forms - c#

I have an Image in my application and I have a picture in my WinForms.
public static string Correct_Icons = #"C:\Users\xyz\Documents\Visual Studio 2008\Projects\FileShareMgmt\FileShareMgmt\Resources\Correct.png";
public static string warning_Icon = #"C:\Users\xyz\Documents\Visual Studio 2008\Projects\FileShareMgmt\FileShareMgmt\Resources\Warning.png";
cell.Value = Image.FromFile("Resources/warning_Icon);
But I just want to use a relative path and not the full path like above.
For example something like this:
public static string Correct_Icons = "\Resources\Correct.png";
and cont.
..../
not working. Any suggestions?

For my program, Path.GetDirectoryName (Assembly.GetExecutingAssembly().Location) returns
C:\code\test\Junk\bin\Debug.
cell.Value = Image.FromFile(
Path.Combine (
Path.GetDirectoryName (Assembly.GetExecutingAssembly().Location),
"Resources/warning_Icon"));
Of course, usually you would embed the resources in your assembly unless you want to change them without a recompile.

My issue was solved after this solution:
string[] s = { "\\bin" };
string path = Application.StartupPath.Split(s, StringSplitOptions.None)[0] + "\\Images\\On24.png";

Related

How to find image path in c#?

I want to find image path but I didn't.
my image path : C:\Works\Web5.1.0\Src\Works.WebNext\Password\assets\img
my image name : reset_password.jpg
I tried this : string path2 = Path.GetFullPath("reset_password.jpg"); but it's wrong path (output: C:\Windows\System32\inetsrv)
and tried this :
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);
string a = Path.Combine(path, "reset_password.jpg");
output : (C:\Works\Web5.1.0\Src\Works.WebNext\bin )
I think, output should be like this : C:\Works\Web5.1.0\Src\Works.WebNext\Password\assets\img
one more thing : image path may not be same another computer so I think give a specific path is not right (for example : C:\Works\Web5.1.0\Src\Works.WebNext\Password\assets\img )
X computer : C:\Works\Web5.1.0\Src\Works.WebNext\Password\assets\img
Y computer : C:\Works\Web\Src\Works.WebNext\Password\assets\img
By the way, I am writing with c#.
How can I do ?
Any ideas please.
I'm not sure I've understood the issue but an idea of how to find the same file on many systems is:
AppDomain.CurrentDomain.BaseDirectory
This will give you the location of the folder that your running executable is in. The output is in the format of
"C:\Folder\Folder\WindowsFormsApplication1\WindowsFormsApplication1\bin\Debug\".
So, you can put the image in the same folder as the .exe, add "imagefilename.type" and you should find it.
Please clarify if this doesn't answer your question.
Following code will give you your desired output
string folderPath = #"C:\Works\Web5.1.0\Src\Works.WebNext\Password\assets\img";
string imgFilePath = Path.Combine(folderPath, "reset_password.jpg")
Assembly.GetExecutingAssembly() gives the path of the current working directory i.e. the path from where your executables are being run (in your case its 'bin' folder)
Try this for Web Applications.
string imagePath = "/Password/"; /* Your Image folder */
string path = Server.MapPath(#"ImagePath" + imagePath);
In Windows Application:
try
{
System.IO.DirectoryInfo directory = new DirectoryInfo(#"Your local Image directory inside bin/debug");
FileInfo result = null;
var list = directory.GetFiles(); // Stackoverflow Exception occurs here
if (list.Count() > 0)
{
result = list.OrderByDescending(f => f.LastWriteTime).First();
}
return result;
}
catch (Exception ex)
{
throw ex;
}

C# MVVM proper use of paths for deployment

private void loadWordsFromFile()
{
words = File.ReadAllLines("C:/Users/tony/Documents/Visual Studio 2013/Projects/Hangman/Hangman/Files/test.txt");
}
private void selectWord()
{
WordsRemaining = words.Length.ToString();
HangImage = new BitmapImage(new Uri("C:/Users/tony/Documents/Visual Studio 2013/Projects/Hangman/Hangman/Files/" + wrongGuesses + ".png"));
}
These are my paths. Could you please show me how to make the paths properly?
You can use this to get the current execution path
Uri executingPathUri = new Uri(Assembly.GetExecutingAssembly().GetName().CodeBase);
string executionFolderPath = Path.GetDirectoryName(executingPathUri.LocalPath);
Then, you can have a folder in your deployment directory that contains the files that you need.
Please never try to concatenate path using '+' operator. Always use
Path.Combine(.....)
public static string Combine(string path1, string path2, string path3, string path4);

Get Folder Path

I want to get the path of the folder to a textbox and the name of the folder is Images12345. I tried this.
//Inside the folder "Images12345"
string[] pics = { "1.jpg", "2.jpg", "3.jpg", "4.jpg", "5.jpg", "6.jpg", "7.jpg", "8.jpg" };
int i = 0;
Then in my form load
//I tried this but it is given me wrong path
textBox1.Text = Path.GetFullPath(#"Images12345");
//then slideshow
pictureBox1.Image = Image.FromFile(textBox1.Text+"/"+pics[0]);
timer1.Enabled = true;
timer1.Interval = 5000;
i = 0;
First, use this to get the application folder plus your images folder:
string applicationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Images12345");
Second, always use Path.Combine to work with paths:
pictureBox1.Image = Image.FromFile(Path.Combine(myFolderPath, pics[0]));
NOTE
You'll need to copy images folder where the executable is. That's your bin/Degub while you're debugging. You can navigate two folders up, but you must to implement this like you were in production, when the executable will be right next to your image folder.
EDIT
Maybe it's a better approach to use the current user's pictures folder. Like this:
string userPicturesFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
string imagesFolder = Path.Combine(userPicturesFolderPath, "Images12345");
You already found Path.GetFullPath... you should also look at Path.Combine to make a path out of multiple pieces, instead of just using string concatenation.

How to navigate a few folders up?

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.

Using GetEnvironmentVariable method to move files

I was using hard-coded directory path to Program Files to move file. I would now like to use the correct method to find the folder in Program Files.
I have found this method doing some Googling and it is what i would like to use:
static string ProgramFilesx86()
{
if( 8 == IntPtr.Size || (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("PROCESSOR_ARCHITEW6432"))))
{
return Environment.GetEnvironmentVariable("ProgramFiles(x86)");
}
return Environment.GetEnvironmentVariable("ProgramFiles");
}
I unfortunately am not sure how to implement and use this method.
Where do i insert the method in my app?
How do i use the above instead of this:
if (File.Exists(#"C:\PROGRA~1\TEST\ok.txt"))
File.Delete(#"C:\PROGRA~1\TEST\ok.txt");
File.Copy(#"C:\PROGRA~1\PROGRAMFOLDER\ok.txt", #"C:\PROGRA~1\TEST\ok.txt");
It's much easier to get the special folders like Program Files using
Environment.SpecialFolders
string programFilesFolder =
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86)
Continuing that example you could do something like this
string pathToFile =
Path.Combine(programFilesFolder, #"TEST\ok.txt");
if (File.Exists(pathToFile))
File.Delete(pathToFile);
UPDATE
Modified the code example to always get the 32-bit Program Files folder whether you're running 32- or 64-bit OS as #Mario pointed out that's what your original code was doing.
string fileName = Path.Combine( ProgramFilesx86(), applicationPath, #"ok.txt");
if (File.Exists( fileName ) )
{
File.remove( fileName );
}
string sourceFile = Path.Combine( ProgramFilesx86(), #"\PROGRAMFOLDER", "ok.txt" );
File.Copy( sourceFile, fileName);
Edit:
You should not use this method. The program folder depends on the capability of the programs and not the system! You must know whether they install to the ProgramFiles or ProgramFilesX86 folder.
And then use Eric J.'s answer.
string sourceFolder =
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
string source =
Path.Combine(sourceFolder, #"ok.txt");
string targetFolderPath =
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string target = Path.Combine(targetFolderPath, #"ok.txt");
if (File.Exists(source))
File.Delete(source);
File.Copy(targetFolderPath, source);

Categories