如何停止由 Win32::Daemon 启动的 Win32 服务?

2023-12-11

我可以使用以下脚本在 Windows 10(Strawberry Perl 版本 5.30.1)上成功启动 Win32 服务:

package Win32::XYZService;
use feature qw(say);
use strict;
use warnings;
use File::Spec;
use Win32;
use Win32::Daemon;

{
    die "Bad arguments" if @ARGV != 1;
    my $action = shift @ARGV;
    my $xyz = Win32::XYZService->new();
    $xyz->action( $action );

}

sub new {
    my ( $class, %args ) = @_;
    $args{name} = 'xyz_service2';
    my ($bin, $scriptname) = Win32::GetFullPathName( $0 );
    $args{bin} = $bin;
    $args{scriptname} = $scriptname;
    $args{log_fn} = File::Spec->catfile( $bin, 'log.txt' );
    $args{time_interval} = 2000;  # callback timer interval in milliseconds
    my $self = bless \%args, $class;
    return $self;
}

sub action {
    my ($self, $action) = @_;

    if ($self->can($action)) {
        return $self->$action();
    }
    else {
        $self->log("Unknown command: $action");
        $self->log("Valid commands are: create, start, stop, delete");
        return undef;
    }
}

sub start {
    my ($self) = @_;
    $self->log("starting service..");
    system("net", "start", $self->{name});
}

sub stop {
    my ($self) = @_;

    $self->log("trying to stop service..");
    system("net", "stop", $self->{name});
}

sub _scm_start {
    my ($self) = @_;

    Win32::Daemon::RegisterCallbacks( {
        start       =>  \&_callback_start,
        timer       =>  \&_callback_timer,
        stop        =>  \&_callback_stop,
        pause       =>  \&_callback_pause,
        continue    =>  \&_callback_continue,
    } );
    Win32::Daemon::StartService( $self, $self->{time_interval} );
}

sub _callback_continue {
    my ( $event, $self) = @_;

    $self->log("callback continue");
    Win32::Daemon::State( SERVICE_RUNNING );
}

sub _callback_pause {
    my ( $event, $self) = @_;

    $self->log("callback pause");
    Win32::Daemon::State( SERVICE_PAUSED );
}

sub _callback_stop {
    my ( $event, $self) = @_;

    $self->log("callback stop");
    Win32::Daemon::State( SERVICE_STOPPED );
    Win32::Daemon::StopService();
}

sub _callback_timer {
    my ( $event, $self) = @_;

    $self->log("callback timer");
}

sub _callback_start {
    my ( $event, $self) = @_;

    $self->log("callback start");
    Win32::Daemon::State( SERVICE_RUNNING );
}

sub log {
    my ($self, $msg) = @_;

    chomp $msg;
    open(my $fh, ">>", $self->{log_fn})
        or warn("Can't append to log \"$self->{log_fn}\": $!\n"), return;
    say $fh "[PID $$] [" . localtime . "] : $msg";
    say $msg if -t STDIN;
}

sub delete {
    my ($self) = @_;
    if (Win32::Daemon::DeleteService("", $self->{name})) {
        $self->log("Successfully removed service $self->{name}");
    }
    else {
        $self->log("Failed to remove service: " . Win32::FormatMessage( Win32::Daemon::GetLastError()));
    }
}

sub create {
    my ($self) = @_;
    my $service_path = $^X;
    my $service_params = File::Spec->catfile($self->{bin}, $self->{scriptname});
    $service_params .= ' _scm_start';  # Service control manager start
    my %service_info = (
        name            => $self->{name},
        display         => 'xyz_display',
        path            => $service_path,
        description     => 'xyz_description',
        parameters      => $service_params,
        service_type    => SERVICE_WIN32_OWN_PROCESS,
        start_type      => SERVICE_AUTO_START
    );

    if (Win32::Daemon::CreateService( \%service_info)) {
        $self->log("Successfully added service $service_info{name}");
    }
    else {
        $self->log("Failed to add service: " . Win32::FormatMessage( Win32::Daemon::GetLastError()));
    }
}

