I have below script which will
Stop WebService
Delete WebService
Copy items from Jenkins workspace to server path
Create WebService
Start WebService
I run this PS script in Jenkins job and after execution of this,I get a email as Build is failed.
val STOPPED
[SC] DeleteService SUCCESS
val DELETED
Remove-Item : Cannot remove item \\Location.dll: Access to the
path '\\Location.dll' is denied.
At C:\Users\Administrator\AppData\Local\Temp\hudson7587011077362516847.ps1:33 char:5
+ Remove-Item "$val\*" -Force -Recurse
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (\\10.0.1.190\d$...h\Grpc.Core.dll:FileInfo) [Remove-Item], Unauthoriz
edAccessException
+ FullyQualifiedErrorId : RemoveFileSystemItemUnAuthorizedAccess,Microsoft.PowerShell.Commands.RemoveItemCommand
My PS script
# force strict - so any variable used before being assigned causes an error
Set-PsDebug -Strict
# force PowerShell to exit with a non-zero code on teh first error
$ErrorActionPreference = 'Stop'
# set $LASTEXITCODE to zero, so the script doesn't fail if no exit code returned
$LASTEXITCODE = 0
# set directories here once, so we can reuse
$MystiflySearchDir = "\\Location"
$ReleaseDir = "C:\Location"
# get directory contents (are you expecting these to return to Jenkins?)
Get-ChildItem "$ReleaseDir\*"
# create the search directory if it doesn't exist
if (-not (Test-Path -Path $val -PathType Container)) { New-Item -Path $val-type directory -Force }
# get the service, but fail gracefully if it doesn't exist
$service = Get-Service -Name val -Computername $env:SERVER -ErrorAction SilentlyContinue
# if we have a service, stop and delete it
if($service.Status)
{
sc.exe \\$env:SERVER stop val
if ($LASTEXITCODE -ne 0) { throw "error stopping the service: $LASTEXITCODE" }
Write-Host "val STOPPED"
Start-Sleep -s 10
sc.exe \\$env:SERVER delete val
if ($LASTEXITCODE -ne 0) { throw "error deleting the service: $LASTEXITCODE" }
Write-Host "val DELETED"
Start-Sleep -s 25
Remove-Item "$val\*" -Force -Recurse
}
# copy release to search
xcopy "$ReleaseDir\*" $val/k/e/d/Y
# (re)create the service
sc.exe \\$env:SERVER create val start=auto DisplayName= "value" binPath= D:\Location.exe
if ($LASTEXITCODE -ne 0) { throw "error creating the service: $LASTEXITCODE" }
sc.exe \\$env:SERVER description val "val"
if ($LASTEXITCODE -ne 0) { throw "error adding description to service: $LASTEXITCODE" }
sc.exe \\$env:SERVER start val
if ($LASTEXITCODE -ne 0) { throw "error starting the service: $LASTEXITCODE" }
Write-Host "val STARTED"
Is there anything i am missing here
Your code needed a little tidying up, as you had a couple of repeating sections, that were performed whether the service existed or not. Also flipped the if logic.
Added some steps at the start of your code to cause PowerShell to be more strict and drop out on any errors with a non-zero code.
This has not been tested, so may need a little fine-tuning. However, it should be 95% there, hopefully!
# force strict - so any variable used before being assigned causes an error
Set-PsDebug -Strict
# force PowerShell to exit with a non-zero code on the first error
$ErrorActionPreference = 'Stop'
# set $LASTEXITCODE to zero, so the script doesn't fail if no exit code returned
$LASTEXITCODE = 0
# se directories her once, so we can reuse
$AirSearchDir = "\\Location"
$ReleaseDir = "C:\Location"
# get directory contents (are you expecting these to return to Jenkins?)
Get-ChildItem "$ReleaseDir\*"
# create the search directory if it doesn't exist
if (-not (Test-Path -Path $AirSearchDir -PathType Container)) { New-Item -Path $AirSearchDir -type directory -Force }
# get the service, but fail gracefully if it doesn't exist
$service = Get-Service -Name val -Computername $env:SERVER -ErrorAction SilentlyContinue
# if we have a service, stop and delete it
if($service.Status)
{
sc.exe \\$env:SERVER stop val
if ($LASTEXITCODE -ne 0) { throw "error stopping the service: $LASTEXITCODE" }
Write-Host "val STOPPED"
sc.exe \\$env:SERVER delete val
if ($LASTEXITCODE -ne 0) { throw "error deleting the service: $LASTEXITCODE" }
Write-Host "val DELETED"
}
# copy release to search
Copy-Item "$ReleaseDir\*" $AirSearchDir -Force -Recurse
# (re)create the service
sc.exe \\$env:SERVER create val start=auto DisplayName="val" binPath= D:\Location.exe
if ($LASTEXITCODE -ne 0) { throw "error creating the service: $LASTEXITCODE" }
sc.exe \\$env:SERVER description val "val"
if ($LASTEXITCODE -ne 0) { throw "error adding description to service: $LASTEXITCODE" }
sc.exe \\$env:SERVER start val
if ($LASTEXITCODE -ne 0) { throw "error starting the service: $LASTEXITCODE" }
Write-Host "val STARTED"
Try running your Jenkins with the administrator account, the reason why you are getting this error is because your jenkins user is unable to interact with the services.
Running it with the administrator account will give it sufficient privileges to interact with other services.
Related
i have a script made in powershell and i am using nssm to create as a service to be executed every "x" time, however when starting the service it generates error and does not execute.
I have full administrator rights and I even tried to run PowerShell as an administrator without success.
If I run the script directly it works, however using nssm it is not working.
The error that happens is this:
Start-Service: Service 'nice (nice)' start failed.
At C: \ Program Files \ NICE Systems \ nssm.ps1: 10 char: 14
Start-Service <<<< $ serviceName
CategoryInfo: OpenError: (System.ServiceProcess.ServiceController: ServiceController) [Start-Service],
ServiceCommandException
FullyQualifiedErrorId: StartServiceFailed, Microsoft.PowerShell.Commands.StartServiceCommand
nssm.ps1
$nssm = (Get-Command nssm.exe).Definition
$serviceName = 'nice'
$powershell = (Get-Command powershell.exe).Definition
$scriptPath = 'C:\Program Files\NICE Systems\script_delecao.ps1'
$arguments = '-ExecutionPolicy Bypass -NoProfile -File "{0}"' -f $scriptPath
& $nssm install $serviceName $powershell $arguments
& $nssm status $serviceName
Start-Service $serviceName
Get-Service $serviceName
script_delecao.ps1
$logPath = "C:\Program Files\NICE Systems\Logs\*\Archive\*"
# -------------------------------------------------------------------------------------------
# SET $NDAYS WITH THE NUMBER OF DAYS TO KEEP IN LOG FOLDER.
$nDays = 180
# -------------------------------------------------------------------------------------------
# SET $EXTENSIONS WITH THE FILE EXTENSION TO DELETE.
# YOU CAN COMBINE MORE THAN ONE EXTENSION: "*.LOG, *.TXT,"
$Extensions = "*.log*"
# -------------------------------------------------------------------------------------------
# PAY ATTENTION! IF YOU COMBINE MORE THAN ONE LOG PATH AND EXTENSIONS,
# MAKE SURE THAT YOU ARE NOT REMOVING FILES THAT CANNOT BE DELETED
# -------------------------------------------------------------------------------------------
$PathDelete = "C:\Program Files\NICE Systems\Delecoes"
while ($true) {
If(!(test-path $PathDelete))
{
New-Item -ItemType Directory -Force -Path $PathDelete
}
$LogDate = (Get-Date).ToString("dd_MM_yyyy")
$DateTime = (Get-Date).ToString("yyy-MM-ddThh:mm:ss")
$Files = Get-Childitem $LogPath -Include $Extensions -Recurse | Where `
{$_.LastWriteTime -le (Get-Date).AddDays(-$nDays)}
foreach ($File in $Files)
{
if ($File -ne $NULL)
{
$Log = $DateTime + " - O arquivo " + $File + " foi deletado "
$Log | Out-File -Append $PathDelete\DeleteLogFile_$LogDate.log
Remove-Item $File.FullName| out-null
}
}
# Add a sleep at the end of the loop to prevent the script from eating
# too much CPU time
$Log = $DateTime + " FINAL DO ARQUIVO "
$Log | Out-File -Append $PathDelete\DeleteLogFile_$LogDate.log
Start-Sleep -Seconds 300
}
I believe I have a similar scenario where I cannot back-up Bamboo file system while it's running. My back-up executes from a rundeck server via Remote PowerShell, and even though the user has local admin rights it cannot stop and start services using NSSM. So I use this function to run the command elevated
ELEVAT "nssm stop bamboo"
tar --exclude=./logs --exclude=./temp --exclude=*.log --exclude=*.jar --verbose -czf E:\dropfolder\bamboo-home.tar.gz --directory=E:\bamboo-home .
ELEVAT "nssm start bamboo"
the function itself...
function ELEVAT ($command) {
$scriptBlock = [scriptblock]::Create($command)
configuration elevated {
Import-DscResource -ModuleName 'PSDesiredStateConfiguration'
Set-StrictMode -Off
Node localhost {
Script execute {
SetScript = $scriptBlock
TestScript = {
if (([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
Write-Verbose "Verified Elevated Session"
return $false
} else {
Write-Verbose "Not an Elevated Session!"
exit 9996
}
}
GetScript = { return #{ 'Result' = 'RUN' } }
}
}
}
$mof = elevated
Start-DscConfiguration ./elevated -Wait -Verbose -Force
if ( $error ) { Write-Host "[ELEVAT][WARN] `$Error[] = $Error" ; $Error.clear()
}
}
I am using powershell to process csv files in a directory when no file found with current date stamp I want the process to raise an error notifying file not found and exit.
# Powershell raise error and exit
# File name: sale_2020_02_03.csv
$getLatestCSVFile = Get-ChildItem -Path $Folder -Filter "*.csv" | Sort-Object LastWriteTime -Descending | Select-Object -First 1
if ($getLatestCSVFile)
{
try
{
# Process .csv file
}
catch
{
# on error
$ErrorMessage = $_.Exception.Message
throw "$ErrorMessage"
}
}
else
{
# If current date file not found raise error and exit
Send-MailMessage
throw "File not found"
}
As for this...
I would like to have the powershell script to stop execution
... that is what the Exit keyword is for or the '-ErrorAction Stop' option is for.
As for this...
if the code gets into the else block in the else block I want to
notify file not found
... as per my above, same thing, and you have to set that.
Meaning stuff like ...
Clear-Host
$Error.Clear()
try
{
# Statement to try
New-Item -Path 'D:\Temp\DoesNOtExist' -Name 'Test.txt' -ItemType File -ErrorAction Stop
}
catch
{
# What to do with terminating errors
Write-Warning -Message $Error[0]
}
# Results
<#
WARNING: Could not find a part of the path 'D:\Temp\DoesNOtExist\Test.txt'.
#>
Or using multiple catch statements, like ...
Example: Force file warning
Clear-Host
$Error.Clear()
try
{
# Results in NoSupportException
# Statement to try
New-Item -Path 'D:\Temp\Temp' -Name my:Test.txt -ItemType File -ErrorAction Stop
# Results in DirectoryNotFoundException
# New-Item -Path 'D:\Temp\Temp' -Name 'Test.txt' -ItemType File -ErrorAction Stop
}
catch [System.NotSupportedException]
{
# What to do with terminating errors
Write-Warning -Message 'Illegal chracter or filename.'
}
catch [System.IO.DirectoryNotFoundException]
{
# What to do with terminating errors
Write-Warning -Message 'The path is not valid.'
}
catch
{
# What to do with terminating errors
Write-Warning -Message 'An unexpected error occurred.'
}
# Results
<#
WARNING: Illegal character or filename.
#>
Example: Force path warning
Clear-Host
$Error.Clear()
try
{
# Results in NoSupportException
# Statement to try
# New-Item -Path 'D:\Temp\Temp' -Name my:Test.txt -ItemType File -ErrorAction Stop
# Results in DirectoryNotFoundException
New-Item -Path 'D:\Temp\Temp' -Name 'Test.txt' -ItemType File -ErrorAction Stop
}
catch [System.NotSupportedException]
{
# What to do with terminating errors
Write-Warning -Message 'Illegal chracter or filename.'
}
catch [System.IO.DirectoryNotFoundException]
{
# What to do with terminating errors
Write-Warning -Message 'The path is not valid.'
}
catch
{
# What to do with terminating errors
Write-Warning -Message 'An unexpected error occurred.'
}
# Results
<#
WARNING: The path is not valid.
#>
See also this discussion, which is a similar use case. Pay particular attention the the 'Exit vs Return vs Break' answer.
Terminating a script in PowerShell
I'm studying for Network\System Admin certification (MCSE is in it) and among other things we started to delve into powershell scripting.
At any rate my instructor gave me a challenge to do as follows:
I need to create a PS script which will run Robocopy tool in order to mirror a folder from point A to Point B and that script should run as a schedule task (/w Task Scheduler).
If robocopy have encountered any errors the script should send a mail via the Company's exchange mail server to the Admin in charge of the process.
I'm not Scripting savvy of any sort so I had to sit and learn the syntax, command etc before I could start working.
Here is what I got so far:
# PowerShell Robocopy Script V.1 | Liron Ben-David
# Variables
$Source ="C:\Source\"
$Destination = "C:\Destination\"
$ExitCode = "Null"
#Copying Process
Robocopy $Source $destination *.* /mir /r:100 /w:10
# Return Code Section
if ($LASTEXITCODE -eq 0) {$ExitCode = "Succeeded, Code: $LASTEXITCODE" }
elseif (($LASTEXITCODE -gt 1) -and ($LASTEXITCODE -lt 17)) {$ExitCode = "Failure, Code: $LASTEXITCODE" }
else {$ExitCode = "No Return Code"}
Write-Host $ExitCode
## Failure Report
if ($ExitCode -gt 1) {Send-MailMessage -to "Admin (Admin#Domain.com)" -From "Machine-Robocopy1 (M1RC#domain.com)" -Subject $ExitCode -SmtpServer mail.domain.com}
else {exit}
basically if there is any kind of error in the process the script supposed to send an email with the script error code as the "Subject" of the message.
First of all:
Does this script contain any embarassing mistakes I did and which I should avoid in the future?
Secondarily:
I never used the CLI to send email messages, using the Send-Mail CMDLET I should have used a credentials switch but according to what I've read\watched it seems it will pop up a window for input.
Considering I'm setting this script for a Domain Environment wouldn't the SSO feature will kick in when I try to send the message?
EDIT:
Also noticed I mixed the error codes so I need to re-calibrate the error code lines.
EDIT 2: Version 2 bsaed on your help,
# PowerShell Robocopy Script V.2 | Liron Ben-David
# Variables
$Source = "C:\Source\"
$Destination = "C:\Destination\"
$ExitCode = "Null"
$ReturnCodeValue = "Void"
$Log = "C:\RoboLogs\RobocopyLog.txt"
#Copying Process
Robocopy $Source $destination *.* /mir /r:100 /w:10 /UniLog:C:\RoboLogs\RobocopyLog.txt /v
# Return Code Section
if (($LASTEXITCODE -eq 0) -or ($LASTEXITCODE -eq 1) -or ($LASTEXITCODE -eq 3) -or ($LASTEXITCODE -eq 5) -or ($LASTEXITCODE -eq 6) -or ($LASTEXITCODE -eq 7)) {$ExitCode = "Succeeded, Code: $LASTEXITCODE" }
elseif (($LASTEXITCODE -eq 2) -or ($LASTEXITCODE -eq 4)) {$ExitCode = "Error, Code: $LASTEXITCODE" }
elseif ($LASTEXITCODE -gt 7) {$ExitCode = "Failure, Code: $LASTEXITCODE" }
else {$ExitCode = "No Return Code"}
$ReturnCodeValue = $LASTEXITCODE
# Debug Section
#Write-Host "Did the script completed succesfuly:" $?
#Write-Host "Script Exit Code:" $ExitCode
#Start-Sleep -s 4
## Failure Report
if (($ReturnCodeValue -gt 7) -or ($ReturnCodeValue -eq 2) -or ($ReturnCodeValue -eq 4)) {Send-MailMessage -to "Admin (Admin#Domain.com)" -From "Machine-Robocopy1 (M1RC#domain.com)" -Subject $ExitCode -SmtpServer mail.domain.com –Attachments $Log -UseSsl}
else {exit}
i try to do error handling within my powershell script. but i always get an fatal. i tried a few things, e. g. try{ } catch{ } - but i did it not get to work.
any ideas or Solutions?
Function Check-Path($Db)
{
If ((Test-Path $Db) –eq $false) {
Write-Output "The file $Db does not exist"
break
}
}
It Returns:
Test-Path : Zugriff verweigert
In K:\access\access.ps1:15 Zeichen:6
+ If ((Test-Path $Db) -eq $false) {
+ ~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (K:\ss.mdb:String) [Test-Path], UnauthorizedAccessException
+ FullyQualifiedErrorId : ItemExistsUnauthorizedAccessError,Microsoft.PowerShell.Commands.TestPathCommand
Somewhat confusingly Test-Path actually generates an error in a number of cases. Set the standard ErrorAction parameter to SilentlyContinue to ignore it.
if ((Test-Path $Db -ErrorAction SilentlyContinue) -eq $false) {
I cannot answer directly. So this has to do:
I strongly disagree with your answer. Test-Path does show $false when you run it against a network share that is not accessible, but it will be false also (without Exception) when the Server is not reachable.
So your answer simply ignores anything but a reachable share.
What is neccessary however is a try-catch-block that handles this better:
[cmdletbinding()]
param(
[boolean]$returnException = $true,
[boolean]$returnFalse = $false
)
## Try-Catch Block:
try {
if ($returnException) {
## Server Exists, but Permission is denied.
Test-Path -Path "\\Exists\Data\" -ErrorAction Stop | Out-Null
} elseif ($returnFalse) {
## Server does not exist
Test-Path -Path "\\NoExists\Data\" -ErrorAction Stop | Out-Null
}
} catch [UnauthorizedAccessException] {
## Unauthorized
write-host "No Access Exception"
} catch {
## an error has occurred
write-host "Any other Exception here"
}
The really important part however is the ErrorAction on the Test-Path command, otherwise the exception will be wrapped around a system management error and is thus not catchable. This is in detail explained here:
PowerShell catching typed exceptions
I'm new to powershell, but I'm trying to output some simple logging in a ps I'm writing to create scheduled tasks. My code is below. It seems that it doesn't throw an exception when you get an error with schtasks. Another SO question mentioned this with fileIO actions and suggested doing "-ea stop" but that doesn't work with schtasks.
#create log file
$log = "\\servername\!incoming\Deploy\log.txt"
Clear-Content $log
#get input file list
$txtServerList = Gc "\\servername\!incoming\Deploy\serverlist.txt"
#loop through each server
ForEach($strServername In $txtServerList)
{
try
{
#install task from XML template
schtasks /create /s $strServername /tn InventoryServer /XML "\\servername\!incoming\Deploy\TaskTemplate.xml"
#run the task immediately
schtasks /run /s $strServername /tn InventoryServer
}
catch [exception]
{
Add-Content -path $log -value $strServername
#Add-Content -path $log -value $_.Exception
#Add-Content -path $log -value $_.Exception.Message
#Add-Content -path $log -value ""
}
}
I verified that 'Add-Content -path "\servername!incoming\Deploy\log.txt" -value "test"'works, so like I said I'm fairly sure it's just not throwing an exception.
In order for a Try/Catch to work, PowerShell needs a terminating exception. When running a cmdlet in a Try block you can make that happen by using -erroraction Stop (or use the -ea alias). As you already realize SCHTASKS.EXE can't do this. Without a terminating exception, the code in the Catch block will never run.
What you have to do is step out side the box, so to speak, and independently check if Schtasks failed. If so, they you can use Write-Error in your Try block.
One thing you might try is using Start-Process and look at the exit code. Anything other than 0 should be an error.
Try {
get-date
$p=Start-Process schtasks.exe -ArgumentList "/Create foo" -wait -passthru
if ($p.exitcode -ne 0) {
write-error "I failed with error $($p.exitcode)"
}
}
Catch {
"oops"
$_.Exception
}