Set permissions on folder used by winform application - c#

My winform application periodically pulls a flash file from an SQL database, writes it to a temporary folder, displays it in a webbroswer control, and then deletes it from the temporary folder. My application creates the temporary folder if it does not exist. The temporary folder is located in 'System.Environment.CurrentDirectory'.
My problem is the permissions of the temporary folder frequently become read only and then my application cannot delete the file. Sometimes the problem occurs immediately, and sometimes I can run the application several times before it occurs.
How do I insure that the file is deleted?
I added code to delete the temporary folder and then re-create it each time it writes to it, but this did not resolve my problem.
Only my application needs to access this folder, and the folder only holds these flash images.
I thought about using the generic 'temp' folder, but read somewhere that that could lead to problems.
Also, I got the same problem when I located the temporary folder at 'D:\'.
I'm using VS2008 on Windows XP. The application is to run on XP, Vista and 7.
Here is code.
DataSet dsFlashQuizRandom = new DataSet();
dsFlashQuizRandom = objUserDAO.GetFlashQuizRandom(intAge);
if (dsFlashQuizRandom.Tables[0].Rows[0]["large_image_blob"] != null && dsFlashQuizRandom.Tables[0].Rows[0]["file_name"].ToString().Trim() != string.Empty)
{
byte[] b = (byte[])dsFlashQuizRandom.Tables[0].Rows[0]["large_image_blob"];
if (b != null)
{
string flashFileName = dsFlashQuizRandom.Tables[0].Rows[0]["file_name"].ToString().Trim();
string targetPath = System.Environment.CurrentDirectory.ToString() + #"\images\";
string strFileName = targetPath + flashFileName;
//Delete the current version of the folder (if it exists); then create a new version of it.
if (System.IO.Directory.Exists(targetPath))
System.IO.Directory.Delete(targetPath, true);
if (!System.IO.Directory.Exists(targetPath))
System.IO.Directory.CreateDirectory(targetPath);
//Write the file to a FileStream, assign that stream to the webbrowser control.
FileStream fs = new FileStream(strFileName, FileMode.CreateNew, FileAccess.Write);
fs.Write(b, 0, b.Length);
fs.Close();
webBrowserQuizFlash.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowserQuizFlash_DocumentCompleted);
webBrowserQuizFlash.Url = new System.Uri(strFileName, System.UriKind.Absolute);
}
}
//Delete the Flash Webbrowser file once it has completed loading.
private void webBrowserQuizFlash_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
FileInfo fi = new FileInfo(strFileName);
try
{
fi.Delete();
}
catch (IOException ex)
{
MessageBox.Show("IOException = " + ex); //test code
}
}
Any suggestions or a point in the right direction would be appreciated.
Cheers,
Frederick
PS--When copying my code to this post I see the color of the text is all red after the #"\images\"; Is there a problem with this part of my code, or is this a display artifact? Should I use this instead: #"\images\\";

You could use System.IO.Path.GetTempPath() to get a temp folder to use.
I assume that you're having problems with the delete due to the file being locked by some process. You might be able to get around that by using the MoveFileEx function to delete it at next reboot.

I think the accessing problem comes from another application that locks the file. One common application group that does such things would be the on access scanner from your anti-virus program.
To get a deeper look into, who accesses your file you should take a deeper look with Process Monitor to find out who will block your file.
Also you can maybe make a little change to your code:
//Write the file to a FileStream, assign that stream to the webbrowser control.
using(FileStream fs = new FileStream(strFileName, FileMode.CreateNew, FileAccess.Write))
{
fs.Write(b, 0, b.Length);
}

Related

C# System.IO.DirectoryNotFoundException: Could not find a part of the path

