NullReferenceException only when opening images from database - c#

I have a table in my database that stores all kind of files.
File names are shown in a ListView and when an user clics on one of them then it's opened by the registered application based on file extension.
This is the code:
if (listViewArchivos.HasItems)
{
dynamic result = listViewArchivos.SelectedItem;
var nombre = Path.GetTempPath() + admin.buscarNombreArchivo((int)result.Id);
var bytes = admin.buscarArchivo((int)result.Id);
try
{
using (var writer = new BinaryWriter(File.Open(nombre, FileMode.Create)))
{
writer.Write(bytes);
}
var p = Process.Start(nombre);
p.WaitForExit();
}
catch (Exception exc)
{
InterfazUtil.error(exc.Message); // This shows a MessageBox
}
finally
{
File.Delete(nombre);
}
}
It's working fine for docx, pdf, txt, etc. But when I try to open an image the file is successfully opened by Window Photo Viewer (Windows 7) but a NullReferenceException is thrown.
If I close WPV first and then the MessageBox the file is deleted from temp folder.
If I close the MessageBox first then the image disappears from WPV and after I close WPV the file is not deleted from temp folder.
Now, if I remove the catch block then the file is successfully opened by WPV and after closing it the file is not deleted from temp folder. Obviously the application crashes because the exception isn't managed.
Looks like the problem is WPV.
Any idea of what is wrong?
TIA
EDIT:
The exception is thrown at
p.WaitForExit();

When you close the MessageBox first the temp file is not deleted because WPV uses it and doesn't allow it.

According to this MSDN: http://msdn.microsoft.com/en-us/library/53ezey2s.aspx
...you will not get back a Process object when the process is already running.
I found this on a forum relating to the nature of WindowsPhotoViewer:
Actually, the Windows Photo Viewer is part of Windows Explorer, and
generally runs in the Explorer.exe process. In fact, what you're
calling the Photo Viewer is really just the "preview" verb for images.
It isn't a standalone application, and opening it without an image or
images doesn't really make any sense.
Thus, you are not getting back a Process object because it is already running by virtue of the fact that explorer.exe is already running.
In the end, I think it means that if your images open in WindowsPhotoViewer, you will not be able to make WaitForExit() work because the owner process will never exit.

Related

How to detect file copying process has finished in C#

