Savefiledialog locked file, change file name - c#

How to keep the savefilediallog open when you write to a file which is in use by an other program so that you can change the file name and try to save again?
private void button1_Click_2(object sender, EventArgs e)
{
Cursor.Current = Cursors.WaitCursor;
CsvExport = Class_ExportData.DataTableToCSV(datatabelControle, csvSCheidingteken);
Cursor.Current = Cursors.Default;
saveFileDialog1.OverwritePrompt = true;
saveFileDialog1.Filter = "Komma gescheiden waarden (*.csv)|*.csv|Tekst bestanden (*.txt)|*.txt|Alle formaten (*.*)|*.*";
saveFileDialog1.DefaultExt = "csv";
saveFileDialog1.AddExtension = true;
saveFileDialog1.ShowDialog();
}
private void saveFileDialog1_FileOk(object sender, CancelEventArgs e)
{
try
{
string name = saveFileDialog1.FileName; // Get file name.
File.WriteAllText(name, CsvExport); // Write to the file name selected.
}
catch (Exception ex)
{
//file is locked, how to get back to the open save file dialog ???
}
}

Try this. Move the code associated with opening the saveFileDialog1 into its own function and invoke that function from button1_Click:
private void button1_Click_2(object sender, EventArgs e)
{
Cursor.Current = Cursors.WaitCursor;
CsvExport = Class_ExportData.DataTableToCSV(datatabelControle, csvSCheidingteken);
Cursor.Current = Cursors.Default;
ShowSaveFileDialog();
}
private void ShowSaveFileDialog()
{
saveFileDialog1.OverwritePrompt = true;
saveFileDialog1.Filter = "Komma gescheiden waarden (*.csv)|*.csv|Tekst bestanden (*.txt)|*.txt|Alle formaten (*.*)|*.*";
saveFileDialog1.DefaultExt = "csv";
saveFileDialog1.AddExtension = true;
saveFileDialog1.ShowDialog();
}
EDIT: On further consideration, I don't think you want/need the loop here, so I've removed it. You still want to invoke the ShowSaveFileDialog method here in case of exceptions, though:
private void saveFileDialog1_FileOk(object sender, CancelEventArgs e)
{
try
{
string name = saveFileDialog1.FileName; // Get file name.
File.WriteAllText(name, CsvExport); // Write to the file name selected.
return;
}
catch (Exception ex)
{
//file is locked, how to get back to the open save file dialog ???
// maybe display an error message here so that the user knows why they're about to see the dialog again.
}
ShowSaveFileDialog();
}
Technically, this can probably lead to a StackOverflowException if the user tries repeatedly (and I mean thousands of times) to retry the save after an exception, but that's pretty unlikely.

Related

C# WPF FileSaving Exception encountered

My issue is that I keep seeing a recurring theme with trying to allow my Notepad clone to save a file. Whenever I try to save a file, regardless of the location on the hard disk, the UnauthorizedAccess Exception continues to be thrown. Below is my sample code for what I've done, and I have tried researching this since last night to no avail. Any help would be greatly appreciated.
//located at base class level
private const string fileFilter = "Text Files|*.txt|All Files|*.*";
private string currentPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
private void MenuFileSaveAs_Click(object sender, RoutedEventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.DefaultExt = "*.txt";
sfd.Filter = fileFilter;
sfd.AddExtension = true;
sfd.InitialDirectory = currentPath;
sfd.RestoreDirectory = true;
sfd.OverwritePrompt = true;
sfd.ShowDialog();
try
{
System.IO.File.WriteAllText(currentPath,TxtBox.Text,Encoding.UTF8);
}
catch (ArgumentException)
{
// Do nothing
}
catch(UnauthorizedAccessException)
{
MessageBox.Show("Access Denied");
}
}
Change the following lines.
...
if (sfd.ShowDialog() != true)
return;
try
{
using (var stream = sfd.OpenFile())
using (var writer = new StreamWriter(stream, Encoding.UTF8))
{
writer.Write(TxtBox.Text);
}
}
...
I hope it helps you.
You need to get the correct path context and file object from the dialog box once the user has hit 'ok'. Namely verify the user actually hit ok and then use the OpenFile property to see what their file selection is:
if (sfd.ShowDialog.HasValue && sfd.ShowDialog)
{
if (sfd.OpenFile() != null)
{
// convert your text to byte and .write()
sfd.OpenFile.Close();
}
}