try
{
string directory = #"D:/user/user.txt";
FileStream FS = new FileStream(directory, FileMode.Append);
StreamWriter SW = new StreamWriter(FS);
string register;
register = $"{generateID()};{txtfirstName.Text};{txtLastName.Text};{txtUser.Text};{txtEmail.Text};{txtPersonalID.Text}";
SW.WriteLine(register);
SW.Close();
FS.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
I run this code in c# windows forms .NET framework and constanly i get the same message. I am in university and i am pretty new in programming so i have no idea what could be wrong. What are your thoughs? Any idea?
Your question is a little confusing. First of all, you shouldn't name your variable directory because in the end it is a file name and used as such.
(I'll ignore the difference between the image "D:\user\user.txt" and the code "D.:\user\user.txt" and will assume you actually ment and did use the first).
Most likely, the D:\User directory does not exist and the FileStream class will not create it for you. It will simply assume that all (sub) directories up to the specified file name exist and fail otherwise.
So make sure that the directory exists, either outside your application, or like so:
string fileName = #"D:\user\user.txt";
string directory = Path.GetDirectoryName(fileName);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
FileStream FS = new FileStream(fileName, FileMode.Append);
// ... rest of code
You are running the application on a windows machine. In windows, the file path needs to be given like
string directory = #"D:\user\user.txt";
Also, make sure this file path exists and the application you are running has permission to write on this file.
If you are running a test application then give permission as FullControl to Everyone. AS below
If you are sure about the path, check if you run VS as an administrator

Adding attachments unlock file

I need some help.
My application works with Outlook files.
For example, I have a MSG format file is stored at my PC.
Let's imagine that I haven't got any running Outlook processes on my PC.
var myProcess = new Process { ProcessInfo = new ProcessStartInfo {FileName = targetPath}}
where targetPath is full path to my file.
Then I start process:
myProcess.Start();
At this moment Outlook runs at OS. Looking into TaskManager I see this process, and it's unique PID.
And there is my first question: why this PID is different from myProcess.Id ?
Moving on. I need to check is my file still opening at Outlook. I resolve this issue by trying to open this file in my application for a certain time.
var iterations = 3600;
while (iterations > 0 ) {
Thread.Sleep(1000);
var fInfo = new FileInfo(targetPath);
FileStream stream = null;
try {
stream = fInfo.Open(FileMode.Open, FileAccess.Read | FileAccess.Write, FileShare.None);
} catch {
//I expect if exception occurs then file is not lock and can send it to server.
}
finally{
if(stream != null)
stream.Close();
}
iteration--;
}
I think, while my MSG file is using by Outlook, I my application cant open file. In that way I decide that cant save my file and send it to server. But! If I add attachment but NOT close this e-mail at Outlook, my application CAN open this file. And I don't understand why Outlook change Read/Write attribute of this file? And how I can solve this issue?
Unfortunately, I haven't any idea why it happens and how to make it work.
I was looking on any info at web that can help to solve my issue, but has no result :(
Thank you for your time.
Firstly, Outlook is a singleton - if you start a new instance of outlook.exe, it will simply switch control to the already running instance and exit.
Outlook internally caches / references open MSG files, there is really northing you can do about that.

Dispose slow on very big filestreams?

I've got this code
string archiveFileName = BuildArchiveFileName(i, null);
string tmpArchiveFileName = BuildArchiveFileName(i, "tmp");
try
{
using (FileStream tmpArchiveMemoryStream = new FileStream(tmpArchiveFileName, FileMode.Create))
{
using (BinaryWriter pakWriter = new BinaryWriter(tmpArchiveMemoryStream))
{
if (i == 0)
{
WriteHeader(pakWriter, pakInfo.Header);
WriteFileInfo(pakWriter, pakInfo.FileList);
uint remainingBytesToDataOffset = pakInfo.Header.DataSectionOffset - CalculateHeaderBlockSize(pakInfo.Header);
pakWriter.Write(Util.CreatePaddingByteArray((int)remainingBytesToDataOffset));
}
foreach (String file in pakInfo.FileList.Keys)
{
DosPak.Model.FileInfo info = pakInfo.FileList[file];
if (info.IndexArchiveFile == i)
{
//Console.WriteLine("Writing " + file);
byte[] fileData = GetFileAsStream(file, false);
int paddingSize = (int)CalculateFullByteBlockSize((uint)fileData.Length) - fileData.Length;
pakWriter.Write(fileData);
pakWriter.Write(Util.CreatePaddingByteArray(paddingSize));
}
}
}
}
}
finally
{
File.Delete(archiveFileName);
File.Move(tmpArchiveFileName, archiveFileName);
}
I've tested this with NUnit on small file sizes and it works perfectly. Then when I tried it on a real life example , that are files over 1 GB. I get in trouble on the delete. It states the file is still in use by another process. While it shouldn't that file should have been disposed of after exiting the using branch. So I'm wondering if the dispose of the filestream is slow to execute and that is the reason I'm getting in trouble. Small note in all my file handling I use a FileStream with the using keyword.
While it shouldn't that file should have been disposed of after exiting the using branch
That's not what it is complaining about, you can't delete archiveFileName. Some other process has the file opened, just as the exception message says. If you have no idea what process that might be then start killing them off one-by-one with Task Manager's Processes tab. That being your own process is not entirely unusual btw. Best way is with SysInternals' Handle utility, it can show you the process name.
Deleting files is in general a perilous adventure on a multi-tasking operating system, always non-zero odds that some other process is interested in the file as well. They ought to open the file with FileShare.Delete but that's often overlooked.
The safest way to do this is with File.Replace(). The 3rd argument, the backup filename, is crucial, it allows the file to be renamed and continue to exist so that other process can continue to use it. You should try to delete that backup file at the start of your code. If that doesn't succeed then File.Replace() cannot work either. But do check that it isn't a bug in your program first, run the Handle utility.

File is being used by another process after File.Copy

I am trying to manage files in my web application. Sometimes, I must create a file in a folder (with File.Copy):
File.Copy(#oldPath, #newPath);
And a few seconds later that file may be deleted:
if (File.Exists(#newPath)) {
File.Delete(#newPath);
}
However, I don't know why the new file remains blocked by the server process (IIS, w3wp.exe) after File.Copy. After File.Delete I get the exception:
"The process cannot access the file because it is being used by
another process."
According to the Api, File.Copy don't block the file, does it?
I have tried to release the resources but it hasn't worked. How can I resolve this?
UPDATED: Indeed, using Process Explorer the file is blocked by IIS process. I have tried to implement the copy code in order to release manually the resources but the problem still goes on:
public void copy(String oldPath, String newPath)
{
FileStream input = null;
FileStream output = null;
try
{
input = new FileStream(oldPath, FileMode.Open);
output = new FileStream(newPath, FileMode.Create, FileAccess.ReadWrite);
byte[] buffer = new byte[32768];
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, read);
}
}
catch (Exception e)
{
}
finally
{
input.Close();
input.Dispose();
output.Close();
output.Dispose();
}
}
You can try Process Explorer to find which application opened the file handle.
If Process Explorer cannot find that, use Process Monitor to trace which process is trying to access the file.
This can be caused by file indexers or anti virus software, which typically scan all new files.
File was being blocked by another process without me being aware of it. Process Explorer was really helpful.
Typical easy issue hard to spot.

Deleting a temp file that is open c#

i have written some pdf files to a temp directory and these get displayed as a thumbnail that the user can view. when i close my form i clean up all of the files in the temp directory.
If however the user has one of the thumbnails open and then closes my application - it deletes the files and then throws an exception because the pdf is open in another process and cant be cleaned up.
I guess this is a shocking programming decision by me, but i am still a novice! How should i account for this in my code?
Thanks
You can detect if the file is in use by using code similar to below, then use that to warn the user that a file can't be deleted.
Unfortunately you can't delete a file that is in use.
public static bool IsFileInUse(string pathToFile)
{
if (!System.IO.File.Exists(pathToFile))
{
// File doesn't exist, so we know it's not in use.
return false;
}
bool inUse = false;
System.IO.FileStream fs;
try
{
fs = System.IO.File.Open(pathToFile, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Read, System.IO.FileShare.None);
fs.Close();
}
catch (System.IO.IOException ex)
{
string exMess = ex.Message;
inUse = true;
}
return inUse;
}
You should catch that exception (in catch block you can inform user to close that file or it will not be deleted), and if the temp directory is yours you can try to delete it when application starts (or when it ends again), if its windows temp directory, then it does not matter that much
Tools like File Unlocker can release a file. However I think this could make programs depending on the file crash...
Maybe you can look up how they unlock files or manage to execute the unlocker via Process.Start to unlock your file and delete it.
However if it's you blocking the file you should try and fix this in your programm. Maybe you should dispose all loaded files (filestreams etc) before trying to clean it up.

Categories

Resources