ShellExecuteEx and waiting until file has been actually opened - winapi

This is the scenario:
I'm using ShellExecuteEx in order to open a given .xlsx file. This works fine, Excel is started and the .xlsx file is opened in Excel.
Now ShellExecuteEx is returning more or less instantly before even Excel has fully started and opened the .xlsx file. So far so good.
Is there a way to wait until the .xlsx file has been actually opened by Excel? Something like a BOOL FileIsOpenExclusively(LPCTSTR filename) function which returns TRUE is the file is opened exclusively?
Then I could do somehing like this (minimalistic, naïve and non error checking) pseudocode:
ShellExecuteEx(... stuff for opening myfile.xlsx ...);
while (FileIsOpenExclusively("myfile.xlsx"))
{
Sleep(500);
}
// now "myfile.xlsx" is opened execusively
EDITED
The actual slightly more complicated scenario is this:
ShellExecuteEx launches Excel open the given .xlsx file.
then I need to know somehow when the .xlsx file is closed, either because the file is closed by the Excel user or because the user quits Excel alltogether.
What I'm doing now is illustrated by this pseudo code:
ShellExecuteEx(... stuff for opening myfile.xlsx ...);
Sleep(5000); // wait that Excel has hopefully has opened the file
do
{
Sleep(500);
Open("myfile.xlsx");
} while (opening file is unsuccessful)
// file could be opened which means that Excel has closed it
Close("myfile.xlsx");
The problem is the Sleep(5000);: if Excel could not open the file within 5.5 seconds, the test below will fail because it will think Excel has closed the file even before it was opened. Therefore I need to know when Excel opens the file rather than waiting a determined amount of time.
Maybe there is another approach. Some comments have suggested to use WaitForInputIdle which sounds promising, but this may not work if there is already an open instance of Excel beforehand (to be tested).
Another comment suggested enumerating the top-level windows and check for changements of the window title, but I'm not sure this works with modern Excel versions (to be checked) and if it works, it may stop working with the next major Excel version.
Using an oportunistic lock sounds very promising, I'll test this next week.
And finally using the Restart manager might be a lead as well.

As others said, there is no way to know when an app opens a file, but if it is specifically for Excel you can use COM automation.
Here is a python example, here is the generic documentation. In C++ you have to use CoCreateInstance to acquire an IDispatch.

Related

Win CLI open file with "How to open"?

I need to open the file using Windows 10 cmd. But when the file opens, I need Windows to show me a modal window "How do you want to open this file?". The system should do this even if it already has a program selected by default to open a certain type of file. Is it possible to do this?
To clarify my problem:
I need the console to run for example ".py" not through the standard Python.File="C:\Windows\py.exe " "%L" %*, and for example via VS Code. You might tell me about the VS Code CLI. But how to handle an event where the user will not have VS Code, but for example Pycharm, and the user will want to open it through it? That is why the question was posed in such a way that the user could choose through what to open the file already through the built-in modal window in Windows. In any case, I will be glad of any suggestion to solve my problem.
I tried to find something similar, but apart from the standard start something.som I didn't find it. And this is not a solution to the problem, because start starts the file in the program that is specified by default in the system. This program may not even be the one that the user ever chose later. I came across a similar question in Stackoverflow, where a person wanted to see which program was responsible for opening a file with a certain extension, where assoc and ftype were used, but they did not give the desired result.

Windows - Opening a file from code and wait for it to be closed

I need some help and/or advice please.
I'm opening a file from code in either the default associated windows program or with a selected windows program using either ShellExecute or CreateProcess. I then wait for the process to complete. But this does not really work for me because:
Let's say the default associated program for text files (*.txt) is Notepad ++ (NPP). For the process to complete, NPP must not be open to start with and must be closed to complete the process.
But if NPP is already open, the file will be opened in the already opened NPP. But I do not necessarily want to close NPP to complete the process, I just want to close the opened text file and need to detect that the file has been closed and not NPP.
So I realised that waiting for the process to complete is not going to work. I've tried several things like trying to detect if the if the file is opened in another process but have not had any success.
So my question is, what would be the best method to detect when a file is open or in use and vice versa?
It sounds like you want to know when the file handle is "closed", not necessiarly when the program that operated on that file has exited.
Your question is closely related to this question. You could reference that to periodically poll the process handle to see what files are open. There will be timing issues - it might take a few seconds for the process to open the file in the first place.
There are also tools such as Handle.exe that may be useful.
However - none of these solutions are perfect. Some apps, including Notepad.exe, just open the file, read the contents, and immediately close the handle. When the user clicks "save", the file is re-opened for writing, contents saved back to disk, then the file handle is closed again.
A simpler approach would be to periodically poll the last-modified timestamp on the file via GetFileTime. When it changes, you could assume the file has been "Saved". Or apply this technique with some combination of the above and/or waiting for the application that was launched to exit.

