由于业务需要 开发一个服务 保证窗口不被关闭,但是又要想看到是否执行成功.
获取服务错误日志
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服务 - 黑月教主 - 博客园