windows 从服务的执行线程执行命令行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8245540/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 18:31:03  来源:igfitidea点击:

Execute a command line from a service's Execute thread

windowsdelphiwinapiservicedelphi-7

提问by Henrik Erlandsson

At first glance I'm having no luck with

乍一看,我不走运

uses ShellApi;

...

ShellExecute(Handle, pchar('open'), pchar('emf2pdf.exe'), 
             pchar(s), pchar(root), SW_SHOWNORMAL);

where s is the parameter string and root is the directory where the command is located.

其中 s 是参数字符串,root 是命令所在的目录。

The error I get is 'missing operator or semicolon', and also 'too many actual parameters'.

我得到的错误是“缺少运算符或分号”,还有“实际参数太多”。

Probably something easy I overlooked, bit stressed. Not even sure where to get the Handle from.

可能是我忽略了一些简单的事情,有点压力。甚至不确定从哪里获得手柄。

Be happy for alternative ways of executing a command line that you can suggest! Basically the service looks for files to convert at regular intervals, so I'm just looking for a way to form a command line such as in DOS and execute it, preferably without a window popping up briefly and closing, but I'll take what I can get. :)

对您可以建议的执行命令行的替代方法感到高兴!基本上,该服务会定期查找要转换的文件,所以我只是在寻找一种方法来形成命令行(例如在 DOS 中)并执行它,最好不要短暂弹出并关闭窗口,但我会采取什么我可以得到。:)

My correct installation of Delphi can code-hint the parameters for me, but not popup a help page on pressing F1 (not found in index).

我正确安装 Delphi 可以为我代码提示参数,但不会在按 F1 时弹出帮助页面(在索引中找不到)。

Update: Used this CreateProcess function from DelphiPages:

更新:使用 DelphiPages 中的这个 CreateProcess 函数:

