Pra007 V
asked on
Power shell script runs successfully but defined function will not effect
Hi,
I am trying below script for removal of files from our local setup basing on the retention policy.
I am able to run the script manually as well as using task manager return code is 0. But actual deletion of the files is not happening.
I am using SYSTEM user with full control to run the script . I bypassed the policies still it is not giving me the wanted result.
Script ::
======
$ErrorActionPreference = "stop"
stop-transcript
start-transcript -path C:\Users\scrptlog.txt
$BaseDirectory = "C:\Users\test"
$Global:RetentionDays = 15
#$Global:OldFiles = @()
#$Global:OldDirectories = @()
$Global:Exceptions = @()
#$Global:NerfMode = $true
$Global:CurrentDate = (get-date)
function EvaluateDirectory
{
Param
(
[parameter(Mandatory=$fals e, Position=0)][string] $DirectoryPath
)
#write-host ("Evaluating " + $DirectoryPath)
try
{
if (!(Test-Path $DirectoryPath))
{
throw "Directory ($DirectoryPath) does not exist or is inaccessible"
}
$Children = Get-ChildItem $DirectoryPath -Force
if ($Children -ne $null)
{
foreach ($c in $Children)
{
$age = $null #Safety first!
$age = $Global:CurrentDate - $c.LastWriteTime
if ($c.LastAccessTime -gt $c.LastWriteTime)
{
$age = $Global:CurrentDate - $c.LastAccessTime
}
[bool] $isOld = $false
if (($age -ne $null) -and ($age.TotalDays -gt $Global:RetentionDays))
{
$isOld = $true
}
if ($c.PSIsContainer -eq $true)
{
$Global:TotalFolders += 1
#I am skipping the below two folders removal
if (($c.Name -ne "Documentation") -and ($c.Name -ne "X_*"))
{
#From the below directories files should be removed basing on my retention
EvaluateDirectory $c.FullName
if (($c.Name -ne "From-Customer") -and ($c.Name -ne "To-Customer")) # -and ($isOld -eq $true))
{
$subChildren = Get-ChildItem $c.FullName -Force
if ($subChildren -eq $null)
{
$Global:RemovedFolders += 1
Remove-Item $c.FullName -Force -Confirm:$false
}
}
}
}
else
{
$Global:TotalFiles += 1
if ($isOld -eq $true)
{
$Global:RemovedFiles += 1
Remove-Item $c.FullName -Force -Confirm:$false
}
}
}
}
}
catch [Exception]
{
$Global:Exceptions += $_
Write-Host "EXCEPTION: $($_.Exception.Message)`r` n`tDirecto ry Path: $DirectoryPath"
}
$Children = Get-ChildItem $BaseDirectory
foreach ($c in $Children | sort-object Name)
{
if (($c.Name -ne "Documentation") -and ($c.Name -ne "X_*"))
{
$Global:TotalFiles = 0
$Global:RemovedFiles = 0
$Global:TotalFolders = 0
$Global:RemovedFolders = 0
EvaluateDirectory $c.FullName
write-host $c.Name
write-host "`tFiles: $($Global:TotalFiles) total, $($Global:RemovedFiles) removed"
write-host "`tFolders: $($Global:TotalFolders) total, $($Global:RemovedFolders) removed"
}
}
}
I am trying below script for removal of files from our local setup basing on the retention policy.
I am able to run the script manually as well as using task manager return code is 0. But actual deletion of the files is not happening.
I am using SYSTEM user with full control to run the script . I bypassed the policies still it is not giving me the wanted result.
Script ::
======
$ErrorActionPreference = "stop"
stop-transcript
start-transcript -path C:\Users\scrptlog.txt
$BaseDirectory = "C:\Users\test"
$Global:RetentionDays = 15
#$Global:OldFiles = @()
#$Global:OldDirectories = @()
$Global:Exceptions = @()
#$Global:NerfMode = $true
$Global:CurrentDate = (get-date)
function EvaluateDirectory
{
Param
(
[parameter(Mandatory=$fals
)
#write-host ("Evaluating " + $DirectoryPath)
try
{
if (!(Test-Path $DirectoryPath))
{
throw "Directory ($DirectoryPath) does not exist or is inaccessible"
}
$Children = Get-ChildItem $DirectoryPath -Force
if ($Children -ne $null)
{
foreach ($c in $Children)
{
$age = $null #Safety first!
$age = $Global:CurrentDate - $c.LastWriteTime
if ($c.LastAccessTime -gt $c.LastWriteTime)
{
$age = $Global:CurrentDate - $c.LastAccessTime
}
[bool] $isOld = $false
if (($age -ne $null) -and ($age.TotalDays -gt $Global:RetentionDays))
{
$isOld = $true
}
if ($c.PSIsContainer -eq $true)
{
$Global:TotalFolders += 1
#I am skipping the below two folders removal
if (($c.Name -ne "Documentation") -and ($c.Name -ne "X_*"))
{
#From the below directories files should be removed basing on my retention
EvaluateDirectory $c.FullName
if (($c.Name -ne "From-Customer") -and ($c.Name -ne "To-Customer")) # -and ($isOld -eq $true))
{
$subChildren = Get-ChildItem $c.FullName -Force
if ($subChildren -eq $null)
{
$Global:RemovedFolders += 1
Remove-Item $c.FullName -Force -Confirm:$false
}
}
}
}
else
{
$Global:TotalFiles += 1
if ($isOld -eq $true)
{
$Global:RemovedFiles += 1
Remove-Item $c.FullName -Force -Confirm:$false
}
}
}
}
}
catch [Exception]
{
$Global:Exceptions += $_
Write-Host "EXCEPTION: $($_.Exception.Message)`r`
}
$Children = Get-ChildItem $BaseDirectory
foreach ($c in $Children | sort-object Name)
{
if (($c.Name -ne "Documentation") -and ($c.Name -ne "X_*"))
{
$Global:TotalFiles = 0
$Global:RemovedFiles = 0
$Global:TotalFolders = 0
$Global:RemovedFolders = 0
EvaluateDirectory $c.FullName
write-host $c.Name
write-host "`tFiles: $($Global:TotalFiles) total, $($Global:RemovedFiles) removed"
write-host "`tFolders: $($Global:TotalFolders) total, $($Global:RemovedFolders) removed"
}
}
}
Start-Transcript is already part of the script ;-).
I don't see you calling the defined function outside of itself. The script does not do anything no matter how you run it, I suppose?
I don't see you calling the defined function outside of itself. The script does not do anything no matter how you run it, I suppose?
hah missed that huh... good call :)
ASKER
Hi Experts,
Thank you for the reply, I am new to powershell, Do you want me to include any extra code inside the given script?
Or can I call it from the command prompt or set up it in batch file or windows task manager? Please provide me your suggestions.
Thanks,
Prathibha
Thank you for the reply, I am new to powershell, Do you want me to include any extra code inside the given script?
Or can I call it from the command prompt or set up it in batch file or windows task manager? Please provide me your suggestions.
Thanks,
Prathibha
Qlemo pointed it out, but it really just looks like the bottom of your script is in the wrong place (within the function).
$ErrorActionPreference = "stop"
stop-transcript
start-transcript -path C:\Users\scrptlog.txt
$BaseDirectory = "C:\Users\test"
$Global:RetentionDays = 15
#$Global:OldFiles = @()
#$Global:OldDirectories = @()
$Global:Exceptions = @()
#$Global:NerfMode = $true
$Global:CurrentDate = (get-date)
function EvaluateDirectory
{
Param
(
[parameter(Mandatory=$false, Position=0)][string] $DirectoryPath
)
#write-host ("Evaluating " + $DirectoryPath)
try
{
if (!(Test-Path $DirectoryPath))
{
throw "Directory ($DirectoryPath) does not exist or is inaccessible"
}
$Children = Get-ChildItem $DirectoryPath -Force
if ($Children -ne $null)
{
foreach ($c in $Children)
{
$age = $null #Safety first!
$age = $Global:CurrentDate - $c.LastWriteTime
if ($c.LastAccessTime -gt $c.LastWriteTime)
{
$age = $Global:CurrentDate - $c.LastAccessTime
}
[bool] $isOld = $false
if (($age -ne $null) -and ($age.TotalDays -gt $Global:RetentionDays))
{
$isOld = $true
}
if ($c.PSIsContainer -eq $true)
{
$Global:TotalFolders += 1
#I am skipping the below two folders removal
if (($c.Name -ne "Documentation") -and ($c.Name -ne "X_*"))
{
#From the below directories files should be removed basing on my retention
EvaluateDirectory $c.FullName
if (($c.Name -ne "From-Customer") -and ($c.Name -ne "To-Customer")) # -and ($isOld -eq $true))
{
$subChildren = Get-ChildItem $c.FullName -Force
if ($subChildren -eq $null)
{
$Global:RemovedFolders += 1
Remove-Item $c.FullName -Force -Confirm:$false
}
}
}
}
else
{
$Global:TotalFiles += 1
if ($isOld -eq $true)
{
$Global:RemovedFiles += 1
Remove-Item $c.FullName -Force -Confirm:$false
}
}
}
}
}
catch [Exception]
{
$Global:Exceptions += $_
Write-Host "EXCEPTION: $($_.Exception.Message)`r`n`tDirectory Path: $DirectoryPath"
}
}
$Children = Get-ChildItem $BaseDirectory
foreach ($c in $Children | sort-object Name)
{
if (($c.Name -ne "Documentation") -and ($c.Name -ne "X_*"))
{
$Global:TotalFiles = 0
$Global:RemovedFiles = 0
$Global:TotalFolders = 0
$Global:RemovedFolders = 0
EvaluateDirectory $c.FullName
write-host $c.Name
write-host "`tFiles: $($Global:TotalFiles) total, $($Global:RemovedFiles) removed"
write-host "`tFolders: $($Global:TotalFolders) total, $($Global:RemovedFolders) removed"
}
}
ASKER
Hi Chris,
Do you want me to move the child code before exceptional handling?
Thanks,
Prathibha
Do you want me to move the child code before exceptional handling?
Thanks,
Prathibha
Just use the code as posted by Chris, it is complete.
ASKER
Thank you Chris,Qlemo for your prompt replies and solution provided is working for me :)
ASKER
Hi Experts,
Could you please let me know if we want to get an email for the completion of the activity to get the log file? and overwrite the existing log file an proceed for next run? How we can take it up?
Thanks,
Prathibha
Could you please let me know if we want to get an email for the completion of the activity to get the log file? and overwrite the existing log file an proceed for next run? How we can take it up?
Thanks,
Prathibha
Please confirm that how I read it is correct:
You want to have the log file overwritten each time, and sent after the job is finished?
If that is correct:
Start-Transcript already overwrites the log file, so nothing to do here.
For emailing the log file, you just add this as last line, with correct addresses of course:
You want to have the log file overwritten each time, and sent after the job is finished?
If that is correct:
Start-Transcript already overwrites the log file, so nothing to do here.
For emailing the log file, you just add this as last line, with correct addresses of course:
Send-MailMessage -SmtpServer mail.company.com -From me@company.com -To you@company.com -Subject "EvaluateDirectory Report" -Attachments C:\Users\scrptlog.txt
ASKER
Hi Qlemo,
Thank you for the reply, when I stopped script intermittently and try to re-run it, I am getting below . So I need to manually comment the stop transcript and once task initiates I will be removing the comment.
If my script failed with some reason once I scheduled how to resolve this with out manual intervention?
Stop-Transcript : An error occurred stopping transcription: The console host is not currently transcribing.
At C:\Scripts\cleanup.ps1:2 char:16
+ stop-transcript <<<<
+ CategoryInfo : InvalidOperation: (:) [Stop-Transcript], PSInvalidOperationExceptio n
+ FullyQualifiedErrorId : InvalidOperation,Microsoft .PowerShel l.Commands .StopTrans criptComma nd
Also when I use the given sent mail option, getting below, Do we need to specify any unlocking for the transcript file after cleanup?
Send-MailMessage : The process cannot access the file 'C:\Users\scrptlog.txt' because it is being
used by another process.
Thank you for the reply, when I stopped script intermittently and try to re-run it, I am getting below . So I need to manually comment the stop transcript and once task initiates I will be removing the comment.
If my script failed with some reason once I scheduled how to resolve this with out manual intervention?
Stop-Transcript : An error occurred stopping transcription: The console host is not currently transcribing.
At C:\Scripts\cleanup.ps1:2 char:16
+ stop-transcript <<<<
+ CategoryInfo : InvalidOperation: (:) [Stop-Transcript], PSInvalidOperationExceptio
+ FullyQualifiedErrorId : InvalidOperation,Microsoft
Also when I use the given sent mail option, getting below, Do we need to specify any unlocking for the transcript file after cleanup?
Send-MailMessage : The process cannot access the file 'C:\Users\scrptlog.txt' because it is being
used by another process.
Start and stop are in very strange places. Fixed here.
$ErrorActionPreference = "stop"
Start-Transcript -path C:\Users\scrptlog.txt
$BaseDirectory = "C:\Users\test"
$Global:RetentionDays = 15
#$Global:OldFiles = @()
#$Global:OldDirectories = @()
$Global:Exceptions = @()
#$Global:NerfMode = $true
$Global:CurrentDate = (get-date)
function EvaluateDirectory
{
Param
(
[parameter(Mandatory=$false, Position=0)][string] $DirectoryPath
)
#write-host ("Evaluating " + $DirectoryPath)
try
{
if (!(Test-Path $DirectoryPath))
{
throw "Directory ($DirectoryPath) does not exist or is inaccessible"
}
$Children = Get-ChildItem $DirectoryPath -Force
if ($Children -ne $null)
{
foreach ($c in $Children)
{
$age = $null #Safety first!
$age = $Global:CurrentDate - $c.LastWriteTime
if ($c.LastAccessTime -gt $c.LastWriteTime)
{
$age = $Global:CurrentDate - $c.LastAccessTime
}
[bool] $isOld = $false
if (($age -ne $null) -and ($age.TotalDays -gt $Global:RetentionDays))
{
$isOld = $true
}
if ($c.PSIsContainer -eq $true)
{
$Global:TotalFolders += 1
#I am skipping the below two folders removal
if (($c.Name -ne "Documentation") -and ($c.Name -ne "X_*"))
{
#From the below directories files should be removed basing on my retention
EvaluateDirectory $c.FullName
if (($c.Name -ne "From-Customer") -and ($c.Name -ne "To-Customer")) # -and ($isOld -eq $true))
{
$subChildren = Get-ChildItem $c.FullName -Force
if ($subChildren -eq $null)
{
$Global:RemovedFolders += 1
Remove-Item $c.FullName -Force -Confirm:$false
}
}
}
}
else
{
$Global:TotalFiles += 1
if ($isOld -eq $true)
{
$Global:RemovedFiles += 1
Remove-Item $c.FullName -Force -Confirm:$false
}
}
}
}
}
catch [Exception]
{
$Global:Exceptions += $_
Write-Host "EXCEPTION: $($_.Exception.Message)`r`n`tDirectory Path: $DirectoryPath"
}
}
$Children = Get-ChildItem $BaseDirectory
foreach ($c in $Children | sort-object Name)
{
if (($c.Name -ne "Documentation") -and ($c.Name -ne "X_*"))
{
$Global:TotalFiles = 0
$Global:RemovedFiles = 0
$Global:TotalFolders = 0
$Global:RemovedFolders = 0
EvaluateDirectory $c.FullName
write-host $c.Name
write-host "`tFiles: $($Global:TotalFiles) total, $($Global:RemovedFiles) removed"
write-host "`tFolders: $($Global:TotalFolders) total, $($Global:RemovedFolders) removed"
}
}
Stop-Transcript
Send-MailMessage -SmtpServer mail.company.com -From me@company.com -To you@company.com -Subject "EvaluateDirectory Report" -Attachments C:\Users\scrptlog.txt
ASKER
Hi Chris,
Really appreciate your efforts, I am very thankful.
Yes script is working with out any issues :)
Thanks,
Prathibha
Really appreciate your efforts, I am very thankful.
Yes script is working with out any issues :)
Thanks,
Prathibha
ASKER
Hi Chris,
once script executed, I found below result from the log.
Ideally script should skip below two directories.
Don't find any name for directory Documentation in the log but I can see the directory X_test in the output.
if (($c.Name -ne "Documentation") -and ($c.Name -ne "X_*"))
Could you please explain me on this?
Thanks,
Pra
once script executed, I found below result from the log.
Ideally script should skip below two directories.
Don't find any name for directory Documentation in the log but I can see the directory X_test in the output.
if (($c.Name -ne "Documentation") -and ($c.Name -ne "X_*"))
Could you please explain me on this?
Thanks,
Pra
You're using a literal comparison (ne) with a wildcard, it will only skip it if the directory is exactly "X_*". Use the "notlike" operator instead.
$c.Name -notlike "X_*
ASKER
Sure Chris.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thank you Chris, I am facing some syntactic issues for new script. Old one is working for me in my local.
But I am facing issue while executing it from the Unix based shared folder. SA confirmed me that it has all the 777 permissions.
But I am facing access denied issues for the folders on UNIX based netapp shared folder. Any clue how make it run for the mentioned netapp folder?
Thanks,
Pra
But I am facing issue while executing it from the Unix based shared folder. SA confirmed me that it has all the 777 permissions.
But I am facing access denied issues for the folders on UNIX based netapp shared folder. Any clue how make it run for the mentioned netapp folder?
Thanks,
Pra
ASKER
Error while running : Nothing was removed it is just showing the count in log.
EXCEPTION: Access to the path is denied.
Directory Path: \\testpath\xxx\
EXCEPTION: Access to the path is denied.
Directory Path: \\testpath\xxx\ Files: 2 total, 2 removed
Folders: 1 total, 0 removed
**********************
EXCEPTION: Access to the path is denied.
Directory Path: \\testpath\xxx\
EXCEPTION: Access to the path is denied.
Directory Path: \\testpath\xxx\ Files: 2 total, 2 removed
Folders: 1 total, 0 removed
**********************
Using "exit <number>" in the script as a terminal exit will let you pass error codes back up to the task scheduler.