So I've been working on a new programm right now and I'm stuck at one function and I don't know how to solve this problem.
So I'm trying to make a button which searches and prints paths of files and folders which have a specific name. After I tried some functions and they all failed, I found this and it should work but it just doesn't print anything.
string[] files = Directory.GetFiles(#"C:\Program Files", "NameOfFileOrFolder",
SearchOption.AllDirectories);
foreach (var file in files)
{
Console.WriteLine(file);
}
Btw. the console does not even open itself...
You can try to read this: https://msdn.microsoft.com/en-us/library/ms143316(v=vs.110).aspx
Also you need administrator's privilege for using current path.
Related
The code, in both case is identical:
This is working and opening the text file in notepad
editor = "notepad.exe";
if (File.Exists(briefingFile))
{
Process.Start(editor, briefingFile);
}
This one does is not work:
editor = "notepad++.exe";
if (File.Exists(briefingFile))
{
Process.Start(editor, briefingFile);
}
It is the same test file and I have notepad++ installed. I Also tried to specify notepad++ with full path but the result is the same.
Instead of opening notepad++ I get the attached error messages which tries to create new file or open missing files.
The notepad.exe file is part of Windows and lives in the Windows folder, which is part of the default search path (an environment variable). Notepad++.exe is not part of Windows, and so its home folder is not part of the default search path.
Therefore, to open a process using Notepad++ you must also know the full path to the program.
When trying the full path, make sure you escape the folder separator characters properly, and you must make sure to account for spaces in your path. In this case, the reason you see the C:\Program error is because you haven't yet accounted for the space in Program Files.
editor = #"""C:\Program Files\Notepad++\notepad++.exe""";
try
{
Process.Start(editor, briefingFile);
}
catch(Exception ex)
{
// Do something here
}
Also note how I switched to an exception handler instead of File.Exists(). Disk I/O is one of those rare places where you should prefer handling the exception. File.Exists() is particularly bad for this, and should be avoided.
One other option here is if you have enough control for your target machines to know for sure Notepad++ is even installed, then you also have enough control register it as the default program for the files types your using, meaning you can skip selecting a program name at all:
Process.Start(briefingFile);
The solution is to use double quotes in the text file, not in the application.
In my case:
change:
Process.Start(editor, briefingFile);
to
Process.Start(editor, $#"""{briefingFile}""");
The "editor" is a full path to the editor.
There is nothing wrong with your code, although, as Joel stated, there are drawbacks to using File.Exists(). You should only need to make sure that the Notepad++ folder is in your User/System Environment PATH variables. I added the path for my Notepad++ folder on this PC, which is just C:\Program Files\Notepad++\, and ran the same code and it opens the file in Notepad++ just fine.
I ran the below code in an empty .NET 3.1 forms project and it can execute just fine. Do you still get your error in a new project?
OpenFileDialog fileDialog= new OpenFileDialog();
fileDialog.Filter = "All Files (*.*)|*.*";
fileDialog.FilterIndex = 1;
string editor = "";
if (fialDialog.ShowDialog() == DialogResult.OK)
{
editor = fileDialog.FileName;
}
//Added the escaped quotes to the front & back of this in case the path contains spaces.
var filePath = #"""C:\SOMELOCALFILEPATH\test.txt""";
if (File.Exists(filePath))
{
Process.Start(editor, filePath);
}
I set a break point and my editor is in this format when Process.Start executes: "C:\\Program Files\\Notepad++\\notepad++.exe"
I ran into this issue and had also exactly same two errors when I tried to open a .txt file which was installed under C:\Program Files (x86)\MyProgram\SecondFolder\MyTxt.txt
The problem was when I copied the file path from windows explorer and pasted it into Visual Studio it deleted the blank space between Files and (x86).
happens when pasted directly into VS to edit it later. Can be avoided if you paste the path into quotation marks
You have to check if the file path is correct. Otherwise it won't work.
My issue is this. I was creating a directory and filing it with files for running a specific process and on subsequent runs it would delete the directory, recreate it and start filling it with files.
root\scripts\'Many files'
All this code seemed to run fine without errors until I opened up my Windows Explorer window and navigated into the 'scripts' directory. When I would run it again it would kick me out of the folder as expected when it deleted, but it would throw an exception trying to add files to the directory, and when I looked the 'scripts' directory didn't even exits.
DirectoryNotFoundException was caught: Could not find a part of the path
My Code looked like this.
if (Directory.Exists(scriptsDirectory))
Directory.Delete(scriptsDirectory, true);
Directory.Create(scriptsDirectory));
File.WriteAllText(scriptsDirectory + fileName, output);
I looked on the internet and found this: Windows Explorer and Directory.Delete()
It seems there's something odd with Windows Explorer, but my issue was different. It wouldn't throw an exception on delete, but when I was trying to add files to the directory, b/c the createDirectory didn't seem to fire while I was in the directory.
My solution is below.
My solution was instead of Deleting the Directory, I instead deleted all the files from the directory, and that worked for me.
if (Directory.Exists(strScriptsDirectory))
{
DirectoryInfo directoryInfo = new DirectoryInfo(strScriptsDirectory);
// Delete the files
foreach (FileInfo fileInfo in directoryInfo.GetFiles())
fileInfo.Delete();
// Delete the directories here if you need to.
}
else
Directory.CreateDirectory(strScriptsDirectory);
This fix might not work well for all solutions and the solution provided in the link doesn't seem too great.
Another solution we tired was too write a while (true) loop that had a try catch to try to create the directory and add a file to it (if the add file caused an exception it would be caught and try again) and if it succeeded it would delete the test file and break out of the while.
Does anyone have any cleaner solutions that would allow you to delete a directory and recreate without having to worry about if a user is within an Explorer window?
I'm trying to make my image viewer app work with files that are opened by clicking an image file directly inside a Zip folder (using windows explorer to browse Zip files). The application seems to be run with correct command line, which looks like this:
"C:\myApp.exe" "C:\Users\Admin\AppData\Local\Temp\Temp1_Wallpapers.zip\Wallpaper1.jpg"
The file is being read with the following code:
using (var fs = new FileStream(path, FileMode.Open))
And the exception is thrown at that line:
Exception:Thrown: "Access to the path 'C:\Users\Admin\AppData\Local\Temp\Temp1_Wallpapers.zip\Wallpaper1.jpg' is denied." (System.UnauthorizedAccessException)
A System.UnauthorizedAccessException was thrown: "Access to the path 'C:\Users\Admin\AppData\Local\Temp\Temp1_Wallpapers.zip\Wallpaper1.jpg' is denied."
I figured this may be a problem with how the path is interpreted. There's a .zip in the middle of it, so this could be the problem, but I don't know how to solve that.
Also, simply opening a file at that path directly (not through zipped folder explorer window) results in the same exception.
Windows Explorer gains the ability to treat a .zip archive as a folder through a shell name extension handler. Such handlers extend the capability of the shell. But that's however restricted to shell functions only, it doesn't automagically make the low-level file access functions capable of doing the same. Like FileStream.
You'll need to copy the file out of the .zip archive first, then you can open it with FileStream. Lots of .zip support libraries around, SharpZipLib and DotNetZip are popular. It got finally added to .NET 4.5 with the System.IO.Compression.ZipArchive class. Let's pick that one for the most future-proof example code.
I created an Example.zip archive with a single image and copied it to my temp directory. This code retrieved it and made it the background image of a Winforms form:
using System.IO;
using System.IO.Compression; // Add reference to System.IO.Compression
...
private void button1_Click(object sender, EventArgs e) {
var srcePath = #"c:\users\hpass_000\appdata\local\temp\example.zip";
using (var file = new FileStream(srcePath, FileMode.Open)) {
var zip = new ZipArchive(file, ZipArchiveMode.Read);
var entry = zip.GetEntry("Chrysanthemum.jpg");
var destPath = Path.GetTempFileName();
using (var srce = entry.Open())
using (var dest = new FileStream(destPath, FileMode.Create)) {
srce.CopyTo(dest);
}
using (var img = Image.FromFile(destPath)) {
this.BackgroundImage = new Bitmap(img);
}
File.Delete(destPath);
}
}
I just found out what the problem was. Files extracted from compressed folders into temp folder will have read-only attribute, which my image viewer app apparently can't handle and throws UnauthorizedAccessException. I just need to remove that attribute and everything will be fine. Guess trying to read read-only files is an access violation of sorts.
The issue has nothing to do with the . in the temp file path because periods are legal in file names as well as directory names.
As you expect, opening a Zip folder in the shell and opening a file automatically extracts the contents to a temp folder, which is just a normal folder. The only thing that looks strange here is that it's opening the Administrator temp folder. Are you running the exe as a normal user? If the exe and shell are running under separate users, the exe may not be able to access the temp folder used by the shell.
When I try to rename a Directory using the following code:
try
{
System.IO.Directory.Move(oldPath, newPath);
}
catch (System.IO.IOException e2)
{
Console.WriteLine(e2.Message);
}
I get the following exception: The process cannot access the file because it is being used by another process.
I don't understand why it says "file" in the first place.
Also, the directory is empty. What file is it referring to?
Lastly, how to manage to rename the Directory without any exceptions?
UPDATE: I guess I found the reason for the exception, it is because I am trying to rename the file/folder names of files/folders situated in the Google Drive. The Google Drive application is the other process using it! Any solutions to rename a folder in the Google Drive? But the weird thing is that I don't get this exception when I try to rename files located in the Google Drive through C#.
Thanks!
Your folder seems to be in use by another process. Try to close your explorer or other programs, that use that folder. If nothing help - try to restart your machine. If those won't help - consider using Unlocker to free folder from usage of another process. Note that it would be weird, if non-system folder is occupied after restart of the machine
It says "file" because the underlying commands are probably using a
generic move command for both directories and files and the
localized error string contains the word file.
Even if a directory is empty, it can be locked for any edits if you have it "open" in an application (do you have explorer Windows open in the directory, is the command prompt current directory set to the one you want to move/delete)?
Unfortunately there's not much you can do unless you want to start killing offending processes programmatically.
You can use Process Explorer to find the process that has a lock on that folder. See http://windowsxp.mvps.org/processlock.htm for more info.
1 Verify that newPath already does not exist
http://msdn.microsoft.com/en-us/library/system.io.directory.move.aspx
2 Verify that your directory does not contain opened file
Say I have this file structure
Soultion-> Folder1 -> FileIwant.html
So this could be something like C:\Soultion\Folder1\FilterIwant.html
Now I need to read this file into my application. I can't just hardcode it since when I give it to someone else they might put it on F: drive or something.
Or when I create a msi file the path might be completely different. So how can I say maybe take
"Folder1\FilterIwant.html"
and use that to get the folder path regardless of where they put it?
Edit
I tried Path.GetFullPath but I land up in the bin/debug directory. But my file is not in that directory. I think it is a couple directories before. Also if I make a msi file will I have bin/debug directory?
Why is a file which is used as part of your application not in the same folder as the application? It sounds to me like you should set the properties on that file to copy to the output folder when you do a build.
Doing that will make sure your file is in the bin\debug folder.
EDIT:
either that or you should be placing your files in one of the special folders, app data or my documents spring to mind.
When Visual Studio compiles your project, it will be putting the output into the bin\debug directory. Any content files that you want to reference must also be copied to those locations, in order for your app residing in that directory to be able to read that file.
You have two choices:
either you set the Copy to Output Directory property on your FilterIwant.html to Copy if newer; in that case, if the file has changed, it will be copied to the output directory, and you should be able to reference it and load it there
or
you just define a path in your app.config, something like DataPath, and set it to your folder where the file resides. From your app, you then create the full path name for that file as Path.Combine(AppSettings["DataPath"], "FilterIwant.html") - with this approach, you become totally independant of where the file really is and you don't need to move around anything. Also: this gives you the opportunity to create an admin/config utility for your users later on, so that they can pick any directory they like, and your app will find those files there.
In my console app, I started with the debug directory until i found the closest parent folder I wanted.
static void Main(string[] args)
{
Console.WriteLine("Start");
var debugDir = Environment.CurrentDirectory;
DirectoryInfo di = new DirectoryInfo(debugDir);
var searchDir = "";
while (!di.FullName.ToLower().EndsWith("Folder1"))
{
if(di.FullName.ToLower().EndsWith(":")) //if you went too far up as in "D:" then
break;
di = di.Parent;
}
Console.WriteLine(di.FullName);
}
You need the help of System.Io.Path class:
GetFullPath: Returns the absolute path for the specified path string.
Edit:
You might also need the application directory - this is where your application will be installed:
string appPath = Path.GetDirectoryName(Application.ExecutablePath);
Path.GetFullPath
Edit
The bin/Debug path will not be present when you run your installed application (unless you specifically tell the installer to use that subdirectory, of course).
You probably want to pass the full path as a command line argument. You can then get the argument using the args parameter of the Main method. To convert a relative path to an absolute one you can use Path.GetFullPath:
using System;
using System.IO;
public class CommandLine
{
public static void Main(string[] args)
{
// The path is passed as the first argument
string fileName = arg[0];
// get absolute path
fileName = Path.GetFullPath(fileName);
// TODO: do whatever needs to done with the passed file name
}
}