通过非个性化从.NET Web应用程序启动流程

时间:2016-04-27 11:59:29

标签: asp.net process executable windows-authentication impersonation

我尝试从web应用程序调用.exe文件。 但是我希望用户调用的文件是由来自网站的windoes身份验证的非个人化。

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);
}

正确记录两个信息日志文本。没有错误发生。 但被叫程序没有做任何事情。没有记录,没有在数据库中写入。 用户对该文件具有可执行权限。

当我从Development Server调用相同的代码时,它工作正常。

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

我做错了什么? 或者我怎么能知道什么是错的?

非常感谢,

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

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

    private bool IsRunning(string name)
    {
        Process[] processlist = Process.GetProcesses();

        if (Process.GetProcessesByName(name).Length > 0  )
        {
            return true; 
        }
        else
        {
            return false;
        }
    }

3 个答案:

答案 0 :(得分:1)

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

path = exe文件的文件路径

arguments =用

启动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);
                }


            }

答案 1 :(得分:0)

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

你必须使用模拟,如果你真的想这样做,但你必须启动该过程“冒充”登录网站的用户,因为用户登录的用户帐户甚至有意义在那时候。例如。如果它是域帐户,这可能会有效,但如果您使用其他类型的身份验证,例如表单身份验证,则这在操作系统级别上没有意义,因此您无法在IIS中使用这些凭据进行模拟。

根据我的经验,我已经做了几次,在IIS中模仿总是一件坏事,总是会产生问题,顺便说一下启动命令行过程也是如此。幸运的是总有一个更好/替代方案你想到它的解决方案。等待进程在代码中结束也不是一个好习惯。如果进程阻止怎么办?它会阻止网站。

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

答案 2 :(得分:0)

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

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

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