I want to delete a file, in case it is locked by another process even though I have set try catch, but the program is still dark cash at fi.Delete(), so how to fix it.
A first chance exception of type 'System.UnauthorizedAccessException'
occurred in mscorlib.dll
Additional information: Access to the path 'H:\J\R\sound.MP4' is
denied.
private void GView_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e)
{
try
{
string cellValue = GView.Rows[e.RowIndex].Cells["NAME"].Value.ToString();
var confirmResult = MessageBox.Show("delete this item " + cellValue,
"Confirm Delete!!",
MessageBoxButtons.YesNo);
if (confirmResult == DialogResult.Yes)
{
System.IO.FileInfo fi = new System.IO.FileInfo(cellValue);
fi.Delete();
}
else
{
}
}
catch (UnauthorizedAccessException ex)
{
MessageBox.Show(ex.Message);
}
}
private void GView_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e)
{
try
{
string cellValue = GView.Rows[e.RowIndex].Cells["NAME"].Value.ToString();
var confirmResult = MessageBox.Show("delete this item " + cellValue,
"Confirm Delete!!",
MessageBoxButtons.YesNo);
if (confirmResult == DialogResult.Yes)
{
System.IO.FileInfo fi = new System.IO.FileInfo(cellValue);
fi.Delete();
}
else
{
}
}
catch(System.IO.IOException)
{
// exception when file is in use or any other
}
catch (UnauthorizedAccessException ex)
{
MessageBox.Show(ex.Message);
}
catch(Exception ex)
{
// all other
}
}
I read this article, as suggested by #Keyur PATEL, and figuring out this is a configuration of Visual Studio, I solved it by doing the following:
Navigate to "Debug / Exceptions / Common Language Runtime Exceptions / System"
Scroll down to where "NullReferenceException" is, and uncheck the "throw" checkbox, and check the "user-handled".
Thanks for your help
The user, whose account is used to run your application, must have access to that path
There are 2 ways to achieve this:
Configure a special application pool for your application, that will run under a user that has necessary permissions (can access admin shares on remote server). So your entire application will run under that account and have all its permissions.
Using impersonation to execute parts of your code under another account. This doesn't require any IIS configuration and is more secure and flexible than first way (for example? you can impersonate several accounts in a single application).
Related
Good day.
In my C# windows forms app, I would like to open .pdf files.
The code to do this is:
private void btnOpenPdf_Click(object sender, EventArgs e)
{
try
{
System.Diagnostics.Process.Start(lblPdf.Text);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
The .pdf file paths are storred in an SQL database.
They are stored in this manner: C:\Folder1\Folder2\File Name
In this example this means:
lblPdf.Text="C:\Folder1\Folder2\File Name";
*note: File Name(s) is/are stored without file type (so no .pdf at the end)
Of course this doesn't work, so I added the "#" and ".pdf" to the string:
lblTest.Text = ("#" + "\"" + lblPdf.Text + ".pdf" + "\"");
When I test this with a Message Box:
MessageBox.Show(lblTest);
I get:
#"C:\Folder1\Folder2\File Name.pdf"
The trouble I am experiencing is that this works:
private void btnOpenPdf_Click(object sender, EventArgs e)
{
try
{
MessageBox.Show(lblTest.Text);
System.Diagnostics.Process.Start(#"C:\Folder1\Folder2\File Name.pdf");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
and this does not work:
private void btnOpenPdf_Click(object sender, EventArgs e)
{
try
{
MessageBox.Show(lblTest.Text);
System.Diagnostics.Process.Start(lblTest.Text);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Can anyone shed a light on why this is so?
The error message I receive in the second example is:
"The system cannot find the file specified"
MessageBox.Show gives me the correct syntax and file path in both cases.
Thank you.
#Shovers and anyone else to whom it may concern:
private void btnOpenPdf_Click(object sender, EventArgs e)
{
lblTest.Text = ("#" +lblPdf.Text + ".pdf" );
try
{
MessageBox.Show(lblTest.Text);
System.Diagnostics.Process.Start(lblTest.Text);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Thanks guys.
Just adding the
+ ".pdf"
to the label (lblPdf.Text) is the answer.
private void btnOpenPdf_Click(object sender, EventArgs e)
{
try
{
System.Diagnostics.Process.Start(lblPdf.Text + ".pdf");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I can give you a number of hints:
1 Exceptions
Proper exception handling is a pet peeve of mine and yours is problematic. Your code handles fatal exceptions. And never catching fatal exceptions is a very important part. Doing it will only get you more and less understandable followup errors. Here are two artciles on the mater I do link often:
https://blogs.msdn.microsoft.com/ericlippert/2008/09/10/vexing-exceptions/
https://www.codeproject.com/Articles/9538/Exception-Handling-Best-Practices-in-NET
2. How are those PDF stores with the Database?
PDFs are Binary Large Objects (BLOBS). Ther are two schools of tought on to store blobs with a DB and both affect wich path you have to give:
You store the blob itself in the DB. Usually that requires setting up a HTTP handler to provide the file for download/user consumption. In this case you need a URL to access those files
You store the files in the Filesystem. The DB only contains the paths. In this case you have to eitehr use the URL, Share path or whatever else way you got to download those files
SQL Filestream and equivalent attributes from other DB are a bit of a combination of the two. It works mostly like the 1st one, with performance closer to the 2nd one.
You might have some 4th bastardised version here. Or you simply did not understand how how to use the values in the DB.
having an issue when saving data, I am trying to set it up so if the user tries to save their name data for their character and a file already exists, it will create a second xml file "NameData2.xml" and so forth until a maximum of 3 files is reached, ( so the user has differant characters to choose from ) however at the moment it is simply creating 2 xml files at once all containing the same name ( i would guess this is due to them checking all at once in the same if else statements possibly? all i could find when trying to find an answer was how to check for a files existence and if it cant find it how to create one, i will post my code below if anyone has any suggestions that would be brilliant as im quite stumped!
Thankyou in advance.
// This will save the users generated name in a created file
// NameData.xml and will take the user to the partySelectionScreen.
private void continueButton_Click(object sender, RoutedEventArgs e)
{
try
{
NameSavingInformation nameInfo = new NameSavingInformation();
nameInfo.GeneratedName = generatedNameTexbox.Text;
SaveXml.SaveData(nameInfo, "NameData.xml");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
if(File.Exists("NameData.xml"))
{
NameSavingInformation nameInfo = new NameSavingInformation();
nameInfo.GeneratedName = generatedNameTexbox.Text;
SaveXml.SaveData(nameInfo, "NameData2.xml");
}
else if (File.Exists("NameData2.xml"))
{
NameSavingInformation nameInfo = new NameSavingInformation();
nameInfo.GeneratedName = generatedNameTexbox.Text;
SaveXml.SaveData(nameInfo, "NameData3.xml");
}
else if (File.Exists("NameData3.xml"))
{
MessageBox.Show("You have passed the limit of existing characters" +
"To continue please return to the main menu and delete at least 1 character");
}
You should do like this.
This will perform a a search on the files that doesn't exists and will generate them. This will permit the user to delete any character the wants without breaking the algorithm.
private void continueButton_Click(object sender, RoutedEventArgs e)
{
if(!File.Exists("NameData.xml"))
{
SaveFileInfo("NameData.xml");
}
else if (!File.Exists("NameData2.xml"))
{
SaveFileInfo("NameData2.xml");
}
else if (!File.Exists("NameData3.xml"))
{
SaveFileInfo("NameData3.xml");
}
else
{
MessageBox.Show("You have passed the limit of existing characters" +
"To continue please return to the main menu and delete at least 1 character");
}
}
public SaveFileInfo(string fileName)
{
try
{
NameSavingInformation nameInfo = new NameSavingInformation();
nameInfo.GeneratedName = generatedNameTexbox.Text;
SaveXml.SaveData(nameInfo, fileName);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
when deleting files one by one error is generated as "the process cannot access the file ' because it is being used by another process when trying to delete file"
code : any suggestions for delete files like this ?
private void DeleteFilesFromDestination()
{
string consolidatedFolder = System.Configuration.ConfigurationManager.AppSettings["path"].ToString();
foreach (String file in ListBoxDeleteFiles.Items)
{
try
{
// delete each selected files from the specified TargetFolder
if (System.IO.File.Exists(consolidatedFolder + #"\" + System.IO.Path.GetFileName(file)))
{
proc.WaitForExit();
System.IO.File.Delete(consolidatedFolder + #"\" + System.IO.Path.GetFileName(file));
}
}
catch (Exception ex)
{
MessageBox.Show("Error Could not Delete file from disk " + ex.Message, "Shipment Instruction",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
}
NB : the image will be loaded to a flowlayout pannel like this
//Open the files to see
private void ListBoxSourceFiles_Click(object sender, EventArgs e)
{
try
{
if (ListBoxSourceFiles.SelectedItem != null || !ListBoxSourceFiles.SelectedItem.Equals(string.Empty))
{
//MessageBox.Show("Selected " + ListBoxSourceFiles.SelectedItem);
PictureBox pb = new PictureBox();
Image loadedImage = null;
loadedImage = Image.FromFile(ListBoxSourceFiles.SelectedItem.ToString());
pb.Height = loadedImage.Height;
pb.Width = loadedImage.Width;
pb.Image = loadedImage;
flowLayoutPanel1.Controls.Clear();
flowLayoutPanel1.Controls.Add(pb);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ship Instruction",
MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
}
You don't say specifically what file you're trying to delete, but from your question it sounds like you're trying to delete the image file that you loaded. If that's the case, then you have a problem. The documentation for Image.FromFile says:
The file remains locked until the Image is disposed.
If you need the ability to delete the file, you'll want to copy the image after you've loaded it, and use that image in your PictureBox. Then you can dispose the loaded image, thereby unlocking the file.
You will not be able to delete any file when is is locked by another process.
You first have to find out which process locks the file.
This is possible with SysInternals ProcessExplorer. Use the "Find handle or DLL" function.
If the file is in use you cannot delete it. However, if you for some reason really want to delete it and you are unable to stop the process that is locking the file (like when uninstalling an application) you can schedule the file for deletion the next time the operating system is restarted. These scheduled deletions are performed before any process is able to lock the file.
You have to use the MoveFileEx Windows API using a null new file name and the flag MOVEFILE_DELAY_UNTIL_REBOOT. How to do that from C# is explained in an answer to the Stack Overflow question “MoveFile” function in C# (Delete file after reboot) C#.
pb.Image.Dispose();
pb.Dispose();
After steps above, tou can use picture again
I am making a software that will move files from the downloads folder to a specific sub folder in a directory. The sub folder is selected by the user by a combobox. I keep getting this error: System.IO.IOException: Cannot create a file when that file already exists. Also, these error come up on people's computer who install my program...exceptions and things. How do i turn it off. Also, why do i get this error? Here is my code:
string pathUser4 = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
string pathDownload4 = (pathUser4 + #"\Downloads\");
string sourceFile = pathDownload4 + listBox1.Text;
string pathdoc5 = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string pathDownload5 = (pathdoc5 + #"\iracing\setups\");
string destinationFile = pathDownload5 + comboBox1.Text;
File.Move(sourceFile, destinationFile);
if (comboBox1.Text == "Select File Destination")
{
MessageBox.Show("Please Select A Destination Folder", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
Each File.Move should be wrapped in a try/catch block as you can never expect an IO operation to execute without error. It could be something as simple as the user having a file handle open, or the file existing in the destination folder, either way, you don't want a single file to throw an exception that stops the entire operation. You will want to catch the exceptions and log them either to an error log file or to the event log, this way you can see the errors that occurred but it will not interrupt anything.
Secondly, for any desktop application I would add global error handling to log any uncaught errors. You can do this by putting this code at the beginning of your program,
AppDomain.CurrentDomain.UnhandledException += (a, exception) => File.AppendAllText("errorlog.txt", exception.ToString() + "\n"
This will keep the user from ever seeing ugly exceptions being thrown. Also be sure you are not giving the users the .pdb files as this will cause exceptions to contain paths of the computer it was compiled on which can contain your username and other sensitive information you wouldn't want a client to see.
You can register the global exception handling when the main window is initialized, you want it to be the first thing you do before any thing else because again you never know when an exception will be thrown so you have to think defensively.
public partial class MainWindow : Window
{
public MainWindow()
{
AppDomain.CurrentDomain.UnhandledException += (a, exception) => File.AppendAllText("errorlog.txt", exception.ToString() + "\n");
InitializeComponent();
}
}
C# uses exceptions extensively so it will be good concept for you to study up on if you are not familiar with this type of error handling. All exceptions derive from the Exception class so when you write catch (Exception e) this will catch all exceptions (because a base reference can hold an object of a derived type), however if you know the specific exception a method will throw you can catch a more specific exception (always before the more general catch) and handle it in a specific way. In this example you may have an IOException from the File.Move() that you want to catch and handle differently.
try
{
string pathUser4 = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
string pathDownload4 = (pathUser4 + #"\Downloads\");
string sourceFile = pathDownload4 + listBox1.Text;
string pathdoc5 = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string pathDownload5 = (pathdoc5 + #"\iracing\setups\");
string destinationFile = pathDownload5 + comboBox1.Text;
File.Move(sourceFile, destinationFile);
if (comboBox1.Text == "Select File Destination")
{
MessageBox.Show("Please Select A Destination Folder", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
catch (Exception e)
{
File.AppendAllText("ErrorLog.txt", e.ToString() + "\n");
}
The example code from MSDN for File.Move should get you pointed at the various things you need to deal with, such as an already existing file and basic error handling.
using System;
using System.IO;
class Test
{
public static void Main()
{
string path = #"c:\temp\MyTest.txt";
string path2 = #"c:\temp2\MyTest.txt";
try
{
if (!File.Exists(path))
{
// This statement ensures that the file is created,
// but the handle is not kept.
using (FileStream fs = File.Create(path)) {}
}
// Ensure that the target does not exist.
if (File.Exists(path2))
File.Delete(path2);
// Move the file.
File.Move(path, path2);
Console.WriteLine("{0} was moved to {1}.", path, path2);
// See if the original exists now.
if (File.Exists(path))
{
Console.WriteLine("The original file still exists, which is unexpected.");
}
else
{
Console.WriteLine("The original file no longer exists, which is expected.");
}
}
catch (Exception e)
{
Console.WriteLine("The process failed: {0}", e.ToString());
}
}
}
The error may caused by your code, or by some invalid input.
As #Despertar mentioned, I suggest all the program include error handling and log features in your code. It will be very helpful for your debug.
But I suggest use open source log library, not do it by yourself. For example, log4net, NLog, etc.
I have this simple code:
System.Drawing.Bitmap bm = bitmapSourceToBitmap(source);
try
{
bm.Save(#"C:\Seva\testeImagem.jpg");
}
catch (Exception ex)
{
}
This throws: Generic Error GDI+.
Anyway, I seached and people say that the problem is with permissions. How can I give permissions to it? Thanks
First find out under what credentials the code is running.
Then check (and, when needed, fix) the security/NTFS settings of the Seva folder.
Especially when this code is running from within a website or service the account will not have permissions to write to the folder.
instead of saving to C:\Seva\testeImagem.jpg why not try saving to
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
"testeImagem.jpg");
You must ensure that the Seva folder exists under C:\ and ensure that the current user has permissions to write to\create this folder. Also, its considered bad practice to write to folders that the user doesn't own. If the user is Running As A Normal User (not an admin) failure to do so results in permission exceptions.
Could you test if the folder exists?
void BitmapCopy(System.Drawing.Bitmap source, string filename) {
if (!String.IsNullOrEmpty(filename) && (source != null)) {
string dirName = #"C:\Seva";
if (!System.IO.Directory.Exists(dirName)) {
dirName = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
}
string bmpFile = System.IO.Path.Combine(dirName, filename);
System.Drawing.Bitmap bm = bitmapSourceToBitmap(source);
try {
bm.Save(bmpFile);
} catch (ArgumentNullException ex) {
Console.WriteLine(ex.Message);
} catch (System.Runtime.InteropServices.ExternalException ex) {
Console.WriteLine(ex.Message);
}
}
}