代码之家  ›  专栏  ›  技术社区  ›  Martien de Jong

替代“创建用户会话并使用C_从IIS启动其中的应用程序”

  •  0
  • Martien de Jong  · 技术社区  · 6 年前

    MS Access数据库用于在服务器上进行处理。 当前的过程是,人们使用RDP登录到服务器,然后在mdb文件中运行宏。 这些宏有时需要几天才能执行。

    开发了一个在mdb文件中运行代码的Web应用程序。 当MS Access显示类似“禁用宏”的对话框时,是否信任此文件?(由于服务器更新)或未正确处理的任何错误,进程不会退出,而是一直等待MS访问完成。

    由于存在IIS,MS Access进程正在会话0中运行,无法向用户显示该进程。 我想做的是让用户连接到RDP会话,查看MS Access应用程序并调试VBA代码。

    理想情况下,我会创建一个新的用户会话并在其中运行mdb应用程序,但这似乎是不可能的;因为存在安全风险,Microsoft已经禁用了它。

    处理这种情况的最佳方法是什么?

    任何让MS Access应用程序出现在RDP会话中的解决方案都是受欢迎的。

    我现在的想法是这样的:(但我想听听更方便的解决方案)

    • 在交互式会话启动时运行应用程序,该会话与IIS进程通信,并在收到指示时在前台启动MS Access应用程序。
    • 如果此应用程序没有运行(没有打开RDP会话),则Web应用程序会给出一条错误消息,说明在启动此作业之前请使用RDP进行连接。
    1 回复  |  直到 6 年前
        1
  •  0
  •   Martien de Jong    6 年前

    我通过使用托管自己的Windows窗体应用程序来解决这个问题,这样就可以从Web服务调用它,并结合互操作访问库来启动MS Access和teststack.white库来监视MS Access正在做什么。 最终结果是,用户可以从Web应用程序启动远程计算机上的MS访问。然后,当它正常运行时,结果消息将返回到Web客户机。如果出现问题,用户将收到一条消息,即他们必须通过RDP会话登录才能查看/调试MS访问。如果表单应用程序没有运行(在用户的启动文件夹中),则会显示一条消息,说明必须启动RDP会话才能在远程计算机上执行MS访问文件。表单应用程序中还记录了错误,因此用户有一个以前运行期间在计算机上发生的事件的日志。

    免责声明:这段代码绝不是完整的,它是对我认为重要的代码片段的一般性摘录。(整个应用程序集是巨大的)应该可以将它们融合在一起,形成一些可行的方法。如果有人要求,我会提出一个完整的解决方案,并张贴出来。我想给别人一个可能在寻找类似的东西开始。

    使用TCP的服务主机:

        var host = new ServiceHost(typeof(MyService),
            new Uri("net.tcp://localhost:9001"));
    
        host.AddServiceEndpoint(typeof(IMyService),
            new NetTcpBinding(), "MyService");
        host.Open();
    

    然后在服务中,我在新线程中实例化MS访问:

        Thread t = new Thread(() => { result = RunMdb(pathToMdbFile, "MyFunction", true); });
        t.Start();
    

    实例化MS Access的函数:

        private string RunMdb(string path, string functionToRun, bool visible)
        {
            string result;
            try
            {
                Directory.SetCurrentDirectory(newDir);
    
                // get the MS Access process, we need it later
                var before = Process.GetProcessesByName("MSACCESS");
                MsAccessApp = new Microsoft.Office.Interop.Access.Application { Visible = visible };
                var after = Process.GetProcessesByName("MSACCESS");
                var process = after.Single(p => !before.Select(p1 => p1.Id).Contains(p.Id));
                MsAccessProc = process;
    
                MsAccessApp.OpenCurrentDatabase(newDbPath, false);
                result = MsAccessApp.Run(functionToRun);
            }
            catch (Exception e)
            {
                result = $"MS Access Error: {e.Message}";
                log.Log("MS Access Error:", e);
            }
            finally
            {
                if (IsFunctionRunning)
                {
                    try
                    {
                        MsAccessApp.CloseCurrentDatabase();
                    }
                    catch
                    {
                        // ignored
                    }
                    try
                    {
                        MsAccessApp.Quit(Microsoft.Office.Interop.Access.AcQuitOption.acQuitSaveNone);
                    }
                    catch
                    {
                        // ignored
                    }
                }
            }
            MsAccessApp = null;
            MsAccessProc = null;
            IsFunctionRunning = false;
            return result;
        }
    

    然后在主线程中,我开始使用teststack轮询MS访问。白色:

        result = TrackMsAccessPopups(log, result);
    
        private string TrackMsAccessPopups(ILogger log, string result)
        {
            while (IsFunctionRunning)
            {
                Thread.Sleep(1000);
                if (MsAccessProc != null)
                {
                    if (WhiteApplication == null)
                    {
                        WhiteApplication = TestStack.White.Application.Attach(MsAccessProc);
                    }
                    log.Log(LogLevel.Info, "GetWindows.");
                    WhiteWindows = WhiteApplication.GetWindows();
                    log.Log(LogLevel.Info, "GetWindows done.");
                    if (WhiteWindows.Count > (MsAccessApp.Visible ? 1 : 0))
                    {
                        IsFunctionRunning= false;
                        log.Log(LogLevel.Error, "MS Access has created a popup.");
                        result = $"MS Access has created a popup. Log in on {Environment.MachineName} to view the message.";
                    }
                }
            }
            WhiteApplication = null;
            return result;
        }
    

    生成的字符串通过服务回调返回到Web应用程序。