Function ExecuteAndWait(sExecutableFile : String; wWindowState : Word = SW_SHOWNORMAL) : Boolean;
var
siInfo : TStartUpInfo;
piInfo : TProcessInformation;
begin
    FillChar(siInfo, SizeOf(siInfo), #0);

    with siInfo do begin
    cb := SizeOf(siInfo);
    dwFlags := STARTF_USESHOWWINDOW;
    wShowWindow := wWindowState;
    end;
    Result := CreateProcess(NIL, pChar(sExecutableFile), NIL, NIL, FALSE, CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, NIL, pchar(ExtractFilePath(sExecutableFile)),siInfo, piInfo);
    if Result then
    WaitForSingleObject(piInfo.hprocess,INFINITE);
end;

And then called it with this commandline, which works when pasted in 'cmd' but not with this code:

然后用这个命令行调用它,当粘贴到“cmd”中时它可以工作,但不能使用以下代码:

ExecuteAndWait('D:\EMF2PDF\emf2pdf.exe -append 0 -margin 36x36x36x36 -width 595 -height 420 "D:\EMF2PDF\EMF\example.emf" "D:\EMF2PDF\PDF\example.pdf"');

I'd be happy if you could supply (link to) a working example call (in a service) of the console app commandline above.

如果您可以提供(链接到)上面控制台应用程序命令行的工作示例调用(在服务中),我会很高兴。

UPDATE: The command in question opens no window but types stats of the conversion in console. I use the software downloadable here: http://www.verydoc.com/emf-to-pdf.html

更新:有问题的命令没有打开窗口,但在控制台中键入转换的统计信息。我使用可在此处下载的软件:http: //www.verydoc.com/emf-to-pdf.html

Also, I was not informed until now that the server in question is a virtual server, if that makes a difference.

此外,直到现在我才被告知有问题的服务器是虚拟服务器,如果这有区别的话。

Checked just now, and when I try out my service I'm logged in as a remote session user. Wouldn't the service be able to at least create a process that calls emf2pdf when Windows is running with a logged in user?

刚刚检查,当我尝试我的服务时,我以远程会话用户的身份登录。当 Windows 与登录用户一起运行时,该服务是否至少不能创建一个调用 emf2pdf 的进程?

If you can think of alternative solutions to using the Verydoc software, any at all, under these conditions or other, on this server (such as a batch user) I'd love to try them!

如果您能想到在此服务器(例如批处理用户)上在这些条件或其他条件下使用 Verydoc 软件的替代解决方案,我很乐意尝试它们!

回答by Ritsaert Hornstra

A service runs inside another session and hence another win station so you cannot use ShellExecute beacuse the service win station has no shell at all; there might not be a logged in user etc etc. The only but is an interactive service but those are not supported anymore on the newer Windows version (from Vista and above if I recall correctly).

服务在另一个会话中运行,因此在另一个 win 站中运行,因此您不能使用 ShellExecute,因为服务 win 站根本没有外壳;可能没有登录用户等。唯一的但是是交互式服务,但较新的 Windows 版本不再支持这些服务(如果我没记错的话,来自 Vista 及更高版本)。

As David mentioned in the remarks below: it should be possible to start a process using:

正如大卫在下面的评论中提到的:应该可以使用以下方法启动一个过程:

ShellExecute(0, 'open', 'sleep.exe', '60', '', SW_HIDE);

I tested it with a different program and it failed so it might depend on the application you wish to start so apparently this answer is incorrect. It still gives some insight information so I will leave it here unless someone asks me otherwise.

我用不同的程序对其进行了测试,但它失败了,因此它可能取决于您希望启动的应用程序,因此显然这个答案是不正确的。它仍然提供了一些洞察信息,所以除非有人问我,否则我会把它留在这里。

回答by David Heffernan

Your update to the question reports that the call to CreateProcessworks when run from a standard app but fails when run from a service. The issue is surely related to session 0 isolation of services. With this information, I can think of the following explanations:

您对问题的更新报告说,CreateProcess从标准应用程序运行时调用可以工作,但从服务运行时失败。该问题肯定与服务的会话 0 隔离有关。有了这些信息,我可以想到以下解释:

  1. In the context of the service, the D:\EMF2PDF\...path is not available. Check that you can create and open a text file here to see whether or not this diagnosis is true.
  2. Session 0 isolation is just incompatible with the emf2pdfprogram. If that is so then you will need to find another program to do the conversion. That might be hard to do because it a program that processes EMF is liable to use GDI commands and they are very likely to fail in the context of a service.
  1. 在服务的上下文中,D:\EMF2PDF\...路径不可用。检查您是否可以在此处创建和打开文本文件以查看此诊断是否正确。
  2. Session 0 隔离只是与emf2pdf程序不兼容。如果是这样,那么您将需要找到另一个程序来进行转换。这可能很难做到,因为处理 EMF 的程序很容易使用 GDI 命令,并且它们很可能在服务的上下文中失败。

By far the easiest solution will be to run this process as a standard application. I can see that this might not be a palatable prospect for what appears to be a server service.

到目前为止,最简单的解决方案是将此过程作为标准应用程序运行。我可以看到,对于似乎是服务器服务的东西来说,这可能不是一个可口的前景。

回答by GHN

We had the exact same problem here. We were also generating a PDF with a command-line tool.

我们在这里遇到了完全相同的问题。我们还使用命令行工具生成了 PDF。

If you look at the properties of your service in the services dialog, you can see a checkbox on the 'logon' tabpage. The checkbox is titled 'Allow service to interact with desktop'. Set this to checked.

如果您在服务对话框中查看服务的属性,您可以在“登录”标签页上看到一个复选框。复选框标题为“允许服务与桌面交互”。将此设置为选中。

One of the answers here indicates that this is no longer possible on newer Windows versions, but it works just fine on Windows 7 and Windows 2008 server.

这里的答案之一表明这在较新的 Windows 版本上不再可能,但它在 Windows 7 和 Windows 2008 服务器上运行良好。

Edit: The setting in the properties of the service may have changed it's meaning, I don't know about that. But it solved our problem. Our commandline tool for generating PDFs run just fine after checking this checkbox.

编辑:服务属性中的设置可能已经改变了它的含义,我不知道。但它解决了我们的问题。选中此复选框后,我们用于生成 PDF 的命令行工具运行良好。