我通过使用托管自己的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应用程序。