在 Windows 服务中运行命令行 exe。
在 Windows 服务中运行命令行 exe。
我有一个用于执行以下操作的Windows服务:
- 监控服务器上的文件夹,以便检测PDF文件
- 当文件到达时,运行第三方exe将PDF转换为Excel。不会生成文本输出。第三方工具只需使用输入文件路径并生成输出Excel文件。无需启动窗口,也无需跟踪会话。
- Windows服务从Excel中读取数据,进行处理,并将输出的xml文件放入一个文件夹中。
在调试模式下,这一切都正常工作。然而,当我尝试在发布模式下(使用installutil)在本地机器上运行Windows服务作为服务时(而不是在Visual Studio中),它无法工作。当我附加到进程时,我注意到光标停留在waitforexit上,并且没有生成Excel文件。由于它在调试模式下工作但在发布模式下不工作,我怀疑这是一个权限问题。任何反馈将不胜感激。
已尝试检查“允许服务与桌面交互”。没有帮助。
编辑:更正 - 光标实际上停留在exeProcess.WaitForExit()
ProcessStartInfo sInfo = new ProcessStartInfo(); sInfo.FileName = ConfigurationManager.AppSettings["FileName"]; sInfo.Arguments = GetArguments(); sInfo.UseShellExecute = false; sInfo.CreateNoWindow = true; sInfo.ErrorDialog = false; sInfo.WindowStyle = ProcessWindowStyle.Hidden; //sInfo.RedirectStandardError = true; //没有起作用 //sInfo.RedirectStandardInput = true; //没有起作用 //sInfo.RedirectStandardOutput = true; //没有起作用 using (Process exeProcess = Process.Start(sInfo)) { //StreamWriter inputWriter = exeProcess.StandardInput; //StreamReader outputReader = exeProcess.StandardOutput; //StreamReader errorReader = exeProcess.StandardError; exeProcess.WaitForExit(); }
问题原因:运行Windows服务时,无法从命令行执行.exe文件。
解决方法:添加适当的异常处理和日志记录,以便查找是否有与预期不同的情况。下一步可能是使用您知道可以访问要运行的可执行文件的凭据来配置服务,以及导出生成的文件的目录等。如果可能/可用,则尝试使用可以引用的程序集而不是从代码中运行另一个可执行文件。这样,您将更加掌控。
总体上,可以通过Windows服务运行命令行工具。只需要明确工具希望如何获取数据,如果数据是从命令行获取的,并且工具不等待用户输入。您只是与这个命令行工具有问题还是普遍存在问题?
Service类代码如下:
private FileSystemWatcher watcher;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
watcher = new FileSystemWatcher();
watcher.Path = @"c:\temp\service";
watcher.Created += watcher_Created;
watcher.EnableRaisingEvents = true;
}
protected override void OnStop()
{
}
private void watcher_Created(object sender, FileSystemEventArgs e)
{
try
{
ProcessStartInfo startInfo = new ProcessStartInfo(pathToExe, e.Name);
EventLog.WriteEntry(e.Name);
Process process = Process.Start(startInfo);
process.EnableRaisingEvents = true;
}
catch (Exception ex)
{
EventLog.WriteEntry(ex.ToString());
}
}
命令行工具代码如下:
public class Program
{
public static void Main(string[] args)
{
File.AppendAllText(pathToLog, string.Format("{0} - File got created in watched folder - doing conversion of {1}\n", DateTime.Now, args[0]));
}
}
在“登录”选项卡下,选择了“Local System”帐户,并勾选了“允许服务与桌面交互”。我相信这具有很高的特权。不幸的是,第三方.exe文件是我唯一拥有的。没有dll文件。
感谢提供的代码。我已经几乎完全按照这个做了,但是它没有起作用。最后,我创建了一个无GUI的Windows应用程序,并在服务器上使用任务计划程序运行它。我选择了即使没有登录用户也运行的选项。我还不得不创建一个文件夹(C:\ Windows \ SysWOW64 \ config \ systemprofile \ Desktop),因为如果没有这个文件夹,我的通过任务计划程序运行的应用程序不会创建Excel文件(不确定这个文件夹是如何解决这个问题的)。无论如何,现在pdf2xl.exe正在运行并创建Excel输出。
问题的出现的原因是步骤2和步骤3在非交互式会话0中无法正常工作。不同之处不在于debug和release版本之间的差异,而在于在交互式桌面上运行和在会话0中运行的服务之间的差异。
要解决这个问题,并继续使用服务,您需要确保所有步骤都可以在会话0中运行。我们对步骤2一无所知。步骤3似乎涉及自动化Excel。根据官方的说法,这是不受支持的,并且已知在会话0下无法工作。您需要使用除Excel之外的其他工具来读取Excel文件。至于步骤2,这取决于将PDF转换为Excel的第三方工具。
如果我将所有的代码都移动到控制台应用程序中,并使用topshelf将其作为Windows服务运行,这样会有帮助吗?然后,我能够从控制台应用程序中调用第三方pdf-to-excel命令行exe吗?经过一整天的搜索,我几乎放弃了从Windows服务中调用第三方exe的想法。
问题,我强烈怀疑,是代码在会话0中运行的原因。Topshelf不会改变这一点。我猜想步骤3是否涉及自动化Excel?
不确定您具体在问什么,但是以下是流程:
1. 客户端wpf应用程序将pdf文件放入服务器的"pdf"文件夹中。
2. Windows服务使用文件系统监视器接收该文件,并运行第三方工具将其转换为Excel文件,并将其放入"excel"文件夹中。
3. Windows服务使用第二个文件系统监视器接收Excel文件,使用OleDbConnection将其读入数据表中。数据被处理并转储到第三个"xml"文件夹中。
4. 客户端wpf应用程序监视xml文件,清理它并显示结果。
刚刚尝试了Topshelf + Console App组合。没有成功。这次光标只是在代码中移动,但没有生成Excel文件。:-(
好的一部分是,Windows服务能够读取手动放入的Excel文件,并按预期的方式返回处理后的数据,所以至少任务的后半部分是正常工作的。
当您进行调试时,您将在调试控制台应用程序,对吗?它们不会作为会话0中的服务运行。