window服务相关问题探索 go语言服务开发探索调试

由于业务需要 开发一个服务 保证窗口不被关闭,但是又要想看到是否执行成功.

获取服务错误日志

复制代码
powershell "Get-EventLog -LogName System -Source 'Service Control Manager' -newest 5"
 powershell "Get-EventLog -LogName Application -Source 'DingTalkEventService' -newest 5

服务经常删不掉解决办法sc delete DingTalkEventService

老出现已标记未删除这种情况无法创建和删除,

复制代码
PS C:\Users\Administrator> Get-Service -Name "DingTalkEventService*" | Stop-Service -Force
 Get-Service -Name "DingTalkEventService*" | Remove-Service

PS C:\Users\Administrator>   taskkill /f /im ding.exe
错误: 没有找到进程 "ding.exe"。
PS C:\Users\Administrator>  taskkill /f /im mmc.exe
成功: 已终止进程 "mmc.exe",其 PID 为 1784。
PS C:\Users\Administrator> Get-Service -Name "DingTalkEventService*" | Stop-Service -Force
PS C:\Users\Administrator>

然后 进入服务里面发现服务不见了

也就是说杀掉mmc进程即可

image.png

最后服务bat如下

复制代码
@echo off
setlocal enabledelayedexpansion

echo =============================================
echo 钉钉事件监听服务 - 安装程序
echo =============================================
echo.

set "SERVICE_NAME=DingTalkEventService"
set "SERVICE_DISPLAY_NAME=钉钉事件监听服务"
set "EXE_PATH=%~dp0ding.exe"

echo [信息] 开始安装服务...
echo [信息] 服务名称: %SERVICE_NAME%
echo [信息] 可执行文件: %EXE_PATH%
echo.

:: 检查管理员权限
echo [检查] 验证管理员权限...
net session >nul 2>&1
if not %errorLevel% == 0 (
    echo [错误] 需要管理员权限!
    echo [解决] 请右键点击脚本,选择"以管理员身份运行"
    pause
    exit /b 1
)
echo [成功] 管理员权限验证通过
echo.

:: 检查可执行文件
echo [检查] 验证可执行文件...
if not exist "%EXE_PATH%" (
    echo [错误] 找不到可执行文件: %EXE_PATH%
    echo [解决] 请先编译: go build -o ding.exe .
    pause
    exit /b 1
)
echo [成功] 找到可执行文件
echo.

:: 停止并删除现有服务(如果存在)
echo [检查] 检查现有服务...
sc query "%SERVICE_NAME%" >nul 2>&1
if %errorLevel% == 0 (
    echo [发现] 服务已存在,正在删除...
    sc stop "%SERVICE_NAME%" >nul 2>&1
    timeout /t 3 /nobreak >nul
    sc delete "%SERVICE_NAME%" >nul 2>&1
    if !errorLevel! == 0 (
        echo [成功] 现有服务已删除
    ) else (
        echo [错误] 删除现有服务失败,直接终止MMC
        taskkill /f /im mmc.exe
        pause
        exit /b 1
    )
    timeout /t 2 /nobreak >nul
) else (
    echo [信息] 未发现现有服务
)

:: 创建新服务
echo [操作] 创建新服务...
sc create "%SERVICE_NAME%" binPath= "\"%EXE_PATH%\" -service" DisplayName= "%SERVICE_DISPLAY_NAME%" start= auto >nul 2>&1

if %errorLevel% == 0 (
    echo [成功] 服务创建成功
    
    :: 设置服务描述
    sc description "%SERVICE_NAME%" "监听钉钉事件并处理业务逻辑的后台服务" >nul 2>&1
    
    :: 设置失败恢复选项
    sc failure "%SERVICE_NAME%" reset= 86400 actions= restart/5000/restart/5000/restart/5000 >nul 2>&1
    
) else (
    echo [错误] 服务创建失败,错误代码: %errorLevel%
    pause
    exit /b 1
)

:: 启动服务
echo [操作] 启动服务...
sc start "%SERVICE_NAME%" >nul 2>&1
set "START_RESULT=%errorLevel%"

:: 等待启动
timeout /t 3 /nobreak >nul

:: 检查结果
if %START_RESULT% == 0 (
    echo [成功] 服务启动成功!
) else if %START_RESULT% == 1053 (
    echo [注意] 服务安装成功,启动超时(这通常是正常的)
) else if %START_RESULT% == 1056 (
    echo [信息] 服务已在运行中
) else (
    echo [警告] 启动返回代码: %START_RESULT%
    echo [说明] 服务可能已安装,请检查状态
)

