here is my question:
I have developed a program that uses Microsoft.Excel COM components in order to read/write over Excel files. Well, my app is doing good but when I open, for instance, another file directly with Excel while my program is running, the file(s) that my app uses appear within Excel. I do not want this. I tried also the Visibility property of Excel Application class, but that was not the solution, it just does not work.
NOTE : I have checked this question out.
Restrict access to excel file opened by C# program
Yet, it says no proper solution actually.
You can use Application.IgnoreRemoteRequests = true. This will avoid users opening excel files in the same Excel process as the one you are using.
There is one caveat though: you have to make sure that all execution paths of your application reset this property to false. This property WILL NOT reset itself when you quit and release your Excel application which means that Excel will not respond correctly to a subsequent user who double clicks on a *.xls file for example.
EDIT: Possible issues with IgnoreRemoteRequest
Ok, to make this clearer I'll detail a little bit more what issues you can run into using this feature (at least these are the only ones I've run into when I had to use this feature).
When setting IgnoreRemoteRequests = true you have to make sure you reset this property BEFORE quiting and/or releasing the COM Excel application. If you don't, Excel will not respond to DDE requests which means if someone double clicks on a *.xls file, the file will not open (Excel will start up, but it wont open the file automatically).
This however is only true if you quit the application and/or release it without reseting the property. You just have to make sure that wherever it is in your code that you are quitting/resetting you set the IgnoreRemoteRquests back to false before.
If you'r application crashes and it hasn't been able to clean up (unhandled exception) then the EXCEL process will keep running (if invisible, you will only see it in the Task Manager). That is normal as your app didnt have a chance to quit and release the internal Excel it is using. This however is not an issue. If a user ignores this "leaked" Excel process until it's eventually killed in next reboot or whatever, or manually kills it from the task bar, Excel will work perfectly fine.
Note: MS Excel 2007. Don't know about behavior of previous versions.
Have you tried running your program under a service account? This should avoid the excel com object interfering with the instance used by the logged in console user, so they will not see the effects of your com objects. It's probably also better security practice to run COM type applications under a service account instead of a user account as well, but that's for another question.
Related
Here's the scenario:
Some application reads contents of a file. It does so by opening it for shared reading, and then at some point closing it (as I've seen it in Procmon.exe, see image). Right after the file is closed, I want to run my own code editing that file.
The only answer I've found so far is looping File.Open() in a try block and firing an event when it throws an exception, and that won't work for shared read access, let alone how ugly it is.
Is there a package or a custom class I can use?
Edit: The application doesn't lock the file. To make sure, I tried running File.OpenRead(); Thread.Sleep(); before the application launch, and it loaded the file as intenteded. It crashed with File.OpenWrite() though, so I'm convinced there are no locks placed by the application.
Edit: Tried writing some test programs with Restart Manager API implementations, none of them seem to be capturing non-locking reading.
I created a C# plugin (for a database program) that launches Excel using System.Diagnostics.Process.Start.
When Excel opens that way, one Excel add-in which is set to load at startup doesn't launch while others do.
When I open Excel manually (not running it as administrator), all add-ins launch.
I imagine it is a permission or security issue? I tried running the database program as admin and it didn't make a difference.
Why is launching Excel through Process.Start different from launching Excel manually? Is there a way I can solve this problem from within my plugin?
Does this link give you any information?
https://blogs.msdn.microsoft.com/haahmadi/2010/05/26/my-office-addin-does-not-load/
Specifically step 3.
Set the "VSTO_SUPPRESSDISPLAYALERTS" environment variable to 0. Then
go back to the registry key I mentioned in step 1 and set the
LoadBehavior to 3. Now restart the Excel. You should be able to see a
dialog describing what is happening:
The registry key they are talking about is here
HKEY_CURRENT_USER\Software\Microsoft\Office\Excel\Addins
I have a code that open an Excel file and read the content. Each time i run the code for the first time, it opens the Excel file without prompting me. But from the second time going it always prompt me this message
TestFile.xlsx is being modified by user 1. Open as read only
and it always prompt at this portion of the code:
Excel ._Workbook xlsBook = xlsApp .Workbooks.Open (_fileName,0,false,5 ,"","",false ,Excel .XlPlatform .xlWindows ,"",true ,false ,0,true ,false ,false );
NB: i also close the file after the operation done and also using VS 2012
So what can be the problem of this prompt ??
After running your Code and exiting, look in the taskmanager, most likely die EXCEL.EXE instance is still running.
you most likely didn't release all the com objects like:
System.Runtime.InteropServices.Marshal.ReleaseComObject(_theWorkbook);
System.Runtime.InteropServices.Marshal.ReleaseComObject(_sheets);
System.Runtime.InteropServices.Marshal.ReleaseComObject(_workSheet);
System.Runtime.InteropServices.Marshal.ReleaseComObject(_range);
System.Runtime.InteropServices.Marshal.ReleaseComObject(_excelObj);
Make sure there are no resources where the file would be still opened. Could you post the code you're using to close the resource? Perhaps there's an error there.
Finally, as ugly as it is, it's valid for testing purposes: try manually calling the garbage collector after closing the file.
FINALLY, consider using the OpenXml API to work with Excel/Word files, as opposed to the Interop DLLs (remember these require the client to have Excel installed, as opposed to the OpenXml libraries which you can deploy with your application).
I'm using Microsoft.Office.Interop.Excel to create Excel reports with C#. Those reports have a large amount of graphics and take long time to prepare. During the preparation, The instance of the Excel application that my program uses is hidden from the user.
MY problem is that Microsoft Office tends to share application instances automatically. If the user opens an Excel workbook, Excel will try to find a running instance of Excel and open the document from there. When the user tries to open an Excel workbook while my program is running, it is attached to the instance my program uses.
This generates two problem. First, it forces my reports into visibility before they are supposed to become visible. And second, my program now needs to fight with user over the attention of the Excel instance - and my program usually loses.
So, is there any way to make the Excel instance reject requests(from the user. it should still obey to my program) to open documents, and make Office ignore my instance when it has to decide how to open an Excel document?
You could handle the Application.WorkbookOpen event. In here, either start a second instance of Excel and have it open the workbook, or close the workbook with an error message.
I also saw the Application.Interactive property. I haven't played with this, but it may be of use to you.
You can use NPOI, I suggest you visit the following link
http://npoi.codeplex.com/discussions/36157?ProjectName=npoi
I have done a little experimenting, and I think this will work:
Whenever you begin working with Excel, create two instances, and work with the second. When you're done with your work, delete the second instance and its object, then check the "UserControl" property of the first. If it returns "true", then delete only the object, but leave the process for that instance behind. If it returns "false", then delete the instance as well.
As far as I can tell, the user can open and close any number of workbooks, and it will use the first instance you created, as long as you don't delete it, and the second instance will be unmolested.
I refresh Excel 2007 data connections via a C# program and OLE. Most of the work is done by a single Workbooks.RefreshAll() statement.
As is the nature of refreshing spreadsheets, various things can go wrong. During the refresh process, the program can give dialog box error messages about "Data cannot be read from file '|'", and a message about "Overlapping pivottable reports". Both of these are fatal, and I should be able to catch these errors, and exit my program with an error.
Unfortunately, I don't seem to be able to catch these problems, and instead my automated program sits until I come along and hit enter on the dialog.
Does anyone know if it's possible to programmatically catch the errors shown in excel dialog boxes, instead of having them displayed to the user?
Your best bet is to set the Application.DisplayAlerts property to False. That is, assuming that your Excel.Application object variable is named "xlApp", all you'd have to do is the following:
xlApp.DisplayAlerts = false;
Note that this will cause the default response to be taken for each dialog box, which is normally what you would want. (There's no good way around this. Leaving DisplayAlerts = True and using SendKeys might be your only other option, but would be ugly and very error prone.)
Since you are making this call via OLE Automation, this call is cross-process, and, therefore, the DisplayAlerts setting will persist until you change it. (If called in-process, via VBA, it is switches back to to true automatically when the routine completes. The same behavior probably applies for a VB.NET or C# add-in called via a CommandBar or Ribbon control, but one would need to test to be certain.)