如果我以管理员身份从命令提示符运行此脚本:

>perl xyz_service.pl create
Successfully added service xyz_service2

>perl xyz_service.pl start
starting service..
The xyz_display service is starting.
The xyz_display service was started successfully.

>type log.txt
[PID 8844] [Wed Jul  1 11:33:05 2020] : Successfully added service xyz_service2
[PID 10552] [Wed Jul  1 11:33:42 2020] : starting service..
[PID 12076] [Wed Jul  1 11:33:42 2020] : callback start
[PID 12076] [Wed Jul  1 11:33:44 2020] : callback timer
[PID 12076] [Wed Jul  1 11:33:46 2020] : callback timer
[PID 12076] [Wed Jul  1 11:33:48 2020] : callback timer
[PID 12076] [Wed Jul  1 11:33:50 2020] : callback timer
[PID 12076] [Wed Jul  1 11:33:52 2020] : callback timer
[PID 12076] [Wed Jul  1 11:33:54 2020] : callback timer

>perl xyz_service.pl stop
stopping service..
The requested pause, continue, or stop is not valid for this service.
More help is available by typing NET HELPMSG 2191.

我怎样才能停止该服务?


该模块应该使用SetServiceStatus向 Windows 发出信号,表明它可以处理关闭事件。在旧版本的 Windows 中也是如此。但是,它在 Windows 10(及更高版本)和 Windows Server 2016(及更高版本)中无法做到这一点。

此失败是由于缺少默认子句造成的switch陈述在模块的DllMain in Demon.xs。由于这个问题,gdwControlsAccepted最终得到一个不正确的值。

修正后的switch:

            switch( gsOSVerInfo.dwMajorVersion )
            {
                default:
                    // We have Windows Vista or newer
                    //  The following constants only work on Vista and higher:
                    //      SERVICE_ACCEPT_PRESHUTDOWN
                    //
#ifdef SERVICE_CONTROL_PRESHUTDOWN
                    gdwControlsAccepted |= SERVICE_ACCEPT_PRESHUTDOWN;
#endif  // SERVICE_CONTROL_PRESHUTDOWN

                case 5:
                    // We have Windows 2000 or XP
                    //  The following constants only work on Win2k and higher:
                    //      SERVICE_ACCEPT_PARAMCHANGE
                    //      SERVICE_ACCEPT_NETBINDCHANGE
                    //
                    gdwControlsAccepted |= SERVICE_ACCEPT_PARAMCHANGE  
                                        |  SERVICE_ACCEPT_NETBINDCHANGE;

                case 4:
                case 3:
                case 2:
                case 1:
                case 0:
                    // NT 4.0
                    gdwControlsAccepted |= SERVICE_ACCEPT_STOP 
                                        |  SERVICE_ACCEPT_PAUSE_CONTINUE
                                        |  SERVICE_ACCEPT_SHUTDOWN;
            }