the action can't be completed because the folder or a file in it is open in another program

When deleting a folder that contains a file that is in use, it is common to see the following Windows 7 message,
"The action can't be completed because the folder or a file in it is open in another program."
I commonly have 10-20 programs open, 30-40 folders open, etc. In short, I have many executables running and many windows explorers open.
Does anyone know a simple trick to determine which program is using the file?
Does anyone know a simple trick to determine which file is blocking the delete operation?
This information would be highly useful to display in the Windows 7 'folder in use' dialog, but it is missing.
Consequently I have to close many of my open applications and folders to complete the delete operation. This is annoying because I have to re-open them after deleting them.
Have you seen this other question or this one?
I use to run ProccessExplorer and Find for the blocked folder.
Closing the application Malwarebytes allowed me to delete what I needed to via Windows Explorer.

Excel .xlsx download - sharing violation error message on Open and Save combination

I've found this question posed a few times, but no definitive answers as yet. Looks like a decent solution would help quite a few people.
So we create an excel file (.xlsx) on the server and download it to the client using content-disposition 'attachment'. The Open Save dialog appears and all works fine if you choose Save, or Open and then Save As... However if you choose Open and then hit the Save... button then Excel hangs for a moment and then presents the message:
Your changes could not be saved to 'Export[5].xlsx' because of a sharing violation. Try saving to a different file.
then:
The file you are trying to open 'F8CAC020.IE5\HM2NBE5C\F8CAC020', is in a different format than specified by the file extension. Verify that the file is not corrupted and is from a trusted source before opening the file. Do you want to open the file now?
then:
you finally get the Save As: dialog (assuming you pressed 'Yes').
Code for creating the file is:
Response.Clear()
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
Response.AppendHeader("content-disposition", "attachment;filename=Export.xlsx")
Response.AddHeader("Content-Length", New System.IO.FileInfo(NewFile).Length)
Response.TransmitFile(NewFile)
Response.Flush()
If you remove the content-disposition header you get the right sort of behaviour in Excel, but with the wrong name and no guarantee that the Excel document will not instead be shown in the browser (depending on client settings). If you press Open and then Save then you
get a message:
'default.aspx' is read-only. To save a copy, click OK, then give the workbook a new name in the Save As dialog box.
So the question is how to combine the 2 behaviours into a reasonable one:
Get the nice error message directly above, when you try to Open and then Save a downloaded file, but also specify that the document should be downloaded and given a default filename.
Cheers,
James
I believe there is a bug in the IE file download code that does not acknowledge the completed file transfer (download) from the web server, thus leaving a connection to the downloaded (temporary) file open when the save is attempted. That generates the "sharing violation" message. I tried the same code with FireFox and I don't get the same result, which surely leads me to believe this is an IE-specific problem.
Unfortunately, given that I believe this to be a bug in IE, I don't think there is presently a clean resolution to this issue.

How do I launch an Excel document in Windows, edit it and get the application to ask to save it?

I can launch Excel with the document I want using VB.Net 2010:
Dim p As New System.Diagnostics.Process
p.StartInfo.FileName = "c:\temp\myfile.xlsx"
p.Start()
Excel starts OK with the file opened. I edit the file, but when I close it down, Excel doesn't ask if I want to save changes. So it closes and loses my edits.
If I do the same with a text file:
Dim p As New System.Diagnostics.Process
p.StartInfo.FileName = "c:\temp\myfile.txt"
p.Start()
It opens (in Notepad++), I edit it and close it, and Notepad++ asks if I want to save changes. Great!
I've now tried similar code with a Word document - and that's OK. Also with an OpenOffice Sheet document and that works as well.
This behaviour is happening in Windows 7 with Excel 2010. It works as expected in Windows XP with Excel 2007.
What am I doing wrong with Excel? Is it me?
I couldn't recreate your error. I ran the app with and without Excel already being open. I closed out of Excel and then by just closing the workbook only. I was prompted to save each time.
You may need to check your settings in Excel. Could be a security setting. Are you doing any other changes to the excel file programatically or are they just manual changes through the Excel UI only?
Maybe SuperUser.com can help.
OK, so it's not related to the way I was opening the document (using System.Diagnosis.Process). I initially thought it was. If I open files via Explorer, edit them and close Excel, it doesn't ask to save the changed file. So it's not a programming issue.
Thanks for the help anyway guys.
Dave

Resources