echo.
echo ============================================
echo 安装完成!
echo ============================================
echo.
echo 服务名称: %SERVICE_NAME%
echo 可执行文件: %EXE_PATH%
echo.
echo 常用命令:
echo   查看状态: sc query %SERVICE_NAME%
echo   停止服务: sc stop %SERVICE_NAME%
echo   启动服务: sc start %SERVICE_NAME%
echo   查看日志: 运行"查看状态.bat"
echo   卸载服务: 运行"卸载服务.bat"
echo.

pause


image.png

复制代码
@echo off
setlocal enabledelayedexpansion

echo =============================================
echo 钉钉事件监听服务 - 卸载程序  
echo =============================================
echo.

set "SERVICE_NAME=DingTalkEventService"
set "SERVICE_DISPLAY_NAME=钉钉事件监听服务"

echo [信息] 开始卸载服务...
echo [信息] 服务名称: %SERVICE_NAME%
echo [信息] 显示名称: %SERVICE_DISPLAY_NAME%
echo.

:: 检查管理员权限
echo [检查] 验证管理员权限...
net session >nul 2>&1
if not %errorLevel% == 0 (
    echo [错误] 需要管理员权限!
    echo [解决] 请右键点击脚本文件,选择"以管理员身份运行"
    pause
    exit /b 1
)
echo [成功] 管理员权限验证通过
echo.

:: 检查服务是否存在
echo [检查] 检查服务是否存在...
sc query "%SERVICE_NAME%" >nul 2>&1
if %errorLevel% == 0 (
    echo [发现] 服务存在,开始卸载过程...
    
    :: 显示当前状态
    echo [信息] 当前服务状态:
    sc query "%SERVICE_NAME%"
    echo.
    
    :: 尝试停止服务
    echo [操作] 正在停止服务...
    sc stop "%SERVICE_NAME%" >nul 2>&1
    if %errorLevel% == 0 (
        echo [成功] 停止命令已发送
        echo [等待] 等待服务完全停止...
        timeout /t 5 /nobreak >nul
    ) else if %errorLevel% == 1062 (
        echo [信息] 服务未启动
    ) else (
        echo [警告] 停止服务失败,错误代码: %errorLevel%
        echo [继续] 将尝试直接删除服务
    )
    
    :: 删除服务
    echo [操作] 删除服务...
    sc delete "%SERVICE_NAME%" >nul 2>&1
    if %errorLevel% == 0 (
        echo [成功] 服务删除成功
        
        :: 等待服务完全删除
        echo [等待] 等待服务完全从系统中移除...
        timeout /t 3 /nobreak >nul
        
        :: 验证删除结果
        sc query "%SERVICE_NAME%" >nul 2>&1
        if %errorLevel% == 1060 (
            echo [确认] 服务已从系统中完全移除
        ) else (
            echo [警告] 服务可能仍在系统中,请重启后检查
        )
        
    ) else if %errorLevel% == 1060 (
        echo [信息] 服务已经不存在
        
    ) else if %errorLevel% == 1072 (
        echo [错误] 服务被标记为删除,请重启系统完成删除过程
        
    ) else if %errorLevel% == 5 (
        echo [错误] 访问被拒绝,请确保以管理员身份运行
        pause
        exit /b 1
        
    ) else (
        echo [错误] 删除服务失败,错误代码: %errorLevel%
        echo [原因] 可能的原因:
        echo        1. 服务仍在运行中
        echo        2. 权限不足
        echo        3. 系统资源被锁定
        echo        4. 服务依赖关系问题
        echo.
        pause
        exit /b 1
    )
    
) else if %errorLevel% == 1060 (
    echo [信息] 服务不存在,无需卸载
    echo [说明] 服务"%SERVICE_NAME%"未在系统中找到
    echo.
    
) else (
    echo [错误] 查询服务状态失败,错误代码: %errorLevel%
    echo [原因] 可能的原因:
    echo        1. 权限不足
    echo        2. 系统服务管理器异常
    echo        3. 服务名称错误
    echo.
    pause
    exit /b 1
)