我没有测试过这个。请测试并提交错误报告。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何停止由 Win32::Daemon 启动的 Win32 服务? 的相关文章

  • 在Windows Server 2003下如何在本地系统帐户下运行jvisualvm.exe?

    我在带有 Java 1 6 u 20 的 Windows Server 2003 下将 GlassFish 3 0 1 作为 Windows 服务运行 总体上我很满意 我希望能够在这个 JVM 上使用 VisualVM 并使用无法在 Tom
  • 初始化 LPCTSTR /LPCWSTR [重复]

    这个问题在这里已经有答案了 我很难理解并使其正常工作 基本上归结为我无法成功初始化这种类型的变量 它需要有说的内容7 2E25DC9D 0 USB003 有人可以解释 展示这种类型的正确初始化和类似的值吗 我已查看此站点上的所有帮助 将项目
  • 如何编写 Perl 脚本来使用 curl 处理 URL?

    我有一个非常简单的任务 我有一个 crontab 每小时运行一个脚本 该脚本旨在简单地处理 URL 这就是我所拥有的 这不起作用 我收到语法错误 usr bin perl curl http domain com page html 我已经
  • 正则表达式从字符串中提取 IP 和端口

    我正在使用 Perl 尝试从字符串中提取 IP 地址和端口 我尝试使用的正则表达式是 s sip 字符串是 sip 255 255 255 255 8080 transport TCP sip 255 255 255 255 8080 显然
  • 如何在 perl 中合并两个数组,交替每个数组中的值

    假设我有 2 个如下所示的数组 a1 Vinay Raj harry b1 dude rock 合并后我想要这样的结果 Vinay dude Vinay rock Raj dude Raj rock harry dude harry roc
  • 向用户提示多个问题(是/否和文件名输入)

    我想问用户多个问题 我有两种类型的问题 是 否或文件名输入 我不知道如何将这一切放入一个好的if结构 我不确定是否也应该使用 else 语句 有人可以帮我们解决这个问题吗 这是我到目前为止所拥有的 print Do you want to
  • 检测桌面是否被锁定[重复]

    这个问题在这里已经有答案了 可能的重复 如何以编程方式确定我的工作站是否被锁定 https stackoverflow com questions 44980 how can i programmatically determine if
  • 安装 Windows 服务时的凭据

    我正在尝试使用 VisualStudio Net 部署项目安装 C Windows 服务项目 要运行部署项目 我右键单击并从上下文菜单中选择 安装 安装向导将运行并最终提示我出现 设置服务登录 对话框 要求输入用户名和密码 当我从命令行使用
  • 在 Windows 7 中使用 Windows 服务截取屏幕截图 [重复]

    这个问题在这里已经有答案了 我知道这是一个关于 Win 7 中的屏幕截图与 c 上的 winService 的老问题 我已经阅读了 Stack Overflow 上有关此内容的所有文章以及 CodeProject 上的很多文章 我了解服务的
  • 调整大小时在窗口中绘图留下未绘制的边框

    我遇到的问题看似微不足道 但我找不到解决的方法 这里是 我有一个窗口 里面有一些图形 为了简单起见 我们假设它是一个实心绿色矩形 填充了窗口的整个客户区域 我希望每次窗口改变大小时都重新绘制这个矩形并填充整个窗口 我最初做的就是这样的 我已
  • 如何将会话管理添加到简单的 Perl CGI 网页?

    我有一个简单的网页 到目前为止不需要任何登录 它是用 Perl CGI 编程的 我想知道添加会话支持以便获得登录信息的步骤 我不需要非常复杂的方法 因为网页非常简单 另外 我想要一些关于支持 Perl 会话所需的技术 库的建议 我在很多很多
  • 在 qx 运算符中将 perl 数组拆分为单独的参数

    我试图将一组参数传递给qx操作员 考虑 my files qw A txt B txt print qx ls files 这给出了错误 ls cannot access A txt B txt No such file or direct
  • 是否可以通过 C#.NET 编写 Win32 .dll 文件?

    是否可以通过 C NET 编写 Win32 dll 文件 如果是的话 我在哪里可以找到一些教程 如果不是 那么您对编写 Win32 DLL 有什么建议 Thanks 对的 这是可能的 事实上有一个工具可以做到这一点 它在 Rainmeter
  • 使用 -T 开关运行时 $ENV{ENV} 不安全

    当我尝试最后一个例子时perlfaq5 如何计算文件中的行数 http perldoc perl org perlfaq5 html How do I count the number of lines in a file 我收到一条错误消
  • ZLIB 解压缩

    我编写了一个小型应用程序 该应用程序应该解压缩以 gzip deflate 格式编码的数据 为了实现这一点 我使用 ZLIB 库 使用解压缩功能 问题是这个功能不起作用 换句话说 数据不是未压缩的 我在这里发布代码 int decompre
  • 如何使用 Win32 API 与 com 端口 (RS232) 通信

    我正在尝试使用 win32 API 与 com 端口对话 我找到了这个http www robbayer com files serial win pdf http www robbayer com files serial win pdf
  • 如何验证文件名称在 Windows 中是否有效?

    是否有一个 Windows API 函数可以将字符串值传递给该函数 该函数将返回一个指示文件名是否有效的值 我需要验证文件名是否有效 并且我正在寻找一种简单的方法来完成此操作 而无需重新发明轮子 我正在直接使用 C 但针对的是 Win32
  • OleLoadPicturePath 是否已以非向后兼容的方式更改?

    我最近遇到一个问题 我能够在一台 PC 上将图标添加到 VB6 表单 它运行良好 但他们无法在第二台 PC 上运行 编译它 结果发现图标文件是 32 位的 包括 Alpha 通道 这就是问题所在 但令我惊讶的是 这是一个依赖于系统的功能 在
  • Perl 和 Selenium::远程::驱动程序

    再次编辑 我在弗吉尼亚州北部某处的 AWS 上有一台服务器 这是我的监控服务器 我从另一个状态 ssh 进入这个 Ubuntu 服务器来进行系统管理 我想在这台服务器上进行 Web 自动化测试 它将测试互联网上的 Web 应用程序 点击 U
  • 如果加载 dll 找不到依赖项,有什么方法可以捕获错误吗?

    我正在编写一个 Windows 32 位程序 可以使用多个可能的 dll 之一 所以它尝试依次加载每个 dll 使用SysUtils SafeLoadLibrary如果加载成功 它就会使用该 dll 不幸的是 其中一些 dll 静态链接到其

