File Already Exists When Moving File - c#

In Windows Explorer you can have this structure:
Main Directory
New Directory(a directory)
New Directory(a file without an extension)
My structure is:
Main Directory
New Directory(a directory)
Some File.txt
What I'm trying to do is rename "Some File.txt" to "New Directory", like you can in Explorer. I'm using File.Move("/Main Directory/Some File.txt", "/Main Directory/New Directory");
However, I keep getting an exception saying
Cannot create a file when that file already exists.
I assume it's not liking the fact that there's a directory named "New Directory". But given the fact that a directory and file with the same name may coexist, I don't see why the Move API fusses about this.
Is there some way to tell it to ignore directories with the same name when copying files, and vice versa?
EDIT: I recently reinstalled Windows and forgot to turn file extensions back on, so my rename in Explorer wasn't modifying the extension like I'm used to it doing. With extensions on, I can't perform the rename. So behavior is actually as expected. I'll leave this here in case someone does the same thing in the future.

... given the fact that a directory and file with the same name may coexist ...
That statement is incorrect. Each object in a container must have a distinct name. Presumably your shell is configured to hide extensions of registered file types which is leading you to make this erroneous statement.
The error message reported is accurate and cannot be avoided without renaming one of the files.

Related

Get a file path C#

I have a .txt file that I need to read in my program. For the moment I have the directory hardcoded as such:
file = new StreamReader(#"C:\Users\<username>\Documents\File.txt");
However that will (obviously) not work on any other PC that does not have that access to altering the code, or (by some strange happenstance) the same directory as the original code.
How can I get the full file path to set it in my program using C#?
You could create the file in their Application Data directory (they could still find it if they wanted to, but at least it wouldn't be as obvious as the My Documents folder).
When you want to access it, use the Environment class. There are methods for locating special folders for the current user, without resorting to hard-coded paths:
var filePath = Path.Combine(Environment.GetFolderPath(
Environment.SpecialFolder.ApplicationData), "File.txt");
Option 1:
Application.StartupPath can be used for the purpose.
It gets the path for the executable file that started the application, not including the executable name.
Keep File.txt with your executable.
Option 2:
Use Environment.SpecialFolder.ApplicationData
It gives directory that serves as a common repository for application-specific data for the current roaming user.
NOTE: If you want to restrict the user to look into the contents of File.txt then you might need to encrypt the contents.

Why cannot libspotify save to cache?

Running my C# application from Visual studio works fine (in this respect)
But when installing the application in my system (win7, .NET 4.0) I get problems with the cache.
These are the errors I get:
LogMessageCallback. Message:20:43:03.988 E [playlist:1978] Unable to save file: playlist.bnk
LogMessageCallback. Message:20:43:03.988 E [social-mgr:830] Unable to save file: social_stream.bnk
LogMessageCallback. Message:20:46:31.034 E [user_cache:107] Unable to save file: user-cache.bnk
LogMessageCallback. Message:20:43:04.988 I [c:/Users/spotify-buildagent/BuildAgent/work/1e0ce8a77adfb2dc/client/core/protocol/file_streamer_simple.cpp:769] Request for file 57a6ab34bad26645e2345a610ae652fe77f82afb complete (code: 0)
I have tried to deleted the entire cache library and it gets recreated when I start the app, so it can't be a matter of file privilege.
Since the cache does not seem to be valid my playlists are not accessible to me at startup.
I do log out properly.
Any explanation/workaround?
I think I've got it...
I search for the playlist.bnk file on my disk and found one under Spotify\bin\Debug\cache_location\Users\bes51659-user, that is from where I run my project with visual studio. "cache_location" in the path directed me to the settings_location argument in the config struct when creating the session. I had set it to const string "cache_location". I must have understood the explanation wrong:
https://developer.spotify.com/docs/libspotify/12.1.51/structsp__session__config.html#a342532432040d476aaaf73f10893d23b
The location where Spotify will write setting files and per-user cache items. This includes playlists, track metadata, etc. 'settings_location' may be the same path as 'cache_location'. 'settings_location' folder will not be created (unlike 'cache_location'), if you don't want to create the folder yourself, you can set 'settings_location' to 'cache_location'.
(a bit contradictory that the "cache_location" catalog was actually created under debug!)
The comment must mean that if I reuse the same location for setting_location as for cache_location I do not have to create it as it has already been created!
I do not know if libspotify did not have permissions to create the catalog "cache_location" under "program files", or if it expected it to be there and did not find it. But it does not matter. I have now changed both the locations to "c:\mySpotify" in the config struct and problem solved...
My only excuse is that google tells me that I'm not the first to have fallen into this pithole.

c# writing to a file without full path

If I use this code
File.AppendAllText("C:/Users/Michael/Documents/Visual Studio 2010/Projects/PuzzleGame/PuzzleGame/PuzzleGameContent/player.TXT", "hi");
The file will save and add "hi" to the end of it. However, if I do something like this:
File.AppendAllText("player.TXT", "what is good?");
The file won't have a "what is good?" at the end of it. I can read files just fine using only the "player.TXT" filename but I can't write to a file using only that. Can anyone help me?
Your working directory is wherever the .exe is (unless you change it). So you see, when you compile, the exe ends up in the bin folder, so your player.txt would need to be there, not with your source.
edit:
I bet you're appending to player.txt THEN you read it and that's why it worked fine, because you created a new one in your bin folder. Otherwise, read would not have worked. If you go in your bin folder and delete player.txt, your readfile shouldn't work.
Both forms are perfectly valid. The likely scenario is that your second version is simply writing to a file at a different location, because not specifying the path will default to the current directory.
If you don't include a path, you'll want to ensure the current directory is valid for accessing the file.
Most likely there are two files on the file system, one in the directory that is explicitly defined in the first example and one where the executable is running in the second example since no explicit path was defined in the parameter of the method call.
From MSDN:
Given a string and a file path, this method opens the specified file,
appends the string to the end of the file, and then closes the file.
The file handle is guaranteed to be closed by this method, even if
exceptions are raised.
The method creates the file if it doesn’t exist, but it doesn't create
new directories. Therefore, the value of the path parameter must
contain existing directories
.
The problem is that AppendAllText is a method which will create the file if it doesn't already exist. So when you use an incomplete path it is unsure whether to create a new file in a base directory or add to an already existing file. If you can't use the full path for whatever reason, you could get the current working directory using something like:
File.AppendAllText(System.Environment.CurrentDirectory + "player.TXT", "what is good?");
So long as the current directory is correct, it'll work the same as your first working example.

Using WritePrivateProfileString to write path issue

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.

File Not Found Exception thrown for XML file possibly caused by Outlook

I'm getting a file not found exception when my application is called by Outlook. It's called when an email is saved to the computer the app is called and performs an action on the saved message.
My app uses a XML file to store configurable settings but this file can't be found when Outlook calls to executes the application. If I run the program manually then it works fine.
The interesting thing about the exception is this:
System.IO.FileNotFoundException: Could not find file 'C:\Program Files\Common Files\System\MSMAPI\1033\settingsOpened.xml'.
Why does Outlook think that the file is here ? This isn't the path for the file but I'm sure is related to Outlook. The way I'm referencing the path in the code is just:
XmlDocument xDoc = new XmlDocument();
xDoc.Load("settingsOpened.xml");
With the file being in the same folder as the .exe. I don't want to hard code the full path in for the XML files either.
Any help would be greatly appreciated.
Thanks,
Ross
From the code shown I would assume that it takes the current path as the location to look for the file. The current path is a bit unpredictable as certain operations effect its value and the value is persisted on each call. I.e. when another part of your application, or even another applciation, sets the current path this value is used the next time around. To set the current path it is enought to use a common dialog to browse for a certain file.
In your case I'd try to either to
specify the path explicitly by deriving it from one of the well known folders (e.g. the user's app path - look for Environment.GetFolderPath and Environment.SpecialFolder)
or
to resolve the path relative to your Dll's assembly path.
To find the assembly path for myType you can use the following code:
String strPath = System.IO.Path.GetDirectoryName(typeof(myType).Assembly.CodeBase);
In either case you should consider that in newer windows operating systems the user does not have write access to all paths of the system drive.

Categories