I'm developing a windows service, generating a report. This report has a template. This template is prepared in an excel file. This file is copied to the output folder.
While developing I launched the service like a console application and had no problems accessing this file.
Then I prepared a service installer. The service is installed under Local System account. So this excel template file is marked as content and copied to the installation directory together with the executable as well.
But when the service is launched excel appears to have no access to this file. The service is installed to c:\Program Files (x86)\Our Company\Service Name\. The target OS is Windows Server 2008. While testing I use Windows 7 and run into the same issue.
I use the following code to access excel.
using Excel = Microsoft.Office.Interop.Excel;
//...
Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
//the following line throws an exception
Excel.Workbook xlWorkBook = xlApp.Workbooks.Open(#"path");
I also tried to copy the excel template file to some temporary directory (where the service has the right to write - this is tested) and tryed to open it from there, but to no success (while this variant works good in a console application as well).
The error message sais:
Microsoft Office Excel cannot access the file /path/.
There are several possible reasons:
1. The file name or path does not exist.
2. The file is being used by another program.
3. The workbook you are trying to save has the same name as a currently open workbook.
How can I make the windows service access this excel template file? Or is there another alternative?
To safety run Office applications (Excel and others) under user service with Local system account you must know two important things:
1) In Windows Server 2008/2008 R2 you must manually create two folders:
C:\Windows\system32\config\systemprofile\desktop
C:\Windows\SysWow64\config\systemprofile\desktop (for x64 version only)
Without this folders you cannot correct run office Applications from Local SystemAccount
2) If you service is configured without desktop interaction then in the first time launched office application (Excel for example) freeze on user credentials dialog - you cannot see this window in this mode - to resolve this enable desctop interacting, switch to office window after you service run it and manually enter credeentials.
Other information there(use google translater to read).
There is a detailed MS knowledge base article titled Considerations for server-side Automation of Office. Some key excerpts:
User Identity: Office applications assume a user identity when the applications are run, even when Automation starts the
applications. The applications try to initialize toolbars, menus,
options, printers, and some add-ins based on settings in the user
registry hive for the user who launches the application. Many services
run under accounts that have no user profiles (such as the SYSTEM
account or the IWAM_[servername] accounts). Therefore, Office may not
initialize correctly on startup. In this situation, Office returns an
error on the CreateObject function or the CoCreateInstance function.
Even if the Office application can be started, other functions may not
work correctly if no user profile exists.
Interactivity with the desktop: Office applications assume that they are being run under an interactive desktop. In some
circumstances, applications may need to be made visible for certain
Automation functions to work correctly. If an unexpected error occurs,
or if an unspecified parameter is needed to complete a function,
Office is designed to prompt the user with a modal dialog box that
asks the user what the user wants to do. A modal dialog box on a
non-interactive desktop cannot be dismissed. Therefore, that thread
stops responding (hangs) indefinitely. Although certain coding
practices can help reduce the likelihood of this issue, these
practices cannot prevent the issue entirely. This fact alone makes
running Office Applications from a server-side environment risky and
unsupported.
Obviously, as has been pointed out in the comments, using the SYSTEM account is a mistake. You would need to run the service under an account that has a user profile.
But even when you fix that, the other bullet point will kill you. Office applications do indeed assume they are running under an interactive desktop. My advice is to abandon attempting to automate Office from a service. Use a library like Aspose instead. Or run the process on an interactive desktop.
I just faced the same problem.
I have made a .bat file where I called the .exe file.
finally, I called the .bat file from the task scheduler actions.
It just works fine.
Related
Task Scheduler on a Windows server
User Account is System
Starts a .NET windows app that reads an Excel file
Error:
Microsoft Excel cannot access the file 'D:\Automation\02_14_25_.xlsx'
There are several possible reasons:
• The file name or path does not exist.
• The file is being used by another program.
• The workbook you are trying to save has the same name as a currently open workbook.
I created the folder Desktop in C:\Windows\SysWOW64\config\systemprofile and C:\Windows\System32\config\systemprofile\ but still same error.
When I log in to the server as myself(administrator) and run the app, it runs without errors.
Any suggestions please?
You did not clarify that the file: "D:\Automation\02_14_25_.xlsx"
Actually exists or if that is just the error message you could not correctly interpret.
In that case my answer would be:
Your application is not started with the correct environment variables if it runs as a scheduled task. That is my classical mistake for the:
"It works when i run it manually but it doesn't when i do it with cron/scheduled task." - Scenario
I have a Windows service written in c# which keeps listening to one Event Hub in Azure. As soon as a message is received, the service processes the message and does some execution and calculation.
As part of the execution, it launches a application called AutoCal (company's own window's application), which is COM component similar to that of Excel.
Earlier I had a web api which does the same calculation/execution. Upon every request it opens AutoCal and does some processing. I have added the AutoCal DLL as reference in the project.
The code to open AutoCal is something similar:
(AutoCal.Application)Interaction.CreateObject("AutoCal.Application.NewInstance").
When I tested this locally, it has perfectly as expected. But once I hosted this on the server, it has thrown an error saying "Cannot create ActiveX component". To rectify this, I have given permission to open COM components to Application Pool of IIS. This has resolved my issue.
Now that I have a windows service which also open the AutoCal, from where do I give CO component permissions. I have searched for it, but everywhere the solution is for ASP.net only.
How can I rectify this issue for Windows service?
PS: When I have written same code in console application, it is working fine.
Without having exact error logs (can you try looking for related errors in the EventViewer?) it's hard to tell what the problem is.
But I would try the following:
In the start menu type Component services and open it (right click - as admin!)
Go to Component services -> My Computer -> DCOM Config folder
You'll see something like this
Find your COM Application in the tree.
Right click it, open properties, go to Security Tab
It will look like this (never mind the title of the tab in the picture, in your case it should be something like AutoCal):
If it's grayed out, like in my case, you can use the following procedure to change the settings on your system, and make this tab configurable:
Go to Start > Run. Enter regedit
Go to the key that is associated with the DCOM component you want to manage: HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID\{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
Right click on it. Select Permissions
Click Advanced
Change the owner to Administrator or your user account
Click OK
Select Full Control for the Administrators group and owner you selected
Go to Start > Run. Search for services.
Find COM+ System Application. Right click on the service, then click Restart
Once you have the Security tab enabled, you can change the permissions for your COM object. For example - you can allow the user, under which your service runs, to access or activate this COM object.
I hope this helps you, but again, without any additional error info - it's a long shot.
You will want to run it under NETWORK SERVICE, but that's not the problem.
What you're experiencing is all summarised under KB257757.
Considerations for server-side Automation of Office
Your best bet is rewrite it in .Net. If its basic and you're NOT using XML, it might be worth giving that format a go. Back in the day we had to make sure everyone (all our customers) were on MS Office 2003 (turned out IBM were the only ones on 2002 and there's a plugin for 2002 to read 2003).
I know this is not good and I'm sorry to be the bearer of bad news.
Microsoft's stance:
Most server-side Automation tasks involve document creation or editing. Office 2007 supports new Open XML file formats that let developers create, edit, read, and transform file content on the server side. These file formats use the System.IO.Package.IO namespace in the Microsoft .NET 3.x Framework to edit Office files without using the Office client applications themselves. This is the recommended and supported method for handling changes to Office files from a service.
I'm using the Microsoft.Office.Interop.Outlook to do the following:-
Read an Outlook folder called 'Pending'
Get the attachment from all emails under 'Pending' folder
Save the attachment to hard disk folder
Read the attachment from the saved file and upload to our data base
All the above points are working perfectly fine if I run my C# console application manually.
It also works sometimes when I launch the console application from Windows Service. But some times not.
I read somewhere in Stack that Microsoft.Office.Interop.Outlook is not designed for Windows Services.
What is the best method (quick and fast to develop) to all the above task from Windows Service?
What is the best method (quick and fast to develop) to all the above task from Windows Service?
Short answer - you can't.
COM Automation servers such as the ones from Microsoft Office are GUI-based and therefore require a message pump. When you consider that Windows Services typically run prior to a user logging in, it's not possible to launch a process that attempts to show a GUI. It would simply lock-up.
One could argue that you could always wait until the user logs into Windows but then it sort of defeats the purpose of windows services - that user login is not necessary. Plus if Windows were to reboot your app would not run until the user logs in again.
I developed a C# program that pulls data from a SQL Server database and then generates Word documents which include the data. I've set the program up to run as part of an SSIS job on a Windows Server 2003 box. The program runs as user SQLSVC which doesn't have administrative privileges. When I log in as SQLSVC and run the program it executes correctly. However, when the program is run automatically as an SSIS job it freezes at the following line of code
Microsoft.Office.Interop.Word.Application word =
new Microsoft.Office.Interop.Word.Application();
When I kill the process forcibly, the following error message is generated.
Error Message: System.Runtime.InteropServices.COMException (0x80080005):
Retrieving the COM class factory for component
with CLSID {000209FF-0000-0000-C000-000000000046}
failed due to the following error: 80080005.
at IepGlance.Program.CreateNewIepFiles(Dictionary`2
iepDictionary, EasyIepDataContext dbContext)
at IepGlance.Program.Main(String[] args)
As far as I can figure out the problem is with DCOM permissions. I've used dcomcnfg to add all possible DCOM permissions to user SQLSVC, but this hasn't helped. Are there any other possible solutions?
Run program "dcomcnfg -32". ( You cant find the word and excel components if it runs under 64bit)
Go to "Console Root/Component Services/Computer/My Computer/DCOM Config/" Look up Microsoft Word and Excel and choose properties.
Go to Security and select "Customize" under "Configuration Permissions. (If needed you might want to change the other permissions as well, but I didn't need to) Add "IIS_IUSRS" and give it "Full Control".
Now go to "Identity" and select "The interactive user".
Couple of things here.
First, this thread on SO may help.
Second, Microsoft warns that 'complications' may arise when you automate Office through an unattended process. Here's the punchline (bolded in the original):
Microsoft does not currently
recommend, and does not support,
Automation of Microsoft Office
applications from any unattended,
non-interactive client application or
component (including ASP, ASP.NET,
DCOM, and NT Services), because Office
may exhibit unstable behavior and/or
deadlock when Office is run in this
environment.
The linked article discusses workarounds.
It depends whether you are on a 64-bit machine and if you are 32-bit Office or 64-bit office, but in either scenario you need to go into the Admin Tools > Component Services and under DCOM config you need to find 'Microsoft Word 97 - 2003 Document', and then set the 'identity' to the user that is running your app pool. or simply disable the security on it.
If you are running a 64-bit server with 32-bit Office, you may have trouble finding this DCOM setting. You will need to run "MMC -32" from the command prompt to launch 32-bit MMC and then add 'Component Services' from the 'File > Add / Remove Snap-ins' menu.
Hope this helped
One point from my side,
I was scheduling the batch job in one of our server and it was throwing the same error whereas it was running in my local.
I tried all of the above steps but in my case actual scenario was different.
Whenever schedule the batchjob, do not select the option [Run whether user is logged on or not] because this requires the admin access and if you are not, you are in problem.
Does anyone know how to get the MS Office 2007 .NET C# Interop libraries to work with Vista?
I have a .NET C# application that I have setup to run as a Windows service. This program will open up a Word or Excel template depending on the situation and modify its contents and then save the document back out. All of this worked great when I was doing it on a Windows Server 2003 or XP machine using Office 2007. When I moved everything to a Server 2008 box, everything quit working. In Excel for example, I get a COM exception telling me that the Excel file cannot be opened when the file is clearly there and I can open it just fine when doing it manually. The windows service is running under the same user account that I log into the machine with and that account is an Administrator.
Does anyone have any idea what to do?
On Vista and Windows Server 2008, services run in something called Session0. Before Vista, regular programs would run in Session0 alongside services.
This means that Session0 has become a desktop-less wasteland where your services can't even access explorer.exe. I'm pretty sure the problem is that Office applications are expecting to be able to access a few components that are normally on the desktop.
Since Excel, Word, etc. are only supported on a desktop-ed session, you only have a few choices:
Set the Desktop checkbox in the LogOn tab of your Service's properties and pray that it appeases the Office gods. (It probably wont.)
After trying 1, go through your code and try and remove/work around anything that causes it to crash.
Use remoting/WCF to make a server that performs the interop work, and make your service communicate with it.
You'll need to have a logged in interactive user and the user needs to start the server application somehow. Perhaps best to use autostart.
You can try turning on Automatic login. http://support.microsoft.com/kb/324737
Try impersonating a Logged in user using CreateProcessAsUser and friends.
Note: I don't know how well this works unless a user is actually logged in, so it might not be any more useful than 2 above, and is much harder to pull off. (Needs P/Invoke)
Rewrite your program to use the OpenXML sdk or use something like SpreadsheetGear.
You should really avoiding running the Office clients as server side apps. Consider using xml as file format (xlsx for Office 2007, or using the Excel workbook xsd for (somewhat) older versions.) Then you would be freed from using the Excel API on the server.
I did find an interesting article from Microsoft basically saying don't do Office automation.
Get the installables from
http://www.microsoft.com/downloads/details.aspx?FamilyID=59daebaa-bed4-4282-a28c-b864d8bfa513&displaylang=en
install it on your system and refer excel dll in your solution and hopefully it should work.
Do you have the primary interop assemblies installed on the server? These are usually located in the GAC and not included in the bin directory when you build your program, so they would need to be installed locally on the server.
This is just a guess, but it might be UAC. I know that privileged (admin) applications and user applications cannot send messages to each other or communicate in any way. Your service is running as an administrator, but your desktop is running as a regular user under UAC even though they are the same user. I also expect that Office has started up (pre-loaded) parts of itself on startup and that would be running as a regular user.
Try turning off UAC and see if that helps. If so, at least you know what it is.
Do you leave an account logged on to the machine? Office is not a server-side app, and you will get random errors if you try to launch any of the executables without a desktop context.
Something to remember about Office. Its x86 only, so if your creating an application in x64, you will not be able to access the Office underlying COM objects. You will need to compile your application in x86, then it would work.
You can do that by going into the properties of your project, and selecting x86 under the build tab in visual studio.
This is all assuming that your app is being developed/run in a x64 enviroment that is.