随机推荐

  • 如何对发送到服务器的http请求进行加密?

    是否可以隐藏 或加密 HTTP 请求的内容 以便授权人员之外的其他人无法查看它 例如 如果一个用户只是在登录页面中提交数据 即使使用 http post 那么也可以在 firebug 类工具中看到请求标头中包含的用户名和密码等内容 我知道客
  • 条件 DB2 SQL 查询

    假设我有一个名为 Company 的表 其键为 CompanyID 还有另一个名为 CompanyAddress 的相关表 它具有 CompanyID 外键 因此可以轻松建立连接 此 CompanyAddress 表可以具有给定公司的多个地
  • 从 cs 文件加载脚本并访问主机方法、属性等?

    我只是在和罗斯林玩 但不确定如何执行以下操作 为了保持简单 假设我有一个主机程序 它有一个像这样的方法 public void DisplayMessage string message MessageBox Show message 然后
  • 确定数组是否包含 n...n+m 的算法?

    我在 Reddit 上看到这个问题 但没有给出积极的解决方案 我认为在这里问这个问题是一个完美的问题 这是关于面试问题的帖子 编写一个方法 该方法接受大小为 m 的 int 数组 如果该数组包含数字 n n m 1 该范围内的所有数字以及仅
  • 实现自定义配置节处理程序

    从各种来源 包括 stackOverlflow 收集的信息 但是当我开始使用它时 我收到以下错误消息 配置属性 deviceconfig 可能不是从 ConfigurationSection 派生的 我现在已经在这个问题上挣扎了一整天 而且
  • 在java程序中执行bash命令

    自从我寻找以来已经有一段时间了 但我没有找到解决方案 我正在尝试在 Linux 上的 jar 文件中执行 bash 命令 为此 我尝试了很多方法 包括 Process p new ProcessBuilder java jar M1 MIA
  • 当变量值丢失时,Django 模板中的 Javascript 语法错误

    我有一个带有 AJAX 菜单的 Django 模板 单击不同的菜单项会重新加载页面的一部分 每次菜单单击都会通过 AJAX 调用 Django 视图函数并返回一些要在页面上显示的数据 我只加载主页中所有菜单项所需的所有 JS 据我所知 AJ
  • SerialPort.Read(....) 不尊重 ReadTimeOut

    与支付终端通信的一些旧代码中存在错误 在新的付款开始之前 代码会尝试清除串行端口的内部读取缓冲区 我将代码削减到最低限度 它使用 NET SerialPort 类型 设置读取超时为 50ms 然后它读取 512 字节并继续这样做 直到不再读
  • 是否可以在 C# 中返回对变量的引用? [复制]

    这个问题在这里已经有答案了 例如 我可以返回对双精度值的引用吗 这就是我想做的 ref double GetElement Calculate x y z return ref doubleArray x y z 像这样使用它 void f
  • socket.io 的 C 客户端

    我正在尝试使用socket io 建立从C 程序到节点服务器的连接 我能想到的唯一方法是从 C 程序向节点服务器发出 http 请求 所以我已经对此部分进行了一些介绍 现在我需要从C程序接收来自节点服务器的一些信息 是否有任何 c 客户端库
  • Python 凯撒密码解码器

    在我的课程中 我的任务是创建一个凯撒密码解码器 该解码器接受输入字符串并使用字母频率找到最佳可能的字符串 如果不确定这有多大意义 但让我们提出问题 编写一个执行以下操作的程序 首先 它应该读取一行输入 这是编码消息 由大写字母和空格组成 您
  • 使用 SALib 工具箱对测量数据进行 Python 敏感性分析

    我想了解 如何使用 SALib python 工具箱进行 Sobol 敏感性分析 研究参数和交叉参数影响 从最初的例子我应该这样做 from SALib sample import saltelli from SALib analyze i
  • 如何在 R 中将 `foreach` 和 `%dopar%` 与 `R6` 类一起使用?

    我在尝试使用时遇到了问题 dopar and foreach 与一个R6班级 四处搜索 我只能找到两个与此相关的资源 一个未答复所以问题和一个开放的GitHub问题 on the R6存储库 在一条评论 即 GitHub 问题 中 建议通过
  • Android - 一个选项卡中的多个片段

    我在网上搜索了很多有关在一个操作栏选项卡中包含多个片段的可能性的信息 这个问题最接近我的需求 但代码不起作用 是否有另一种可能性可以在一个选项卡中包含多个片段 这是StartActivity public class StartActivi
  • IIS 7.0 错误 HTTP 错误 500.19 - 内部服务器错误(错误代码 0x80070003)

    我的 Windows 2008 Server 上运行着 IIS7 它非常适合我之前托管的网站和文件夹 现在我尝试托管一个包含两个子文件夹的文件夹 子文件夹包含一些 图片 我已正确设置站点文件夹的 IIS IUSRS 权限 当我尝试浏览时 我
  • 常量值无法转换为 int

    我不明白为什么第 5 行无法编译 而第 4 行却可以 static void Main string args byte b 0 int i int 0xffffff00 b ok int j int 0xffffff00 byte 0 e
  • MVC 中的模型应该如何构建? [关闭]

    Closed 这个问题是基于意见的 目前不接受答案 我刚刚掌握 MVC 框架 经常想知道模型中应该包含多少代码 我倾向于拥有一个具有如下方法的数据访问类 public function CheckUsername connection us
  • 在上传之前调整从图库或相机拍摄的图像的大小

    我的网站中有一个表单 允许用户上传照片 我的 Android 应用程序使用 WebView 来允许用户访问该网站 单击上传按钮后 应用程序允许用户在图库中现有的图像之间进行选择 或者拍摄新照片并上传该图像 我为此使用的代码是 showAtt
  • Cosmos DB - 图形 API - 导出 graphSON 并尝试使用迁移工具导入它

    我在新图中插入了一些顶点和边 我已将生成的 grapSON 保存在 json 文件中 然后我尝试使用迁移工具将该 json 文件导入到新图表中 它只起到了部分作用 我有一个带有顶点的新图 但它们没有这样的属性或边 id c39f435b 3
  • 如何停止由 Win32::Daemon 启动的 Win32 服务?

    我可以使用以下脚本在 Windows 10 Strawberry Perl 版本 5 30 1 上成功启动 Win32 服务 package Win32 XYZService use feature qw say use strict us