IO Exception - File In Use By Another Process - c#

C# / .NET 3.5, WindowsForms.
I have this Windows form that displays an image from a file, and whenever user saves the record this code is executed:
string oldLoc = itemsBO.ImageLoc;
if (oldLoc != SystemSettings.NoImageLocation)
{
if (File.Exists(oldLoc))
{
try { File.Delete(oldLoc); }
catch (IOException ex)
{
MessageBox.Show("1 - " + ex.GetType().ToString() + " " + ex.Message);
}
}
}
string saveLoc = itemsBO.ImageSearchLoc + ".jpg";
if (File.Exists(saveLoc))
{
try { File.Delete(saveLoc); }
catch (IOException ex)
{
MessageBox.Show("2 - " + ex.GetType().ToString() + " " + ex.Message);
}
}
try
{
if (pictureBox2.Image != null)
pictureBox2.Image.Save(saveLoc, System.Drawing.Imaging.ImageFormat.Jpeg);
}
catch (IOException ex)
{
MessageBox.Show("3 - " + ex.GetType().ToString() + " " + ex.Message);
}
Disregard the poor MessageBox messages, but it errors out in each Catch statement. It can't delete the "existing" Image because it says it's in use by another process. Can't save because a file exists in that same path because it's not deleting.
This is the code that sets the Image when they try to add a new picture;
Image clipImage = Clipboard.GetImage();
if (tabControl2.SelectedTab == tabPage5)
{
pictureBox1.Image = clipImage;
itemsBO.IsDirtyImage = true;
}
else if (tabControl2.SelectedTab == tabPage6)
{
pictureBox2.Image = clipImage;
itemsBO.IsDirtyImage2 = true;
}
Then when the form loads up an existing record with an image, this is the code used to fetch/display it:
byte[] bits = File.ReadAllBytes(imgfil);
msImage = new MemoryStream(bits, 0, bits.Length);
if (tabControl2.SelectedTab == tabPage5)
pictureBox1.Image = Image.FromStream(msImage);
else if (tabControl2.SelectedTab == tabPage6)
pictureBox2.Image = Image.FromStream(msImage);
imgfil being a path to the image, of course.
Absolutely no idea where to begin...

I have this Windows form that displays an image from a file, and whenever user saves the record
If you're still displaying the image when they save the file, the application will still be accessing the file if I'm not mistaken. Try disposing of the file first, probably by setting the picture box's (or whatever you're using to display the image) image to null, or load a blank picture before you perform the operation.

If it says file in use by another process, well then it must be in use by another process :)
Have you tried monitoring the file lock using Process Explorer.
Once you have identified what's holding your file, close that file handle using Process Explorer and then try to run your code.
This might help-
How to find out what processes have folder or file locked?

So I had inherited this application from another user, turns out the pictureBoxes were having their Image set in another chunk of code independent of that third block of code in the original post. It was because of this that the IOException was happening :(

Related

System.IO.File.Create is returning System.UnauthorizedAccessException but just for one file

Background
I have the some c# code that queries sharepoint and then provides the ability to download specific files into a folder on the local computer.
The strange this is that when I try downloading file A, it works no problems. When i try downloading file B, 2 weird things happen:
the "exists" variable always comes back as true - eventhough a local copy of the file doesn't exist.
when i click on the option to replace the local file, when it hits the .Create() method, it throws the System.UnauthorizedAccessException error ...
So specifically, when I try to download:
C:\Users\me\AppData\Local\Packages\d87c4dcd-a0b6-4d3e-a529-72da28f897e4_4p54yvdgfzqvw\LocalState\ABCDoc.docx
It works fine.
When I try to download
C:\Users\me\AppData\Local\Packages\d87c4dcd-a0b6-4d3e-a529-72da28f897e4_4p54yvdgfzqvw\LocalState\123Doc.docx
I always get the message box that says the file already exists, do i want to replace. I'll click on yes. Then it fails with the unauthorized access error.
What I've tried
When running in debug mode, I hijack the name of the file and change it to a new name, the download /save works.
Here's the code:
protected async void DownloadFile(object sender, EventArgs e)
{
var menuItem = sender as MenuItem;
if (menuItem != null)
{
//grab the details of the file currently selected
var selectedFile = (Microsoft.Graph.ListItem)menuItem.BindingContext;
//check if the file already exists in the local workspace. if it does prompt. if not just download.
var driveItemPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), selectedFile.DriveItem.Name);
var exists = System.IO.File.Exists(driveItemPath);
if (exists)
{
if (!await DisplayAlert("Download", "Download and replace local copy of " + selectedFile.DriveItem.Name + "?", "Yes", "No"))
{
return;
}
}
try
{
using (var stream = await App.GraphClient.Sites[siteID].Drive.Items[selectedFile.DriveItem.Id].Content.Request().GetAsync())
{
var driveItemFile = System.IO.File.Create(driveItemPath);
stream.Seek(0, SeekOrigin.Begin);
stream.CopyTo(driveItemFile);
driveItemFile.Close(); //also a stream which needs to be Dispose()d.
}
DisplayAlert("Download", selectedFile.DriveItem.Name + " successfully downloaded", "OK");
}
catch (Exception ex)
{
Console.WriteLine("DOWNLOAD FAILED WITH: " + ex.Message);
DisplayAlert("ERROR", selectedFile.DriveItem.Name + " failed with: " + ex.Message, "OK");
}
}
}