Open a directory and process files/folders in background worker query

I have the following code, I'm trying to open a directory and process the files in it via the Background worker but I am having issues with it.
The error I have is (The name filePath does not exist in the current context), which I can understand because it's stored in another method? if someone could point out to me what is wrong with my code it would be appreciated. Folderbrowser doesn't work under the Background worker section.
private void btnFiles_Click(object sender, EventArgs e)
{
//btnFiles.Enabled = false;
btnSTOP.Enabled = true;
//Clear text fields
listBoxResults.Items.Clear();
listBoxPath.Items.Clear();
txtItemsFound.Text = String.Empty;
//Open folder browser for user to select the folder to scan
DialogResult result = folderBrowserDialog1.ShowDialog();
if (result == DialogResult.OK)
{
//Store selected folder path
string filePath = folderBrowserDialog1.SelectedPath;
}
//Start the async operation here
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//Process the folder
try
{
foreach (string dir in Alphaleonis.Win32.Filesystem.Directory.EnumerateFiles(filePath, "*.*", SearchOption.AllDirectories, true))
{
//Populate List Box with all files found
this.Invoke(new Action(() => listUpdate2(dir)));
FileInfo fi = new FileInfo(dir);
if (fi.Length == 0)
{
//Populate List Box with all empty files found
this.Invoke(new Action(() => listUpdate1(dir + Environment.NewLine)));
}
}
}
//Catch exceptions
catch (Exception err)
{
// This code just writes out the message and continues to recurse.
log.Add(err.Message);
//throw;
}
finally
{
//add a count of the empty files here
txtItemsFound.Text = listBoxResults.Items.Count.ToString();
// Write out all the files that could not be processed.
foreach (string s in log)
{
this.Invoke(new Action(() => listUpdate1(s)));
}
log.Clear();
MessageBox.Show("Scanning Complete", "Done", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
//If cancel button was pressed while the execution is in progress
//Change the state from cancellation ---> cancelled
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
//backgroundWorker1.ReportProgress(0);
return;
}
//}
//Report 100% completion on operation completed
backgroundWorker1.ReportProgress(100);
}
#DonBoitnott solution is the most general for data flow inside class. Specifically to BackgroundWorker there is another one exists
private void btnFiles_Click(object sender, EventArgs e)
{
...
// pass folder name
backgroundWorker1.RunWorkerAsync(folderBrowserDialog1.SelectedPath);
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// get passed folder name
string filePath = (string)e.Argument;
...
}
The variable "filePath" is being declared local to the btnFiles_Click method. In order for it to be used elsewhere, it must be declared global to the code page:
public class Form1
{
private String _filePath = null;
private void btnFiles_Click(object sender, EventArgs e)
{
//get your file and assign _filePath here...
_filePath = folderBrowserDialog1.SelectedPath;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//use _filePath here...
}
}

SaveFileDialog event FileOk

private void button2_Click(object sender, EventArgs e)
{
SaveFileDialog Sdialog = new SaveFileDialog();
Sdialog.ShowDialog();
Sdialog.FileOk += Sdialog_FileOk;
}
void Sdialog_FileOk(object sender, CancelEventArgs e)
{
try
{
StreamWriter FileProtocol = new StreamWriter(((SaveFileDialog)sender).FileName);
FileProtocol.Write(textBox3.Text);
FileProtocol.Close();
MessageBox.Show("File is write ok");
}
catch (Exception)
{
MessageBox.Show("Unknown Error. File is not write");
}
}
Why does event FileOk not work?
Because you need to hook the event up before calling ShowDialog(). When you call ShowDialog() it stops processing on that thread and waits for a response.
So, instead of this:
Sdialog.ShowDialog();
Sdialog.FileOk += Sdialog_FileOk;
do this:
Sdialog.FileOk += Sdialog_FileOk;
Sdialog.ShowDialog();
To use the DialogResult to simplify you're workflow, just do this:
if (Sdialog.ShowDialog() == DialogResult.OK)
{
try
{
StreamWriter FileProtocol =
new StreamWriter(Sdialog.FileName);
FileProtocol.Write(textBox3.Text);
FileProtocol.Close();
MessageBox.Show("File is write ok");
}
catch (Exception)
{
MessageBox.Show("Unknown Error. File is not write");
}
}
ALSO: instead of doing this:
StreamWriter FileProtocol =
new StreamWriter(Sdialog.FileName);
FileProtocol.Write(textBox3.Text);
FileProtocol.Close();
how about simplify it to this:
File.AppendAllText(Sdialog.FileName, textBox3.Text);
The benefit is two fold:
The code is clearly much more concise, and;
The code is safer because it manages the un-managed resources appropriately for you.

how do I recall a string from a different function?

I am having trouble calling the string "rlist" from:
public void main()
{
string rlist;
if (radioButton1.Checked)
textBox1.Enabled = false;
textBox1.ReadOnly = true;
rlist = "text";
}
to
public void button1_Click(object sender, EventArgs e)
{
OpenFileDialog openFile = new OpenFileDialog();
openFile.Filter = "WTF Files (*.wtf)|*.wtf";
openFile.Title = "Please Pick your realmlist file:";
if (openFile.ShowDialog() == DialogResult.Cancel)
return;
try
{
textBox5.Text = openFile.FileName;
string file = openFile.FileName;
TextWriter rlist_writer = new StreamWriter (openFile.FileName);
rlist_writer.WriteLine(rlist);
rlist_writer.Close();
}
catch (Exception)
{
MessageBox.Show("Error opening file", "File Error",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
I get the error on this line:
rlist_writer.WriteLine(rlist);
is it possible to call a string from one function and send it to the other with the same value it had in the function it was originally pulled from?
By the sounds of your question,
Your string is local to your main function.
So judging by your method names and knowledge of winforms(presumed again)
you need to make your string class level
string rlist;
public void main()
{
rlist = "yay"
public void button1_Click(object sender, EventArgs e)
{
someText = rlist;
As it currently stands you are not able to, as temporary (local) variables will be cleaned through garbage collection when you leave the method
Edit
You may wish to review this also
try
{
textBox5.Text = openFile.FileName;
using(TextWriter rlist_writer = new StreamWriter (openFile.FileName))
{
rlist_writer.WriteLine(rlist);
}
}
You can define that variable in your class scope, then if you call that variable in your button_click event, it will maintain the same value as in your main method.

In C# while creating a file second time will throw an exception

I am creating a file using file stream, but before that i am applying if condition to see if the file exist or not. When i click on button and if supppose file is there it deletes the file. Its ok, and again if i press the button the file gets created. At first time it works well.
Now the file is created, again if I press the button and it should delete but it is trhowing an exception saying that*The process cannot access the file 'C:\Hello1' because it is being used by another process.*
Below is my code
private void button2_Click(object sender, EventArgs e)
{
string fileName = #"C:\Hello1";
if
(File.Exists(fileName))
{
File.Delete(fileName);
MessageBox.Show("File is deleted");
}
else
{
FileInfo createFile = new FileInfo(fileName);
FileStream create = createFile.Create();
MessageBox.Show("Created");
}
}
So why I am not able to delete second time, My text file is not open also but still it is showing the exception.
You're never closing your stream that created the file. Put your FileStream in a using statement, which will automatically clean up the open file handle.
using(FileStream create = createFile.Create())
{
//code here
}
The file stream is still opened when you're trying second time, try this:
private void button2_Click(object sender, EventArgs e)
{
string fileName = #"C:\Hello1";
if
(File.Exists(fileName))
{
File.Delete(fileName);
MessageBox.Show("File is deleted");
}
else
{
FileInfo createFile = new FileInfo(fileName);
using(FileStream create = createFile.Create())
{
MessageBox.Show("Created");
}
}
}
Oh yes i got the answer,
I need to use
private void button2_Click(object sender, EventArgs e)
{
string fileName = #"C:\Hello1";
if
(File.Exists(fileName))
{
File.Delete(fileName);
MessageBox.Show("File is deleted");
}
else
{
FileInfo createFile = new FileInfo(fileName);
FileStream create = createFile.Create();
MessageBox.Show("Created");
create.Close();
}
}
We need to use create.Close();
Here is an example I used to write a local log:
StreamWriter log;
string fpath = string.Format(#"{0}\{1}.txt",GetDirectory(),DateTime.Now.ToString("yyy-MM-dd"));
if (!File.Exists(fpath))
{
log = new StreamWriter(fpath);
}
else
{
log = File.AppendText(fpath);
}
log.WriteLine(string.Format("{0} ==> {1}",DateTime.Now.ToString("MM/dd/yyy HH:mm:ss"), Message));
log.Dispose();
log = null;

Categories

Resources