如何从Windows服务运行excel vba代码

时间:2013-02-24 17:21:37

标签: c# windows excel excel-vba windows-services vba

我想从Windows服务运行一些excel vba代码。该服务正在使用fileSystemWatcher来监视要添加的xml文件的目录。添加文件后,xml文件的内容将反序列化为对象属性。在这个阶段,我想打开一个excel文件,并将这些值传递给某些单元格,并从该工作簿中运行vba代码。我从Windows窗体应用程序完美地工作,但我不能从我的Windows服务应用程序。我将一个调试器附加到应用程序以尝试查看发生了什么,但没有抛出错误并且所有步骤都已成功完成。我知道Windows服务不支持打开MS Office文件,因为存在与UI交互及其具有的用户权限的问题。但我正在寻找一种能够从服务中运行此vba代码的方法。我正在使用Windows 7家庭高级版32位,我的帐户用于我的服务设置为LocalSystem。这是我正在使用的代码:

    private void FSWatcherTest_Created(object sender, System.IO.FileSystemEventArgs e)
    {
            Trade t;
            XmlSerializer serializer;
            XmlReader reader;
            XmlWriter writer;

            string filePath = @"C:\Inbox\TradeInfo.xml";


            serializer = new XmlSerializer(typeof(Trade));
            reader = XmlReader.Create(filePath);
            t = (Trade)serializer.Deserialize(reader);
            reader.Close();



            string path=@"C:\Windows\System32\config\systemprofile\Desktop\TwsDde.xls";

            oXL = new Microsoft.Office.Interop.Excel.Application();

            oXL.Visible = true;

            oXL.DisplayAlerts = false;

            mWorkBook = oXL.Workbooks.Open(path,2, false, 5, "", "", true,Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "", true, false, 0, true,false, false);

            //Get all the sheets in the workbook

            mWorkSheets = mWorkBook.Worksheets;

            //Get the allready exists sheet

            mWSheet1=(Microsoft.Office.Interop.Excel.Worksheet)mWorkSheets.get_Item("Basic Orders");

            // Microsoft.Office.Interop.Excel.Range range= mWSheet1.UsedRange;

            mWSheet1.Cells[12, 1] = "GE";
            mWSheet1.Cells[12, 2] = "STK";
            mWSheet1.Cells[12, 7] = "SMART";
            mWSheet1.Cells[12, 9] = "USD";
            mWSheet1.Cells[12, 12] = "Buy";
            mWSheet1.Cells[12, 13] = "100";
            mWSheet1.Cells[12, 14] = "MKT";

            Excel.Range range;
            Excel.Range row;

            range = mWSheet1.get_Range("A12", "O12");
            range.EntireRow.Select();

            oXL.Run("TwsDde.xls!Sheet2.placeOrder");
        }

非常感谢任何帮助。或者做同样事情的其他方法,即运行包含此代码的Windows窗体可能?

3 个答案:

答案 0 :(得分:3)

您尝试做的是not supported

  

Microsoft目前不建议也不支持从任何无人参与的非交互式客户端应用程序或组件(包括ASP,ASP.NET,DCOM和NT服务)自动化Microsoft Office应用程序,因为Office可能会出现不稳定Office在此环境中运行时的行为和/或死锁。

如果流程在交互式桌面中运行,则可以自动执行Excel。尝试从非交互式桌面(例如,从会话)自动化Excel不受支持并失败。

答案 1 :(得分:1)

嗨,我设法让这种工作以一种方式进行。我基本上遵循了launch an interactive process from a service上的本教程和代码,允许服务以SYSTEM用户身份运行,但是为第一个登录用户采用会话ID,并为用户提供管理权限以运行GUI应用程序等交互式流程。要打开excel并通过Windows服务运行宏我首先在Windows窗体应用程序中编写了所有代码来执行此操作,然后测试它在那里工作。然后我改变了可执行文件,它运行得很好。我希望这可以帮助其他人解决同样的问题。

答案 2 :(得分:0)

在没有启用“桌面交互”的情况下,Excel在用户服务下运行良好 第一,创建Excel COM的标准方法无法在服务下运行。您需要从程序启动Excel.exe进程 - 使用ShellExecuteEx(推荐方式)或CreateProcess(未推荐)来执行此操作。
第二个阶段:使用GetActiveObject附加到Excel COM Application对象。现在您可以正确访问所有Excel COM接口 此外,在多个操作系统中,Excel可能会在LocalSystem帐户下错误地崩溃 - 要手动创建2个文件夹:         C:\ WINDOWS \ system32 \设置\ systemprofile \桌面
        C:\ WINDOWS \ SYSWOW64 \ CONFIG \ systemprofile \桌面 没有desctop服务的其他bug在第一次与Excel交互时会询问用户凭据并冻结在内存中。您可以在注册表或界面中禁用它(请参阅Excel帮助)。有关启动流程的其他信息是there