6

I created the script below to check my application's port 2025 and log the number of connections.

I need this script to run as a service on Windows with the name netstat_2025. Does anyone know if there is such a possibility?

I do not want to use the Task Scheduler, but instead run the script as a service on Windows.

script SCTT521CTO.ps1

$startTime =  (Get-Date).ToString("dd_MM_yyyy")
$LogDate = ((get-date).ToLocalTime()).ToString("yyyy-MM-ddTHH:mm:ss.fff")
$hostname = hostname

$portTServer = 8000
$FileTserver = netstat -ano | findstr "8000"

$LogTserver = $LogDate + " - Quantidade de Conexoes na porta " + $portTServer + ": " + $FileTserver.count + " - Servidor: " + $hostname
$LogTserver | Out-File -Append D:\SCTT521CTO\netstat_$startTime.log

$limit = (Get-Date).AddDays(-5)
$path = "D:\SCTT521CTO\*"
Get-ChildItem -Path $path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force

script service.ps1

# Desired name of the service
$serviceName = 'netstat_2025'

# Get the full path to powershell.exe
$powershellPath = ( Get-Command powershell ).Source

# The path to the script you want to run as a service
$serviceScriptPath = D:\scripts\SCTT521CTO.ps1

# The arguments to pass to the powershell executable each time the service starts
$args = '-ExecutionPolicy Bypass -NoProfile -File "{0}"' -f $serviceScriptPath

# Install the service using nssm
nssm install $serviceName $powershellPath $args