c# adobe acrobat SDK: file is still locked after SDK quit

I'm working with C# and adobe acrobat SDK.
When the program throws an error due to the pdf already being compressed I want to move the pdf.
However, C# complains that the file is being used by another process and I know it has to do with the SDK and not another program.
After some debugging I found out that compressPDFOperation.Execute is the culprit.
How can I close it so that I can move the file?
try {
// Initial setup, create credentials instance.
Console.WriteLine(".json: " + Directory.GetCurrentDirectory() + "/pdftools-api-credentials.json");
Credentials credentials = Credentials.ServiceAccountCredentialsBuilder()
.FromFile(Directory.GetCurrentDirectory() + "/pdftools-api-credentials.json")
.Build();
// Create an ExecutionContext using credentials and create a new operation instance.
ExecutionContext executionContext = ExecutionContext.Create(credentials);
CompressPDFOperation compressPDFOperation = CompressPDFOperation.CreateNew();
// Set operation input from a source file.
FileRef sourceFileRef = FileRef.CreateFromLocalFile(directory + #"\" + pdfname);
compressPDFOperation.SetInput(sourceFileRef);
// Execute the operation.
FileRef result = compressPDFOperation.Execute(executionContext);
// Save the result to the specified location.
//if pdf is part of a group, the group directory name will be stored in fileGroupDirectory
string fileGroupDirectory = directory.Replace(sourceDir, "");
result.SaveAs(finishedDir + fileGroupDirectory + pdfname);
}
catch (ServiceApiException ex)
{
Console.WriteLine("Exception encountered while executing operation", ex.Message);
if (ex.Message.Contains("The input file is already compressed"))
{
File.Move(file, finishedDir + fileGroupDirectory + fileName);
}
}
I've found a solution , it's not best practice but I don't know an other way to do it.
I've declared all the variables used to execute the compression (sourceFileRef, compressPdfOperation, ...) before the try catch statement and after result.SaveAs(...) I set those variables to null and run the garbage collection.
compressPDFOperation = null;
result = null;
sourceFileRef = null;
executionContext = null;
credentials = null;
GC.Collect();

Deep zoom image creation throws exception in c#

Iam building a website which uses a pivot viewer that uses a deep zoom collection to show images and the metadata from a database. Iam using the deezoomtools.dll from microsoft to create the deep zoom collection.
From this website i can start a thread that starts the creation of several collection. For small collections this process goes just fine, however when doing a large collection it fails regularly.
I added some debug lines to see what happens and the exception i get is:
Thread was aborted as the message and as stack trace where it came from.
I found that when the images are processed the exception occurs. I guess that the error occurs in this code sample in the function GetImageForDeepZoomComposer
private bool processImage(Item collectionItem, string backupImage,StreamWriter _logFile)
{
try
{
_logFile.WriteLine("start process");
if (string.IsNullOrEmpty(collectionItem.Image))
return false;
if (!File.Exists(collectionItem.ImagePath))
return false;
_logFile.WriteLine("File is there");
if (!AllImagesUnique) // check to see if we have processed this exact file before.
if (cacheOfImageIds.ContainsKey(collectionItem.ImagePath)) // we already have have processed this image so don't do it again
{
collectionItem.ImageId = cacheOfImageIds[collectionItem.ImagePath];
return true;
}
_logFile.WriteLine("Get Image: " + collectionItem.ImagePath);
string workingImage = GetImageForDeepZoomComposer(collectionItem.ImagePath, collectionItem.Id);
_logFile.WriteLine("Image aquired");
_logFile.WriteLine("collection name and id");
string deepZoomImage = DeepZoomImageDir + collectionItem.Id;
sendAction(string.Format("\tConverting image {0} to Deep Zoom Output file {1} ", workingImage,
deepZoomImage));
//imageCreator.Create(workingImage, deepZoomImage);
_logFile.WriteLine("set image surrogate");
SurrogateImageInfo sii = new SurrogateImageInfo(workingImage, "DeepZoomImages/" + Path.GetFileName(deepZoomImage) + ".xml");
_logFile.WriteLine("image surrogate set");
images.Add(sii);
if (!AllImagesUnique) // if we want to make sure we don't use the Deep Zoom Composer on the same file twice then add this image to the cache
cacheOfImageIds.Add(collectionItem.ImagePath, collectionItem.Id);
return true;
}
catch (Exception ex)
{
_logFile.WriteLine(ex.Message);
sendAction(
string.Format(
"\tSkipping current item cause of execption encountered while processing the image\r\n\t\t{0}",
ex.Message));
return false; // this item will not be added to the collection
}
}
internal string GetImageForDeepZoomComposer(string imageFile,int id)
{
if (imageFile.StartsWith("http://") || imageFile.StartsWith("https://"))
{
if (_client == null) // if we havent used the WebClient for this collection yet create one
_client = new WebClient();
string tempFile = ImageDownloadDir + Guid.NewGuid();
sendAction(string.Format("\tDownloading image '{0} to {1}", imageFile, tempFile));
_client.DownloadFile(imageFile, tempFile);
return tempFile;
}
else if (imageFile.StartsWith("\\") || imageFile.StartsWith("E:\\") || imageFile.StartsWith("e:\\"))
{
var dir = Path.Combine(DeepZoomImageDir, id.ToString() + "_files");
//if (!Directory.Exists(dir))
// Directory.CreateDirectory(dir);
var fixedSizeFileName = imageFile.Replace("_thumb", "_fs");
//create a fixed size image if it's not already created
if (!File.Exists(fixedSizeFileName))
FixedSize(new System.Drawing.Bitmap(imageFile), 512, 512).Save(fixedSizeFileName,codecInfo,parameters);
//copy the fixed size image to the DeepZoomImages folder so it can be used when zooming in to the deepest level
var localFixedSizeImage = Path.Combine(DeepZoomImageDir, id + ".jpg");
File.Copy(fixedSizeFileName, localFixedSizeImage);
return localFixedSizeImage;
}
return imageFile;
}
I think it has something to do with images that are locked when it tries to get the image and tries to save it with a different name such that it could be used. Iam truly at a loss here.
Thank you in advance for the information

webbrowsercontrol issue, clear cache not working?

I'm using a webbrowsercontrol to show .pdf's stored locally. At button press I want the webbrowser to show an empty page/nothing and I want to move the .pdf to a different folder. First I tried navigating to "" before moving but my .pdf was used by another process. Google told me that I probably needed to clear the browser's cache to be able to move it. I did so using the code found here: http://www.gutgames.com/post/Clearing-the-Cache-of-a-WebBrowser-Control.aspx and I even tried the alternative code line found in comment nr 2, but none of these let me move my .pdf, it's still used by another process.
What can/should I do to be able to move the file? Have I forgotten something?
At the second File.Move is where I get the error:
webBrowser1.Navigate("");
WebBrowserHelper.ClearCache();
if (calConv != "")
{
File.Move(forsDir + calConv + ".cal", forsDir + calConv.Replace("ToDo\\", "") + ".cg4");
File.Move(forsDir + calConv + ".pdf", forsDir + calConv.Replace("ToDo\\", "") + ".pdf");
}
This is how to show the PDF without using the webcontrol, using Adobe Reader instead:
Download the Acrobat SDK from http://www.adobe.com/devnet/acrobat/downloads.html
In your project add a reference to two dlls from the SDK - AxInterop.AcroPDFLib.dll and Interop.AcroPDFLib.dll
In your form's constructor add the Adobe previewer control:
// Check if the user has Adobe Reader installed, if not you could show a link to Adobe Reader installer
if (Type.GetTypeFromProgID("AcroPDF.PDF") == null)
{
pnlGetAdobe.Visible = pnlGetAdobe.Enabled = true;
}
else
{
try
{
// Initialize the Adobe control
axAcroPDF1 = new AxAcroPDF();
axAcroPDF1.Dock = DockStyle.Fill;
axAcroPDF1.Enabled = true;
axAcroPDF1.Location = new Point(0, 25);
axAcroPDF1.Name = "axAcroPDF1";
axAcroPDF1.OcxState = (AxHost.State)new ComponentResourceManager(typeof(JasperPdfReport)).GetObject("axAcroPDF1.OcxState");
axAcroPDF1.Size = new Size(634, 393);
axAcroPDF1.TabIndex = 1;
pnlCenter.Controls.Add(axAcroPDF1); // Add it to a container or instead directly to your form with this.Controls.Add(axAcroPDF1)
axAcroPDF1.BringToFront();
}
catch (COMException cex)
{
axAcroPDF1.Dispose();
axAcroPDF1 = null;
MessageBox.Show(cex.ToString());
}
catch (Exception ex)
{
axAcroPDF1.Dispose();
axAcroPDF1 = null;
MessageBox.Show(ex.ToString());
}
}
And finally load your PDF file into the control:
if (axAcroPDF1 != null && File.Exists(pdfFilename))
{
axAcroPDF1.setShowToolbar(false);
axAcroPDF1.setView("FitH");
axAcroPDF1.setLayoutMode("SinglePage");
// Load the PDF into the control
axAcroPDF1.LoadFile(pdfFilename);
axAcroPDF1.src = pdfFilename;
// Show it
axAcroPDF1.Show();
axAcroPDF1.Refresh();
}

Trouble deleting a file from c:\windows\system32 using C#

Not quite sure why I can't get this file to delete. I'm logged in as Admin, tried "Run as Admin", tried running in the same folder, tried setting permissions on the file, tried creating a test 1.txt file to delete and no luck. It is acting like the file isn't there. I can see it in Windows Explorer. Please any help is welcome. Thank you for your time.
public void deleteFile(string FileToDelete)
{
//sets system32 to system32 path
string system32 = Environment.SystemDirectory + #"\";
//File.SetAttributes(#system32 + FileToDelete, FileAttributes.Normal);
try
{
//check if file exists
if (!File.Exists(#system32 + #FileToDelete))
{
//if it doesn't no need to delete it
Console.WriteLine("File doesn't exist or is has already been deleted.");
//Console.WriteLine(system32 + FileToDelete);
} //end if
//if it does, then delete
else
{
File.Delete(system32 + FileToDelete);
Console.WriteLine(FileToDelete + " has been deleted.");
} //end else
} //end try
//catch any exceptions
catch (Exception ex)
{
Console.WriteLine(Convert.ToString(ex));
} //end catch
} //end DeleteFile
I created a test file "test.txt" and it worked no problem. I should not that I didn't use the method you posted, but rather used the contents of your supplied method and used them within the main() method of a console application.
ou should also add ReadLine() to display any messages that are returned.
This is what I used, not that it's much different from what you supplied. If this code doesn't work for you then it must be a system privileged issue.
static void Main(string[] args)
{
string FileToDelete = "test.txt";
//sets system32 to system32 path
string system32 = Environment.SystemDirectory + #"\";
try
{
//check if file exists
if (!File.Exists(system32 + FileToDelete))
{
//if it doesn't no need to delete it
Console.WriteLine("File doesn't exist or is has already been deleted.");
//Console.WriteLine(system32 + FileToDelete);
Console.ReadLine();
} //end if
//if it does, then delete
else
{
File.Delete(system32 + FileToDelete);
Console.WriteLine(FileToDelete + " has been deleted.");
Console.ReadLine();
} //end else
} //end try
//catch any exceptions
catch (Exception ex)
{
Console.WriteLine(Convert.ToString(ex));
Console.ReadLine();
} //end catch
}
Try this one out
check if file exist on 64 bits system using File.Exists
If you're using Vista / Windows 7, maybe you're running into file virtualization issues. Have you tried adding a manifest with a <requestedExecutionLevel level="requireAdministrator"/> line in it ?

Categories