C# Targeting a directory of which a mapname is partially known - c#

I am trying to send a file using the smtp from gmail, but I have stumbled upon a problem.
The file will be stored in the windows appdata folder.
To add the file to the e-mail, I'm using:
attachment = new System.Net.Mail.Attachment((Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "/Folder1/Folder2/Folder3/result.txt"));
The code as above works, BUT:
The issue I currently have, is that Folder2 as seen above, will be a random name containing numbers, letters, and the word TEMP.
For example a12TEMP34b
I have tried and searched if I'm able to use * somehow, but can't seem to get it working.
Any ideas?

You can use Directory.EnumerateDirectories to search for a specific folder :
var folder1 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Folder1");
var folder2 = Directory.EnumerateDirectories(folder1, "*TEMP*").Single();
var path = Path.Combine(folder2, "Folder3/result.txt");
attachment = new System.Net.Mail.Attachment(path)

You could parse Directory.GetDirectory into a string array and grab the first element of that array if you're sure it will always be that path.
So:
string staticPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "/Folder1/";
string dynamicFolder = Directory.GetDirectory(staticPath, "*TEMP*")[0];
string finalPath = dynamicFolder + "/Folder3/result.txt"

Related

Get folder on in same directory as App domain path

I have an asp.net web app and i need to get the string path of a folder in the same directory as my web app.
Currently im using this code to get the add domain path.
string appPath = HttpRuntime.AppDomainAppPath;
Which returns "c:/path/webapp", i need "c:/path/folder".
Thanks.
If you'd like a more generic approach that doesn't require knowing the starting folder:
//NOTE: using System.IO;
String startPath = Path.GetDirectoryName(HttpRuntime.AppDomainAppPath);
Int32 pos = startPath.LastIndexOf(Path.DirectorySeparatorChar);
String newPath = Path.Combine(startPath.Substring(0, pos), "folder"); //replace "folder" if it's really something else, of course
This way, whatever directory your web app is running from, you can get it, reduce it by one level, and tack on "folder" to get your new sibling directory.
You can use String.Replace method.
Returns a new string in which all occurrences of a specified string in
the current instance are replaced with another specified string.
string appPath = HttpRuntime.AppDomainAppPath;
appPath = appPath.Replace("webapp", "folder");
Here is a DEMO.
Thanks to DonBoitnott comments, here is the right answer;
string appPath = #"C:\mydir\anotherdir\webapp\thirddir\webapp";
int LastIndex = appPath.LastIndexOf("webapp", StringComparison.InvariantCulture);
string RealappPath = Path.Combine(appPath.Substring(0, LastIndex), "folder");
Console.WriteLine(RealappPath);
This will print;
C:\mydir\anotherdir\webapp\thirddir\folder

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.

Moving files based on name to the corresponding folder

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);
}

Writing to a subfolder in c#

I'm having a little bit of trouble writing to a text file within a folder I tried to create. It said I didn't have access to the path 'C:\'
Could anyone tell me why and how to fix it? Thanks!
string file_name = Environment.CurrentDirectory;
file_name += #"\.";
file_name = (string)combobox1.SelectedValue;
file_name += #"\.";
file_name += (string)combobox2.SelectedValue;
TextWriter name = new StreamWriter(file_name);
EDIT: Here's the new code after revisions...
var location = Path.Combine(Environment.CurrentDirectory, (string)combobox1.SelectedItem);
Directory.CreateDirectory(location);
var path = Path.Combine(location, combobox2.SelectedItem);
TextWriter name = new StreamWriter(path, true);
My goal is to write a text file to \\.txt
Could anyone tell me how? Thanks!
have you checked the value of file_name to make sure is a valid Path?
you have missed a concatenation anyway at line number 3
string file_name = Environment.CurrentDirectory;
file_name += #"\.";
file_name += (string)combobox1.SelectedValue; // <--
file_name += #"\.";
file_name += (string)combobox2.SelectedValue;
TextWriter name = new StreamWriter(file_name);
The account that the application is running under does not have write permissions in the location you are trying to save the file to.
This article goes over how to resolve this issue:
http://www.phdcc.com/findinsite/instperm.htm
You should be using Path.Combine():
var fileName = Path.Combine(Environment.CurrentDirectory, (string)comboBox1.SelectedValue,
(string)comboBox2.SelectedValue);
If at that point it still doesn't work, at least you'll know it's actually a permissions/existence/etc. issue, rather than an issue with the way you've constructed the file name.
The solution here is a combination of what everyone else has said.
As has already been pointed out, this line:
file_name = (string)combobox1.SelectedValue;
is incorrectly doing an assignment (=) instead of a concatenation (+=). This means that if comboxbo1.SelectedValue is null, your path becomes \., which is the root directory of the drive.
You need to remember that it's legal for SelectedValue to be null, because a combo box can have an empty selection. You need to handle that case, perhaps by disabling your save functionality until the combo boxes have valid selections.
This isn't really a problem with permissions; it's unlikely that you actually need or intend to write to the root directory, which is why you aren't given that permission in the first place.

How should I handle windows/Linux paths in c#

My intention is for my application to run on windows and linux.
The application will be making use of a certain directory structure e.g.
appdir/
/images
/sounds
What would be a good way of handling the differences in file(path) naming differences between windows and linux? I don't want to code variables for each platform. e.g. pseudo code
if #Win32
string pathVar = ':c\somepath\somefile.ext';
else
string pathVar = '/somepath/somefile.ext';
You can use the Path.DirectorySeparatorChar constant, which will be either \ or /.
Alternatively, create paths using Path.Combine, which will automatically insert the correct separator.
How about using System.IO.Path.Combine to form your paths?
Windows example:
var root = #"C:\Users";
var folder = "myuser";
var file = "text.txt";
var fullFileName = System.IO.Path.Combine(root, folder, file);
//Result: "C:\Users\myuser\text.txt"
Linux example:
var root = #"Home/Documents";
var folder = "myuser";
var file = "text.txt";
var fullFileName = System.IO.Path.Combine(root, folder, file);
//Result: "Home/Documents/myuser/text.txt"
If you're using Mono. In the System.IO.Path class you will find:
Path.AltDirectorySeparatorChar
Path.DirectorySeparatorChar
Hope this helps!

Categories