从具有非个性化设置的 .NET Web 应用程序启动进程



我尝试从Web应用程序调用.exe文件。但是我想要由用户调用的文件,该文件由网站的Windows身份验证非个性化。

Process process = new Process();
try
{
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.FileName = ConfigData.PVDToBudgetDBexePath;
    process.StartInfo.CreateNoWindow = false;
    process.Start();
    log.Info("Process started by " + WindowsIdentity.GetCurrent().Name +  " with ID: " + process.Id);
    process.WaitForExit();
    log.Info("After WaitForExit Process ID: " + process.Id);
}
catch (Exception ex)
{
    log.Error("Error executing file with message " + ex.Message);
}

两个信息日志文本都已正确记录。没有发生错误。但是被调用的程序不执行任何操作。没有日志记录,没有写入数据库。用户对文件具有可执行权限。

当我从开发服务器调用相同的代码时,它工作正常。

我使用 .Net 4.5 和 IIS 7我发现有关此主题的帖子仅适用于非常旧版本的.Net和IIS,这对我无济于事。

我做错了什么?或者我怎样才能找出出了什么问题?

非常感谢,

编辑:为了更好地阐明我的意图:我有这个(自制的)exe文件,可以将Excel工作表中的数据导入数据库。这需要一些时间。在这样做的同时,它会将其进度和log4net也记录到数据库中。我想要一个UI(Web应用程序)是用户可以触发导入的。在此 UI 上还有一个 ajax 进度条,显示从数据库中的日志表中导入 takten 的进度。

我希望此导入过程最多同时运行一个实例。所以我有一个函数来检查进程是否仍在运行。如果是这样,则不允许启动另一个进程。如果没有,您可以重新启动它。

    private bool IsRunning(string name)
    {
        Process[] processlist = Process.GetProcesses();
        if (Process.GetProcessesByName(name).Length > 0  )
        {
            return true; 
        }
        else
        {
            return false;
        }
    }

我现在通过TimeScheduler启动exe文件解决了这个问题。

路径 = 文件EXE文件的路径

参数 = 用于启动 exe 文件的参数

using Microsoft.Win32.TaskScheduler;

            using (TaskService taskService = new TaskService())
            {
                var taskDefinition = taskService.NewTask();
                taskDefinition.RegistrationInfo.Author = WindowsIdentity.GetCurrent().Name;
                taskDefinition.RegistrationInfo.Description = "Runs exe file";

                var action = new ExecAction(path, arguments);
                taskDefinition.Actions.Add(action);
                taskService.RootFolder.RegisterTaskDefinition("NameOfTask", taskDefinition);
                //get task:
                var task = taskService.RootFolder.GetTasks().Where(a => a.Name == "NameOfTask").FirstOrDefault();
                try
                {
                    task.Run();
                }
                catch (Exception ex)
                {
                    log.Error("Error starting task in TaskScheduler with message: " + ex.Message);
                }

            }

如果您所说的开发服务器是指由Visual Studio启动的Web服务器,那么这将为您提供一个错误的测试用例,因为该服务器由Visual Studio启动并使用您的Windows帐户运行,而标准配置的IIS不是在"用户"帐户下运行,而是在非常有限的系统帐户下运行(幸运的是!!即使用户使用您网站的域帐户登录,IIS 进程也不会在此帐户下运行(无论如何这都没有意义)。这就是为什么此代码不会在 IIS 中运行,而是在开发服务器中运行的原因。即使您启动 exe,它也将使用 IIS 的系统帐户运行,因为您没有提供任何帐户,这是一个有限的帐户,它将再次以不同于您预期的方式运行 exe。

如果您真的想这样做,您将不得不使用模拟,但您必须启动该过程"模拟"登录网站的用户,支持用于登录的用户帐户在这一点上甚至有意义。 例如,如果它是一个域帐户,这可能会起作用,但是如果您使用某种其他类型的身份验证, 与窗体身份验证一样,这在操作系统级别没有任何意义,因此不能将这些凭据用于 IIS 中的模拟。

根据我的经验,我已经这样做过几次,在IIS中模拟总是一件坏事,并且总是会产生问题,顺便说一下,启动命令行进程也是如此。幸运的是,当您考虑它时,总有一个更好/替代的解决方案。此外,等待进程在代码中结束并不是一个好的做法。如果进程阻塞怎么办?它将阻止网站。

幸运的是,当您考虑它时,总有一个更好/替代的解决方案。这里更好/可能的解决方案是使用消息队列,例如,您只需推送消息以执行任务,另一端是处理消息的应用程序,然后可能会使用此命令行工具。该应用程序可以在所需的任何用户帐户下运行,而不必让 IIS 在其他帐户下运行。稍后您当然必须回来查找操作的结果,但这可以使用网站后台的回调来完成。虽然这个解决方案比你想做的要大一点,但它几乎在每个领域都会有更好的结果(网站的响应能力、可维护性、可扩展性,..唯一更糟糕的是你需要的代码行,但这很少是一个需要考虑的有效因素

如果您自己编写用于 excel 处理的应用程序,则可以将数据库中的表用作某种队列,而不是使用消息总线。然后,您的 Web 应用程序只需在该表中添加包含流程的所有必要信息的行,状态和进度就是其中之一。扩展您的处理应用程序以持续监视此表,一旦它检测到新记录,它就可以开始执行必要的任务并相应地更新数据库进度、状态和最终结果)。这避免了消息传递子系统,将同样出色地工作,并且将避免您不得不启动具有模拟的进程,这是一开始的邪恶事情。

您可以将 excel 进程修改为 Windows 服务,以便它连续运行并与系统一起启动,但是,如果您不想这样做,还有一些工具可以将任何命令行应用程序作为 Windows 服务运行)。

这种技术比模拟容易得多,并允许您的网站在其受保护的环境中运行

最新更新