I have a program that tracks changes on a local folder using a FileSystemWatcher object.
The issue is that sometimes, on some environments and situations (I do not know which ones), this watcher gives me an event on a DOS path ("/Hello/How/Are/You" becomes something like "/HE~1/HO~1/AR~1/YO~1").
What I am looking for is a way to force this path back into its full and normal aspect.
Or at least something that can tell me that the path is indeed a DOS path, so I can process the entry differently.
EDIT: it has to work on long paths (+260 chars), so Path.GetFullPath(sShortPath) does not work for me here!
Path.GetFullPath(#"/HE~1/HO~1/AR~1/YO~1") should do what you need.
The best method depends what you are looking for, if you just want to access the file once then the 8byte file names will work for internal file references
if you want to display to the user or store then there are 2 option
Path contains most of the tools you need to manipulate paths
fullPath = Path.GetFullPath(path1);
FileInfo and DirectoryInfo these 2 classes provide persistent access to files and directory information and while they can be created with any valid path both have a Full name property that provides access to the full path
As others said, Path.GetFullPath(sShortPath) works fine if not used on very long paths (+260 chars).
Here is a link I followed that worked for me.
GetLongPathName from kernel32.dll worked fine with me, I just had to change the 255 StringBuilder limit to a higher value to make it work with long paths.
Related
I'm trying to delete folders in a shared location on a network using C#. Some of the folder paths are too long for Windows to handle. I've tried multiple options for this. The best one I found was creating a FileSystemObject, adding \\?\ to the path and calling DeleteFolder on the path that I want to delete, which works on my local computer for paths that are too long, because I have mapped drives like C: and G: etc, but when I try to use it on a Network share folder I get either a HRESULT: 0x800A004C (CTL_E_PATHNOTFOUND) or value does not fall within the expected range.
The following is my code:
private static void DeletePathWithLongFileNames(string path)
{
string tmpPath = #"\\?\" + path;
FileSystemObject fso = new FileSystemObject();
fso.DeleteFolder(tmpPath, true);
}
let's say for example, the network + share folder is \\myServer\mySharedFolder\folder1\etc\etc, which would be the path string I'm sending to my delete function
then the tmpPath is showing as "\\\\?\\\\\\myServer\\mySharedFolder\\folder1\\etc\\etc"
I don't know much about UNC so I don't know if this is what is wrong or not. I'm pretty sure there is something wrong with my tmpPath variable, but again I'm not sure. Maybe it's a syntax error But I can't for the life of me figure out what is wrong. Thanks in advance for the help
EDIT: I believe I have found the answer, I am testing it right now. So far it has worked for me. if I run the DeleteFolder method on the following path \\?\UNC\server\sharedFolder\folder1\etc\etc" this seems to work. Now I just have to figure out how to get rid of all those extra slashes.
EDIT 2: This does work, tested it on a Share folder on a network. It just came down to me not understanding UNC paths.
The safe way to delete paths that are too long is to use AlphaFS. AlphaFS is a .NET library providing more complete Win32 file system functionality to the .NET platform than the standard System.IO classes. The most notable deficiency of the standard .NET System.IO is the lack of support of advanced NTFS features, most notably extended length path support (eg. file/directory paths longer than 260 characters).
See Directory Delete: http://alphafs.alphaleonis.com/doc/2.2/api/html/BE179564.htm
Alphaleonis.Win32.Filesystem.Directory.Delete(path)
I have an XML file I'm streaming as an XDocument. I need to be able to get the full path of the file (NOT the bin/Debug path) using reflection or the like (so this will be the path from the User's machine it lives on).
I have tried about a zillion different ways, including:
System.Reflection.Assembly.GetCallingAssembly().Location
System.Reflectin.Assembly.GetEntryAssembly().Location
System.Reflection.GetExecutingAssembly().Location
AppDomain.CurrentDomain.BaseDirectory.
How do I look use System.IO to find the path on the User's machine to my file?? Quite suprised I haven't found the simple answer after googling all day.
::EDIT:: I've now found out that there is no way to "reflectively" locate a path dynamically based on whether the application is running in the debugger or not. My only option is to do some detection.
Thanks in advance!!
I'm assuming that the file is in a child directory of the executable?
You can get the full path of the current working directory (ie where your .exe was run from) by using the Environment class. You can then concatanate this with the child directory
Environment.CurrentDirectory + #"\folder\file.xml"
http://msdn.microsoft.com/en-us/library/system.environment.aspx
Hope this helps!
EDIT: After reading up a little it turns out that CurrentDirectory can be changed rather easily. The accepted answer here Environment.CurrentDirectory is yielding unexpected results when running installed app offers a more reliable method.
Found my answer here (using path stripping and GetFullPath() ). It's a real bummer there's no way around just stripping the bin/debug part of the path. I used the third part of the question linked above.
i am trying to make a code which takes an image from a file path which i type in manually.
here is my code:
pieceImage = Image.FromFile(#"O:\Projects\imagename.png");
This code is saved on my USB flash drive.
However, whenever i run this code on a different computer, the path is different (obviously) and doesn't necessarily start with O:\ but something else, for example F:.
What can i use so that the path will change accordingly to the computer on which it runs? many thanks in advance.
You could get the drive letter based on the drive name, then build the Path to the file based on that (so only use the relative path from the root of the drive, no letter). See the DriveInfo class on MSDN and this question for a practical example of usage.
Of course, if the image is not on the USB drive, you will need to be more creative. But then I would recommand a different approach all the same, because there might be a design flaw in all this.
Assuming your program is in directory /Program/, include all images under your /Program/ directory, such as /Program/Images/. That way the images will be available no matter where the program is run.
I am using WritePrivateProfileString in c# (through DllImport) to store paths taken from textboxes on the interface. And the .ini file name is hardcoded in my application
string ini_file = ".\\config.ini";
However, when the file writing happens, the configuration file is written to the first path taken from the interface instead of writing it to the exe directory. Which is quite odd.
Debugging shows that the values are sent correctly to the WritePrivateProfileString but it still is written to the wrong location. Anyone knows why is that happenening?
I'd guess that something is changing the working directory of your process, most likely your code in the process. Note that the documentation has this to say:
If the lpFileName parameter does not contain a full path and file name for the file, WritePrivateProfileString searches the Windows directory for the file. If the file does not exist, this function creates the file in the Windows directory.
Now my guess is that this applies if you supply just a file name. Because your file name starts with . I believe that will force the function to start from the current working directory.
Having said all of that, and no matter what the cause of the problem is, you should use a fully-qualified path in order to make sure the file is written where you want it to be written. Whenever you want the file to go in a specific directory, it's always easiest to force that by using fully-qualified paths.
You can find the path to your executable using Application.ExecutablePath and then remove the file name part.
Another point to make is that the same directory as the executable may be a bad choice. If your program is installed under the Program Files directory then the directory which contains the executable will not be generally writeable. I think you should consider using a directory under in the user profile. Look for one of the Environment.SpecialFolder values.
Further to David Heffernan's answer - you can use
Path.GetDirectoryName(Application.ExecutablePath);
to safely get just the running application's folder part.
If you're in a dll rather than an executable, you can use
Path.GetDirectoryName(Assembly.GetAssembly(typeof(MyClass)).CodeBase);
Both require System.IO, and were originally posted here. Second example also requires System.Reflection).
Application data files are supposed to be written to the LocalApplicationData special folder.
string path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData);
You typically will not have permissions to write into the Program Files folder etc.
There are several related questions on stackoverflow but either my situation is different or I am too dumb to relate those to situation. I am hoping someone can help me with this. Further I am not even much of a .NET developer so I apologize in advance for any wrong terminology use.
My scenario is as follows: The tool that is used to deploy our .net application (One Click?) puts it in a directory whose full name exceeds 300 characters. The application uses a third party component -- lets call it dbstore -- that processes the specified file that resides in the application deployment directory.
So far we were using Assembly.GetExecutingAssembly().GetName().CodeBase to construct the fully qualified name of the file to pass to dbstore. But dbstore uses old style APIs and fails when it tries to open the file.
Since dbstore is not expected to change soon, it was recommended that the application chdir to the deployment directory and pass a relative path name in current directory to it. This is also the approach described in the accepted response PathTooLongException in C# code
However I find that Directory.SetCurrentDirectory also throws PathTooLongException. This happens even when I am using UNC path name, e.g a name starting with \\?\0000000000000\...
Am I doing something fundamentally wrong? Is there another function to use?
EDIT: It seems there is no way to achieve what I am looking for. Far as I can tell there is no way to set current directory to a long path.
Do you get a similar result when using Environment.SetCurrentDirectory() ?
If so, you may want to change your directory subfolder after subfolder.
EDIT:
Windows actually sets a limitation of 255 chars for a file path (WinXP) or 260 chars (Vista).
Note that this limitation does not apply for the filesystem, so you can have a file stored in such a long directory path, but Windows Explorer and many Windows services cannot read from such path.
Actually it seems to also include .NET framework methods since you cannot access such files. You may need to write your own filesystem API, but that's a bit too much overhead. Can't you just shorten the file path ? Does Windows offer a shortened way to address a file (like 8 octet file names) ?
Source: http://labnol.blogspot.com/2006/10/limitations-with-long-file-names-on.html