Skip to content

Instantly share code, notes, and snippets.

@tcartwright
Last active November 16, 2022 04:01
Show Gist options
  • Save tcartwright/152109ed9c3e5fa7fad1fec0edeb39e8 to your computer and use it in GitHub Desktop.
Save tcartwright/152109ed9c3e5fa7fad1fec0edeb39e8 to your computer and use it in GitHub Desktop.
NSSM Generic Service, Generic service wrapper utilizing NSSM to execute a powershell script
@%~d0
@cd "%~dp0"
@set /p svc=<"%~dp0ServiceName.txt"
powershell.exe -ExecutionPolicy RemoteSigned -NoLogo -NonInteractive -NoProfile -file "%~dp0%svc%.ps1"
@echo Done
@rem @pause
Clear-Host
$category = [System.IO.Path]::GetFileNameWithoutExtension($MyInvocation.MyCommand.Definition)
$scriptRoot = [System.IO.Directory]::GetParent($MyInvocation.MyCommand.Definition)
function Write-LogError ([string]$msg, [System.Exception]$exception) {
Write-Error -Message "$category[$(get-date -Format "MM-dd-yyyy HH:mm:ss.ffff")][Error]: $($msg)`r`n" -Exception $exception
}
function Write-Log ([string]$msg) {
Write-Host "$category[$(get-date -Format "MM-dd-yyyy HH:mm:ss.ffff")]: $($msg)`r`n"
}
#customize this to address list for the exception email if an exception occurs
$to = @("noreply@foo.com")
$serviceName = Get-Content "$scriptRoot\ServiceName.txt" -First 1
try {
# ADD CUSTOM CODE HERE
#
# ADD CUSTOM CODE HERE
} catch {
Write-LogError -msg $_.Exception.Message -exception $_.Exception
$computerInfoFile = "$scriptRoot\ComputerInfo.txt"
Get-ComputerInfo | Out-File -FilePath $computerInfoFile -Force -Encoding ascii -Width 5000
$from = "noreply@$($env:COMPUTERNAME).$((Get-WmiObject Win32_ComputerSystem).Domain)".ToLower()
$subject = "$($env:COMPUTERNAME) Service: $serviceName Error"
$msg = "$($subject), Exception:`r`n`r`n$($_.Exception.ToString())"
Send-MailMessage -SmtpServer "mail.domain.com" -From $from -To $to -Subject $subject -Body $msg -Attachments @($computerInfoFile)
} finally {
#stop the service now that we are done
Stop-Service -Name $serviceName
#REMOVE ANY ROLLOVER LOG FILES OLDER THAN X DAYS
$logPath = "$scriptRoot\logs"
if (Test-Path -Path $logPath) {
$limit = (Get-Date).AddDays(-14)
Get-ChildItem -Path $logPath -File -Force -Filter "service-*.log" | `
Where-Object { $_.CreationTime -lt $limit } | `
Remove-Item -Force
}
}
Information: A generic service wrapper that allows for custom services to be easily created for various administrative purposes.
The service is designed to be wrapped by NSSM (https://nssm.cc/). NSSM must be installed as a sibling folder to
the service folder.
".\GenericService\"
".\nssm\win64\nssm.exe"
The service will invoke the service bat which will in turn invoke the service ps1 file. This should contain the
guts of your service. The logic in the service ps1 can be tailored to your needs and situation.
Files:
- {ServiceName}.bat: The sole purpose of this file is to invoke the {ServiceName}.ps1.
- {ServiceName}.ps1: This file contains the bulk of the logic of the service. Customize to your indicidual needs.
By default these files are named:
GenericService.bat
GenericService.ps1
NOTE: The name of the service bat and ps1 file must match the service name in ServiceName.txt.
- ServiceName.txt: File which contains the name of the service. There must be only one line in this file, and it must be
the name of the service. If you edit the service name, you must edit the file names of the service bat, and ps1 file.
There is a Service-Rename.bat file to make renaming the service easier.
- Service-Install.bat: Installs and configures the service. Can be used to reconfigure an already installed service.
This file can be customized to match your service installation needs.
- Service-Edit.bat: Invokes the NSSM editor for the service. Will only work if the service is installed.
- Service-Remove.bat: Stops and removes the service.
- Service-Rename.bat: Stops and removes the service if installed, and then updates the ServiceName.txt file and renames
the service bat and ps1 file with the new service name.
- ComputerInfo.txt: (TEMP FILE) This file is created any time an exception occurs in the default exception handler for the
{ServiceName}.ps1 file. It includes information garnered from Get-ComputerInfo and is attached to an email detailing the exception.
@set /p svc=<"%~dp0ServiceName.txt"
"%~dp0..\nssm\win64\nssm.exe" edit %svc%
@if %ERRORLEVEL% NEQ 0 @pause
@rem https://nssm.cc/usage
@rem https://nssm.cc/commands
@md logs > nul
@set nssm="%~dp0..\nssm\win64\nssm.exe"
@set /p svc=<"%~dp0ServiceName.txt"
%nssm% install %svc% "%~dp0%svc%.bat"
@rem it is VERY important that the ending back slash on the app directory is there to escape the ending quote
%nssm% set %svc% AppDirectory """%~dp0\"""
%nssm% set %svc% Start SERVICE_DEMAND_START
@rem set the exit action to no restart, important!!! as this allows the script to exit and not get restarted
%nssm% set %svc% AppExit Default Ignore
%nssm% set %svc% Description Generic Service. Allows for custom code to be run on demand manually from a service by use of powershell.
@rem %nssm% set %svc% DependOnService ServiceName
%nssm% set %svc% AppStdout "%~dp0logs\service.log"
%nssm% set %svc% AppStderr "%~dp0logs\service.log"
%nssm% set %svc% AppStdoutCreationDisposition 4
%nssm% set %svc% AppStderrCreationDisposition 4
%nssm% set %svc% AppRotateFiles 1
%nssm% set %svc% AppRotateOnline 0
@rem 86400 == 1 day
%nssm% set %svc% AppRotateSeconds 86400
@rem 1048576 == 1.04 MB, 25000 == 25K, 0 == only use seconds for rotate
%nssm% set %svc% AppRotateBytes 0
@echo.
@echo Done
@echo.
@pause
@SET nssm="%~dp0..\nssm\win64\nssm.exe"
@set /p svc=<"%~dp0ServiceName.txt"
%nssm% stop %svc%
%nssm% remove %svc% confirm
@pause
@setlocal
@echo.
@set /p newsvc="What is the new service name? (Enter default to reset the name): "
@if [%newsvc%] == [] @goto emptyservice
@if [%newsvc%] == [default] @set newsvc=GenericService
@rem get the old service name so we can rename the files
@set /p oldsvc=<"%~dp0ServiceName.txt"
@if [%newsvc%] == [%oldsvc%] @goto samename
@call "%~dp0Service-Remove.bat"
rename "%~dp0%oldsvc%.bat" "%newsvc%.bat"
@if %ERRORLEVEL% NEQ 0 @goto error
rename "%~dp0%oldsvc%.ps1" "%newsvc%.ps1"
@if %ERRORLEVEL% NEQ 0 @goto error
echo %newsvc%> ServiceName.txt
@goto end
:emptyservice
@echo You have entered an empty service name. This is invalid, exiting.
@goto end
:error
@echo An error has occurred. This has occurred because there is most likely a name mismatch between the names of the service files and the contents of the ServiceName.txt file. Exiting.
@goto end
:samename
@echo You have entered the same name as the old service name. Exiting.
@goto end
:end
@pause
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment