指定的服务在delphi应用程序上标记为删除

指定的服务在delphi应用程序上标记为删除,delphi,service,delphi-xe2,uninstallation,Delphi,Service,Delphi Xe2,Uninstallation,我编写了一个Delphi应用程序(基本上是一个用于管理服务的GUI,它具有以下特性:允许用户设置服务使用的一些参数,并启动/停止/取消安装/安装新版本)。 所以,在所有的功能中,有一个“行为不正常”:在某一点上,应用程序试图卸载并安装新版本的服务 使用ShellExecuteI运行以下命令: C:\myPath\myService.exe /Uninstall C:\myPath\myService.exe /Install // this is tipically done to insta

我编写了一个Delphi应用程序(基本上是一个用于管理服务的GUI,它具有以下特性:允许用户设置服务使用的一些参数,并启动/停止/取消安装/安装新版本)。 所以,在所有的功能中,有一个“行为不正常”:在某一点上,应用程序试图卸载并安装新版本的服务

使用
ShellExecute
I运行以下命令:

C:\myPath\myService.exe /Uninstall
C:\myPath\myService.exe /Install  // this is tipically done to install a newer version of it
如果服务已经在运行,它将被成功卸载(我会收到“Successfully uninstalled”消息),但如果我打开services.msc,我会看到myService仍然在服务列表中,但从其弹出菜单中禁用了Start和Stop(但我希望它根本不在列表中)

此时,如果我尝试安装该服务,会出现以下错误: “指定的服务已标记为删除”

请注意,如果在命令提示符下运行卸载和安装命令,卸载即可,服务不在services.msc列表中。注意:在这种情况下,我的意思是根本不使用Delphi(或编译的exe)

我尝试了很多技巧,包括在卸载后放置
Sleep(10000)
,但都不起作用。我还尝试了保持services.msc关闭(据我所知,保持它打开可能会有问题)

我通过以下步骤找到了一个成功的窍门:

1) 我在从Delphi调用Uninstall之后放置了一个断点

2) 我转到services.msc:服务仍然在列表中,即使在“刷新”之后,它仍然在列表中

3) 我中断(从IDE:CTRL+F2)应用程序的执行

4) 我在services.msc中再次点击“刷新”按钮:myservice将按原样从列表中删除

因此我怀疑Delphi XE2(在IDE中调试或运行exe)某种程度上“锁定了服务”,不允许完全卸载它。

注意:该服务是使用另一个delphi项目构建的

您能帮助我理解为什么由
ShellExecute
进行的服务卸载会出现此错误吗

非常感谢

重要提示:
我忘了提到我使用IDE和cmd.exe作为管理员。

我认为您的命令提示符具有提升的权限,因此可以实际停止服务。Delphi可能不是,或者至少您的项目不是,因此允许它卸载服务(这只不过是从注册表中删除一些值),但它实际上无法停止服务

该服务随后被“标记为删除”,因为它已被卸载,但仍在运行。如果重新启动电脑,服务将不会再次启动,您的工具可以安装新版本

如果我猜对了,那么解决方案就是以管理员的身份运行你的程序——本质上是一个安装程序,因此它也有权立即停止并删除服务


您可以尝试的另一件事是,首先调用
net stop
停止服务,但我怀疑这是否解决了问题。

我也有过类似的经历。在我的代码中,我使用了一个变量来保持与服务控制管理器的开放连接。现在,我将所有句柄声明为局部变量,并动态安装和卸载服务

您可以通过调用卸载服务。备注部分内容如下:

DeleteService函数将服务标记为从服务控制管理器数据库中删除。在调用CloseServiceHandle函数关闭服务的所有打开句柄且服务未运行之前,不会删除数据库项。正在运行的服务通过调用带有服务控制停止控制代码的ControlService函数来停止。如果无法停止服务,则系统重新启动时将删除数据库条目

因此,它必须停止,并且您应该关闭所有句柄。下面的代码应该可以做到这一点:

function  UninstallService(aServiceName: String; aTimeOut: Cardinal): Boolean;
var
    ComputerName: array[0..MAX_COMPUTERNAME_LENGTH + 1] of Char;
    ComputerNameLength, StartTickCount: Cardinal;
    SCM: SC_HANDLE;
    ServiceHandle: SC_HANDLE;
    ServiceStatus: TServiceStatus;

begin
    Result:= False;

    ComputerNameLength:= MAX_COMPUTERNAME_LENGTH + 1;
    if (Windows.GetComputerName(ComputerName, ComputerNameLength)) then
    begin
        SCM:= OpenSCManager(ComputerName, nil, SC_MANAGER_ALL_ACCESS);
        if (SCM <> 0) then
        begin
            try
                ServiceHandle:= OpenService(SCM, PChar(aServiceName), SERVICE_ALL_ACCESS);
                if (ServiceHandle <> 0) then
                begin

                    // make sure service is stopped
                    QueryServiceStatus(ServiceHandle, ServiceStatus);
                    if (not (ServiceStatus.dwCurrentState in [0, SERVICE_STOPPED])) then
                    begin
                        // Stop service
                        ControlService(ServiceHandle, SERVICE_CONTROL_STOP, ServiceStatus);
                    end;

                    // wait for service to be stopped
                    StartTickCount:= GetTickCount;
                    QueryServiceStatus(ServiceHandle, ServiceStatus);
                    if (ServiceStatus.dwCurrentState <> SERVICE_STOPPED) then
                    begin
                        repeat
                            Sleep(1000);
                            QueryServiceStatus(ServiceHandle, ServiceStatus);
                        until (ServiceStatus.dwCurrentState = SERVICE_STOPPED) or ((GetTickCount - StartTickCount) > aTimeout);
                    end;

                    Result:= DeleteService(ServiceHandle);
                    CloseServiceHandle(ServiceHandle);
                end;
            finally
                CloseServiceHandle(SCM);
            end;
        end;
    end;
end;
函数卸载服务(aServiceName:String;aTimeOut:Cardinal):布尔;
变量
ComputerName:Char的数组[0..MAX\u ComputerName\u LENGTH+1];
ComputerNameLength,StartTickCount:Cardinal;
SCM:SC_手柄;
服务手柄:SC_手柄;
服务状态:TServiceStatus;
开始
结果:=假;
计算机名称长度:=最大计算机名称长度+1;
如果是(Windows.GetComputerName(ComputerName,ComputerNameLength)),则
开始
SCM:=OpenSCManager(ComputerName,nil,SC\u MANAGER\u ALL\u ACCESS);
如果(SCM 0),则
开始
尝试
ServiceHandle:=OpenService(SCM、PChar(aServiceName)、SERVICE\u ALL\u ACCESS);
如果是(ServiceHandle 0),则
开始
//确保服务已停止
QueryServiceStatus(ServiceHandle,ServiceStatus);
如果(不是(ServiceStatus.dwCurrentState位于[0,服务已停止]),则
开始
//停止服务
控制服务(服务手柄、服务控制停止、服务状态);
结束;
//等待服务停止
StartTickCount:=GetTickCount;
QueryServiceStatus(ServiceHandle,ServiceStatus);
如果(ServiceStatus.dwCurrentState服务_已停止),则
开始
重复
睡眠(1000);
QueryServiceStatus(ServiceHandle,ServiceStatus);
直到(ServiceStatus.dwCurrentState=SERVICE_STOPPED)或((GetTickCount-StartTickCount)>aTimeout);
结束;
结果:=删除服务(ServiceHandle);
CloseServiceHandle(ServiceHandle);
结束;
最后
关闭服务手柄(SCM);
结束;
结束;