# See that the service is registered and check its status
Get-Service $serviceName
  • Does this answer your question? [how to run a powershell script as a windows service from inside a Java program?](https://stackoverflow.com/questions/42927184/how-to-run-a-powershell-script-as-a-windows-service-from-inside-a-java-program) – Paxz Dec 30 '19 at 12:11
  • Have a look at [New-Service](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/new-service?view=powershell-6) – Theo Dec 30 '19 at 13:31
  • I followed the example, but to no avail, the service was created, but unable to start it. – Leandro de Matos Dec 30 '19 at 13:38
  • sc.exe create PS_Trigger_Service Displayname= "PS_Trigger_Service" binpath= "D:\SCRIPTS\SCTT521CTO.ps1" start= auto – Leandro de Matos Dec 30 '19 at 13:39
  • Returns an error while trying to start the service. "Erro 193: 0Xc1" – Leandro de Matos Dec 30 '19 at 13:40
  • It sounds like you need to run this as a scheduled task rather than as a service. (Services are special applications that respond to control requests.) – Bill_Stewart Dec 30 '19 at 18:50
  • How scheduled task works, however in my work it is not feasible to create this way, so I thought of running as a service in Windows. – Leandro de Matos Dec 30 '19 at 18:56
  • Why is it not feasible? – Bill_Stewart Dec 31 '19 at 00:39
  • @LeandrodeMatos see my updated answer – codewario Jan 02 '20 at 15:06
  • @BendertheGreatest I tried to create the script below using nssm but the service does not start, returning me the error "Service netstat_8000 ran for less than 1500 milliseconds. Restart will be delayed by 1" – Leandro de Matos Jan 12 '20 at 23:49
  • My answer already covers this but if you want your service to run until stopped, you need to put your main logic in an infinite loop, or at least a loop that won't terminate until a condition is met where you want the service to stop. Otherwise, your service ends because you reached the end of your code. This isn't nssm specific, this is a rule of service design. In your case you'll probably want to make sure at the end of the loop you sleep for some number of seconds at the end of the main loop otherwise your service is likely to eat a bunch of CPU time. – codewario Jan 13 '20 at 03:15
  • I updated my answer to show what I mean by "put your main logic in an infinite loop" – codewario Jan 13 '20 at 15:15

2 Answers2

4

You can just download NSSM from nssm.cc them:

  1. Run nssm in command line: nssm install YourServiceName

  2. Set the informations:

  • Path: Powershell path
  • Startup directory: Your script directory
  • Options: .\yourscript.ps1 -arg1 value -arg2 value -arg3 value

enter image description here

That's it.

2

My original answer failed to take into account that you still need to implement the service control interfaces, which powershell.exe does not implement. I did look into some other methods of running a PowerShell script as a service, however.

One of the easier tools I came across that does this for you is nssm You can use nssm (Non-Sucking Service Manager) to register a new service and have it run your PowerShell script. You'll need to make sure your script's main logic runs within an infinite loop (as most long running programs or services do), and then you can use nssm to register a new service that will run your PowerShell script. Below is an example of putting your code into a main loop that doesn't terminate:

while( $true ) {
  $startTime =  (Get-Date).ToString("dd_MM_yyyy")
  $LogDate = ((get-date).ToLocalTime()).ToString("yyyy-MM-ddTHH:mm:ss.fff")
  $hostname = hostname

  $portTServer = 8000
  $FileTserver = netstat -ano | findstr "8000"

  $LogTserver = $LogDate + " - Quantidade de Conexoes na porta " + $portTServer + ": " + $FileTserver.count + " - Servidor: " + $hostname
  $LogTserver | Out-File -Append D:\SCTT521CTO\netstat_$startTime.log

  $limit = (Get-Date).AddDays(-5)
  $path = "D:\SCTT521CTO\*"
  Get-ChildItem -Path $path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force

  # Add a sleep at the end of the loop to prevent the script from eating
  # too much CPU time
  Start-Sleep -Seconds 60
}

To register your script as a PowerShell service, you can use the following PowerShell code (note that if you install with Chocolatey, nssm will already be on the PATH, not sure if it is when you manually install):

# Desired name of the service
$serviceName = 'netstat_2025'

# Get the full path to powershell.exe
$powershellPath = ( Get-Command powershell ).Source

# The path to the script you want to run as a service
$serviceScriptPath = C:\path\to\service\script.ps1

# The arguments to pass to the powershell executable each time the service starts
$args = '-ExecutionPolicy Bypass -NoProfile -File "{0}"' -f $serviceScriptPath

# Install the service using nssm
nssm install $serviceName $powershellPath $args

# See that the service is registered and check its status
Get-Service $serviceName

Your service should now be installed and able to be controlled like any other Windows service. The way this works is instead of registering powershell.exe as a service directly, it registers nssm.exe as the service executable instead, which does implement the correct service control handlers, and then runs whatever program you configured it to for this service (in this case, calling your script with powershell.exe).

codewario
  • 19,553
  • 20
  • 90
  • 159
  • Hello, I created the service however trying to start it returns the error below: "The service did not respond to the start request or control in a timely manner." One solution I have tried so far was to create a key in the windows registry called ServicesPipeTimeout hoping that the error was that the wait time to start the service was too small, but unfortunately it did not resolve. How can I proceed? Should I change something in my code? – Leandro de Matos Dec 30 '19 at 18:23
  • Damn, I thought this would work but it seems you still need to implement the .NET service interfaces within your script for this to work. I don't have time at the moment but I can update this tonight or tomorrow with how to do that from your script. – codewario Dec 30 '19 at 19:00
  • Looking at your script you'll also need your main bit to be an unterminating loop for when the service is running, otherwise it'll just stop because it hits the end of your code. – codewario Dec 30 '19 at 19:04
  • 1
    The main problem, of course, is that services are special executables that respond to control signals, and `powershell.exe` is not designed as a service. The OP should opt to run the script using a scheduled task instead. – Bill_Stewart Dec 31 '19 at 10:50
  • Due to my work restrictions, all tasks in Scheduler are automatically deleted. Therefore I must create as a service. – Leandro de Matos Dec 31 '19 at 11:49
  • @BendertheGreatest I tried some ways but could not update the code, could you tell me how to proceed? – Leandro de Matos Dec 31 '19 at 11:51
  • 2
    You cannot directly run a PowerShell script as a service because `powershell.exe` is not a service executable. How and why are all tasks in the scheduler automatically deleted? The Task Scheduler is a core OS component. Address that problem and run as a task, or use another tool that lets you schedule programs to run. – Bill_Stewart Dec 31 '19 at 19:35
  • 1
    Still, there are cases where a long running service is more desirable than a scheduled task. Solving this problem is still useful to know. I'm updating my answer with how to achieve this correctly with PowerShell. – codewario Jan 02 '20 at 14:38
  • IMO a third-party tool is unnecessary when you can just run as a scheduled task. – Bill_Stewart Jan 03 '20 at 01:14