I am working on a project that I need to do the following:
I need to rename an image file. (Open an image from folder, and give a name & save it in to same folder)
try
{
string oldFileName = #"path\to\person1.jpg";
string desFileName = #"path\to\person2.jpg";
File.Copy(oldFileName, desFileName, true);
if (File.Exists(oldFileName))
{
File.Delete(#oldFileName);
}
}
catch (Exception ex)
{
}
I did rename the file using above way.
This process copy the old file with new name, but couldn't remove old file
Exception message :
The process cannot access the file 'path\to\person1.jpg' because it is
being used by another process.
How to resolve this? Please suggest any way to detect copying process has complete or not.
Your copy process is definatly complete on if statement becouse your code is sync.
I bet you got this error becouse file is used by another proccess (not your programm). Maby you have paint open or something else.
You should find it out with process monitor or something else. Check this question.

Check if a file that's not locked is open

Some programs (image programs such as Paint, text editors such as notepad and Wordpad,and others) open files, load the contents into memory, then release the file lock. Is there a way to tell if a program is using that file even though it's not locked?
For example, even if image1.bmp is open in Paint, my program can overwrite the copy of image1.bmp that's on the disk because the file isn't locked. Now the copy of image1.bmp that is open in Paint is different than the copy of image1.bmp that is on the disk.
My program is written in C#. I usually use this method for checking if a file is locked, but it won't work in the above case.
Is there a way to check if a file is in use?
Is there any solution to this?
"Now the copy of image1.bmp that is open in Paint" - here's your mistake - the file is no longer open in Paint. It was opened, read, and then closed. Paint does not keep the file open at all - it only has a COPY of its contents in RAM memory. To put it in another way - the fact that you see a picture in MS Paint doesn't mean the file is open.
It is comparable to loaning a document to someone, then he makes a photocopy and returns it - that person no longer "holds" the document, he has a separate copy of it. And there is no way, just by looking at the document, to know who might have made a copy of it at some point in history.
Another way of putting it is this pseudocode:
File file = Open("image.png");
Image img = ImageFromFile(file);
file.Close();
...
img.Save("image.png");
Here no file is being opened at all, there's just a copy in RAM of its content.
Note: I actually checked that for Paint - Process Explorer can show you opened handles, I opened a file in Paint and there was no handle at all listed for a file of that name.
Here's what I came up with. I check all open processes for a window title. If the process has a window title, I see if it contains the name of the file I'm looking for.
It won't work 100% of the time since some applications can have multiple files open in a single instance.
I adapted it from this question:Getting a list of all applications
bool isFileOpen(string file)
{
string windowTitle = "";
Process[] myProcesses = Process.GetProcesses();
foreach (Process P in myProcesses)
{
if (P.MainWindowTitle.Length > 1)
{
windowTitle = P.MainWindowTitle;
if (windowTitle.Contains(file) == true)
{
return true;
}
}
}
return false;
}

Replacing PDF fails. Even with File.Delete() success when opened in Edge-Browser

The goal is to replace a PDF-File which is currently saved on disk.
I am deleting the current PDF file from disk, then recreating a new one. This works fine unless the PDF is currently opened in the Microsoft Edge Browser.
// Try delete PDF-File (which is opened in Edge Browser)
var info = new FileInfo(pathToPdf);
if (info.Exists)
{
try
{
info.Delete();
// Same thing with the File.Delete call
//File.Delete(path);
Console.WriteLine("Success.");
}
catch (Exception)
{
Console.WriteLine("Failed.");
return;
}
}
We get a "Success" print out even though the file is opened in Edge. If it were opened in Adobe Reader it would throw an exception (File in use).
Let's create a new file. (For demonstration purposes a text file with a .pdf ending)
try
{
using (var writer = File.CreateText(pathToPdf))
{
writer.Write("Foo");
writer.Flush();
Console.WriteLine("Success.");
}
}
catch (Exception e)
{
Console.WriteLine("Failed.");
return;
}
I expected to be able to create a new file, since the Delete() didn't fail. Yet I get an UnauthorizedAccessException: "Access to the path 'XYZ' is denied."
As a workaround I can recheck if the file exists after deleting it.
var newInfo = new FileInfo(pathToPdf);
if (newInfo.Exists)
// Delete failed
But why would I need to do this? Shouldn't FileInfo.Delete() or File.Delete(path) fail in the first place?
Notes:
Tested on Windows 10 Pro with .Net Framework 4.5.1
The file is still visible in the File-Explorer with its original filesize after it was deleted by code (while opened in Edge).
When closing the Edge Browser after deleting the file by code, the file vanishes from the File-Explorer and I can create a new file programatically.
This problem occurs only with PDFs being opened in Edge. When using a Text-File instead the Text-File gets deleted properly.
Any clarification and help is appreciated.
Best Chris
If the file does not exist, FileInfo.Delete() does nothing.
From msdn
WinNt4Family
Delete does not delete a file that is open for normal I/O or a file that is memory-mapped.
You get an UnauthorizedAccessException when the path is a directory.
If FILE_SHARE_DELETE is set on the handle by Edge, then File.delete() can be called with success by another process even when the handle exists. The file is then marked for deletion and deleted after the handle is closed. Until then, it is still visible in the Explorer, but not accessible anymore.
For a more detailed explanation, see this SO post:
Odd behaviour when deleting Files with Files.delete()

check if a text file is opened in notepad

how to find whether specific .txt file is opened in notepad?
I have tried solutions mentioned here
Is there a way to check if a file is in use?
But they work fine for Word and pdf file but not working for txt file opened in Notepad.
here is code I have wrote.
public bool IsFileOpen(string strFileName)
{
bool retVal = false;
try
{
if (File.Exists(pstrFileName))
{
using (FileStream stream = File.OpenWrite(pstrFileName))
{
try
{
}
catch (IOException)
{
retVal = true;
}
finally
{
stream.Close();
stream.Dispose();
}
}
}
}
catch (IOException)
{ //file is opened at another location
retVal = true;
}
catch (UnauthorizedAccessException)
{ //Bypass this exception since this is due to the file is being set to read-only
}
return retVal;
}
am i missing somthing here.??
My requirement:
I have application which works similar to VSS. When user checks out specific file and opens ,and try to check in the same, while it has opened. Application is suppose to throw a warning message.For that i have used the above functionality.Its working fine for word and pdf.
To expand on my comment. A file is only locked if a handle is kept open by an application. Word for example will open the file, read in the stream and maintain the handle so that other applications cannot delete that file while the user is working on it.
Notepad, and other applications, just open the file, read in the entire stream and then close the file releasing the lock they have. This means that the file is no longer locked and can be edited by another application or even deleted and Notepad will not care as it has its own copy in memory.
You could try and hack around with getting instances of Notepad and checking if a file is open but this is ultimately not a great idea. If the file is not locked then you should be free to do what you want with it.
This is a hack solution I just came up with, but it should work for you. This makes use of System.Diagnostics.
Process[] processes = Process.GetProcessesByName("notepad");
for (int i = 0; i < processes.Length; i++)
{
Console.WriteLine(processes[i].MainWindowTitle);
if (processes[i].MainWindowTitle.Equals("myFile.txt - Notepad"))
{
Console.WriteLine("The file myFile is Open!");
}
}
Console.ReadLine();
Hopefully that should do the trick. My example looks to see if an instance of notepad is open with the window title "myFile.txt - Notepad". The window name is always "filename.extension - Notepad" so you can handle that however you might need to.
I suppose you could make a call to System.IO.File.GetLastAccessTime(filePath). You could then poll the file every so often and when the access time changes you know the file has been opened, you can then fire an event that the file has been opened. See Jeffs post here:
Detect File Read in C#
You could also do this using the following tactic: It seems that notepad does hold some kind of lock on the hosting folder (try to delete the folder and you'll see you can't).
you could use the following code Using C#, how does one figure out what process locked a file? to check list of processes that lock the folder.
one of the processes will be your notepad.
you could them compare by Title as another answers mentioned.
if you're issuing the open of the file - you could save the PID and comapre it with one of the processes that returned.

Powerpoint could not open file

I am developping a C# programm which creates a PowerPoint presentation. However, I am running into a problem with the following instruction:
Presentation pres = pres_set.Open(path,
Microsoft.Office.Core.MsoTriState.msoFalse,
Microsoft.Office.Core.MsoTriState.msoTrue,
Microsoft.Office.Core.MsoTriState.msoTrue);
This instruction works only sometimes. If it doesn't, it throws a exception with the message "PowerPoint could not open file". When I then manually open the template file, close it and execute the function again, most of the time it will execute correctly.
I have used the Microsoft Powerpoint 14.0 and the Microsoft Powerpoint 12.0 libraries, but both have the same problem.
Is there any way to avoid this strange problem?
The answer is much simpler: The Powerpoint-application expects an existing file.
I just had the same exception because I used a relative path, and PowerPoint tried to open the file relative to PowerPoint.exe instead of your Program.exe.
This problem can quickly be fixed by adding something like this before calling the open-method:
// Start Powerpoint
var powerpointApp = new Microsoft.Office.Interop.PowerPoint.Application();
// Get a fileInfo object to generate the full path
FileInfo fileInfo = new FileInfo(#"RelativeDir\YourPresentation.pptx");
// Use the full path
powerpointApp.Presentations.Open(fileInfo.FullName, MsoTriState.msoTrue, WithWindow: MsoTriState.msoFalse);
Have you tried not setting the TriState, like this?
Object oMiss = System.Reflection.Missing.Value;
Presentation pres = pres_set.Open(ref path, ref oMiss, ref oMiss, ref oMiss);
I had the same problem while trying to open an existing PowerPoint presentation until I found out that Visual Basic for Applications (VBA) was not installed on my Office installation options as described here:
http://www.debugging.com/bug/22261
Apparently, this problem only happens when working with PowerPoint as I have no problems manipulating Excel and Word files.
The problemĀ“s gone away as soon as I repaired my Office, including the VBA to the installation.
Hope it helps!
I had a similar problem with PowerPoint. I found my Presentations.Open method was failing unless I had PowerPoint open.
One potential solution is to set PowerPointApplication.Visible = MsoTriState.msoTrue However, this will cause PowerPoint to physically open which is likely to be undesirable.
I resolved my issue by setting the final argument of the Open method to msoFalse, which specifies that the PowerPoint window should not open on the server which is more desirable.
Presentations.Open(inputFileName,
MsoTriState.msoFalse,
MsoTriState.msoTrue,
MsoTriState.msoFalse);
Take a look at this MSDN KB article for more information on the different parameters of the Open method.
ProcessStartInfo ten_ct = new ProcessStartInfo();
ten_ct.FileName = "POWERPNT.EXE";
ten_ct.Arguments = #"D:\project\GiaoAn\GiaoAn\MyPpt.pptx";
Process.Start(ten_ct);
I've seen problems like this with Excel, even when I try to launch it as a user with a command-line file to open. So it may not be anything wrong with your program. When I do this as a user, usually it works the second time.
So my advice would be either
1) For your program to try opening Power Point first without the file, wait (start with 5 seconds), and then have it try to load the file.
or
2) Your program can catch the exception, and simply try opening the file again if it fails (and if you find this works, you should add a maximum number of tries, so the program doesn't loop trying to do this all day). You could optionally also check to see if the file exists (if that's a possibility in your scenario - but it doesn't sound like this is currently the problem you are facing).
Try this:
Presentation pres = pres_set.Open(path,
Microsoft.Office.Core.MsoTriState.msoFalse,
Microsoft.Office.Core.MsoTriState.msoTrue,
Microsoft.Office.Core.MsoTriState.msoFalse);
I solve this problem using:
var app = new PP.Application();
PP.Presentation pres = null;
try
{
Process.Start(inputFile);
var presCol = app.Presentations;
// Waiting for loading
Thread.Sleep(2000);
pres = presCol[inputFile];
// Your code there
// ...............
}
catch (System.Exception ex)
{
Log.Error(ex.Message);
throw;
}
finally
{
if (pres != null)
{
pres.Close();
}
if (app != null)
{
app.Quit();
}
pres = null;
app = null;
}

Categories