加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

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

发布时间:2020-12-15 09:20:44 所属栏目:大数据 来源:网络整理
导读:我编写了一个Delphi应用程序(基本上是一个用于管理服务的GUI,它具有以下功能:允许用户设置服务使用的一些参数以及启动/停止/取消挂起/安装新版本). 因此,在所有功能中,有一个“行为不正常”:在某个时刻,应用程序尝试卸载并安装新版本的服务. 使用ShellExec
我编写了一个Delphi应用程序(基本上是一个用于管理服务的GUI,它具有以下功能:允许用户设置服务使用的一些参数以及启动/停止/取消挂起/安装新版本).
因此,在所有功能中,有一个“行为不正常”:在某个时刻,应用程序尝试卸载并安装新版本的服务.

使用ShellExecute,我运行以下命令:

C:myPathmyService.exe /Uninstall
C:myPathmyService.exe /Install  // this is tipically done to install a newer version of it

如果服务已经运行,它将成功卸载(我得到“成功卸载”消息),但是如果我打开services.msc,我看到myService仍然在服务列表中,但是从其弹出菜单中禁用了“启动”和“停止”(同时我想它根本没有列出.

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

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

我尝试了许多技巧,包括卸载后放入睡眠(10000),但它不起作用我也尝试通过保持services.msc关闭(因为我读到它可能是一个问题,让它打开).

我使用以下步骤找到了一个成功的技巧:

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

2)我去了services.msc:服务仍然在列表中,即使在“刷新”之后它仍然是列表中的stil

3)我打破(从IDE:CTRL F2)应用程序的优先级

4)我再次在services.msc中单击“刷新”按钮:myservice从列表中删除,因为它应该是

所以我怀疑Delphi XE2(无论是在IDE中调试还是运行exe)都以某种方式“锁定服务”而不允许它完全卸载.

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

你能帮我理解为什么ShellExecute进行的服务卸载确实会出现这个错误吗?

非常感谢.

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

解决方法

我有类似的经历.在我的代码中,我发现我使用了一个变量来保持与服务控制管理器的开放连接.如今,我将所有句柄声明为本地变量和服务即时安装和卸载.

您可以通过调用DeleteService来卸载服务.在备注部分中,它显示为:

The DeleteService function marks a service for deletion from the service control manager database. The database entry is not removed until all open handles to the service have been closed by calls to the CloseServiceHandle function,and the service is not running. A running service is stopped by a call to the ControlService function with the SERVICE_CONTROL_STOP control code. If the service cannot be stopped,the database entry is removed when the system is restarted.

因此,它必须停止,你应该关闭所有句柄.下面的代码应该可以解决问题:

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;

我会在几个子函数(即QueryServiceStatus,StopService和UninstallService)中删除上面的代码,但是为了测试这段代码是否适合你,我认为最好用一个简单的解决方案来编写它.最后,请注意,进程需要足够的权限才能成功执行此代码.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读