:: 清理相关文件
echo [清理] 检查是否需要清理相关文件...
if exist "service.log" (
    echo [发现] 找到服务日志文件: service.log
    set /p cleanup="是否删除日志文件? (Y/N): "
    if /i "%cleanup%"=="Y" (
        del "service.log" >nul 2>&1
        if %errorLevel% == 0 (
            echo [成功] 日志文件已删除
        ) else (
            echo [警告] 删除日志文件失败
        )
    ) else (
        echo [保留] 日志文件已保留
    )
) else (
    echo [信息] 未发现日志文件
)

echo.
echo ============================================
echo [成功] 服务卸载完成!
echo ============================================
echo.
echo ===== 卸载摘要 =====
echo 服务名称: %SERVICE_NAME%
echo 显示名称: %SERVICE_DISPLAY_NAME%
echo 卸载状态: 成功
echo.
echo ===== 验证命令 =====
echo 确认删除: sc query %SERVICE_NAME%
echo 查看服务: services.msc
echo.
echo [提示] 如需重新安装,请运行"安装服务.bat"

echo.
pause

上面的那玩意根本不行,后面换了一套服务实现方式也就是下文提到的这个,

复制代码
package main
 
import (
    "log"
    "os"
    "syscall"
    "time"
    "unsafe"
 
    "github.com/kardianos/service"
)
 
var (
    kernel32DLL       = syscall.NewLazyDLL("kernel32.dll")
    outputDebugString = kernel32DLL.NewProc("OutputDebugStringW")
)
 
func OutputDebugString(message string) {
    strPtr, _ := syscall.UTF16PtrFromString(message)
    outputDebugString.Call(uintptr(unsafe.Pointer(strPtr)))
}
 
// MyService 实现了 service.Service 接口
type MyService struct{}
 
func (m *MyService) Start(s service.Service) error {
    go m.run()
    return nil
}
 
func (m *MyService) run() {
    OutputDebugString("Service start...")
    // 在这里编写你的服务逻辑
    for {
        OutputDebugString("Service is running...")
        time.Sleep(1 * time.Second)
    }
}
 
func (m *MyService) Stop(s service.Service) error {
    // 停止服务的逻辑
    OutputDebugString("Service exit...")
    return nil
}
 
func main() {
 
    OutputDebugString("main starting...")
 
    // 服务的名称、显示名称和描述
    svcConfig := &service.Config{
        Name:        "MyGoService",
        DisplayName: "My Golang Service",
        Description: "This is a sample service by golang.",
    }
 
    prg := &MyService{}
    s, err := service.New(prg, svcConfig)
    if err != nil {
        log.Fatal(err)
    }
 
    // 如果服务已经安装,可以通过以下命令来启动、停止、重启或卸载服务:
    // service.exe install
    // service.exe start
    // service.exe stop
    // service.exe restart
    // service.exe uninstall
 
    // 通过以下代码来控制服务的启动和停止
    if len(os.Args) > 1 {
        err = service.Control(s, os.Args[1])
        if err != nil {
            log.Fatal(err)
        }
        return
    }
 
    err = s.Run()
    if err != nil {
        log.Fatal(err)
    }
}

服务调试过滤

下载地址DebugView - Sysinternals | Microsoft Learn

image.png

go语言实现服务使用Golang编写Windows服务 - 黑月教主 - 博客园

相关推荐
sakoba1 分钟前
Docker学习其二(容器卷,Docker网络,Compose)
运维·网络·学习·docker·容器·基础
apocelipes12 分钟前
atomic不是免费午餐
java·性能优化·golang·并发
Johny_Zhao15 分钟前
阿里云平台健康检查巡检清单-运维篇
linux·网络安全·阿里云·信息安全·云计算·shell·系统运维
WSSWWWSSW22 分钟前
Python编程基础与实践:Python循环结构基础
开发语言·python
A了LONE23 分钟前
cv弹窗,退款确认弹窗
java·服务器·前端
极客BIM工作室25 分钟前
深入理解C++中的Lazy Evaluation:延迟计算的艺术
开发语言·c++
来自于狂人28 分钟前
CentOS 镜像源配置与 EOL 后的应对策略
linux·运维·centos
im_AMBER38 分钟前
学习日志25 python
开发语言·python·学习
博语小屋1 小时前
进程初识之进程状态
linux
南棱笑笑生1 小时前
20250802让飞凌OK3576-C开发板在飞凌的Android14下【rk3576_u选项】适配NXP的WIFIBT模块88W8987A的蓝牙
c语言·开发语言