Windows Profile Backup Script - Access Denied for Desktop Files - powershell

I am using a script I modified slightly to backup user library files. For some reason it can backup all libraries but fails to backup any of the Desktop files.
I've tried running this as various users and on different machines but with the same result.
This is in the latest Powershell version on Windows 10. Perhaps the code has changed since Windows 7? Thanks in advance for any help.
Set-StrictMode -Off
#create directories for backup if needed
$TARGETDIR1 = "c:\temp"
if(!(Test-Path -Path $TARGETDIR1 )){
New-Item -ItemType directory -Path $TARGETDIR1
}
$TARGETDIR2 = "c:\temp\backup"
if(!(Test-Path -Path $TARGETDIR2 )){
New-Item -ItemType directory -Path $TARGETDIR2
}
$TARGETDIR3 = "c:\temp\backup\Download"
if(!(Test-Path -Path $TARGETDIR3 )){
New-Item -ItemType directory -Path $TARGETDIR3
}
$TARGETDIR4 = "c:\temp\backup\Staging"
if(!(Test-Path -Path $TARGETDIR4 )){
New-Item -ItemType directory -Path $TARGETDIR4
}
#Variables, only Change here
$Destination="c:\temp\backup" #Copy the Files to this Location
$Destination="C:\temp\backup\Download"
$Staging="C:\temp\backup\Staging"
$ClearStaging=$true # When $true, Staging Dir will be cleared
$Versions="5" #How many of the last Backups you want to keep
$BackupDirs="$env:USERPROFILE\Desktop", "$env:USERPROFILE\Documents", "$env:USERPROFILE\Downloads", "$env:USERPROFILE\Favorites", "$env:USERPROFILE\Pictures", "$env:USERPROFILE\Videos", "$env:USERPROFILE\OneDrive", "$env:USERPROFILE\Links"#What Folders you want to backup
#commented out for now --tom
$ExcludeDirs="C:\Users\seimi\OneDrive - Seidl Michael\0-Temp\Dir1","C:\Users\seimi\OneDrive - Seidl Michael\0-Temp\Dir2" #This list of Directories will not be copied
$LogName="Log.txt" #Log Name
$LoggingLevel="3" #LoggingLevel only for Output in Powershell Window, 1=smart, 3=Heavy
$Zip=$false #Zip the Backup Destination
$Use7ZIP=$false #Make sure it is installed
$RemoveBackupDestination=$false #Remove copied files after Zip, only if $Zip is true
$UseStaging=$true #only if you use ZIP, than we copy file to Staging, zip it and copy the ZIP to destination, like Staging, and to save NetworkBandwith
#Send Mail Settings
# $SendEmail = $false # = $true if you want to enable send report to e-mail (SMTP send)
# $EmailTo = 'test#domain.com' #user#domain.something (for multiple users use "User01 <user01#example.com>" ,"User02 <user02#example.com>" )
# $EmailFrom = 'from#domain.com' #matthew#domain
# $EmailSMTP = 'smtp.domain.com' #smtp server adress, DNS hostname.
#STOP-no changes from here
#STOP-no changes from here
#Settings - do not change anything from here
$ExcludeString=""
#[string[]]$excludedArray = $ExcludeDirs -split ","
foreach ($Entry in $ExcludeDirs)
{
$Temp="^"+$Entry.Replace("\","\\")
$ExcludeString+=$Temp+"|"
}
$ExcludeString=$ExcludeString.Substring(0,$ExcludeString.Length-1)
#$ExcludeString
[RegEx]$exclude = $ExcludeString
if ($UseStaging -and $Zip)
{
#Logging "INFO" "Use Temp Backup Dir"
$Backupdir=$Staging +"\Backup-"+ (Get-Date -format yyyy-MM-dd)+"-"+(Get-Random -Maximum 100000)+"\"
}
else
{
#Logging "INFO" "Use orig Backup Dir"
$Backupdir=$Destination +"\Backup-"+ (Get-Date -format yyyy-MM-dd)+"-"+(Get-Random -Maximum 100000)+"\"
}
#$BackupdirTemp=$Temp +"\Backup-"+ (Get-Date -format yyyy-MM-dd)+"-"+(Get-Random -Maximum 100000)+"\"
$Log=$Backupdir+$LogName
$Log
$Items=0
$Count=0
$ErrorCount=0
$StartDate=Get-Date #-format dd.MM.yyyy-HH:mm:ss
#FUNCTION
#Logging
Function Logging ($State, $Message) {
$Datum=Get-Date -format dd.MM.yyyy-HH:mm:ss
if (!(Test-Path -Path $Log)) {
New-Item -Path $Log -ItemType File | Out-Null
}
$Text="$Datum - $State"+":"+" $Message"
if ($LoggingLevel -eq "1" -and $Message -notmatch "was copied") {Write-Host $Text}
elseif ($LoggingLevel -eq "3") {Write-Host $Text}
add-Content -Path $Log -Value $Text
}
#Create Backupdir
Function Create-Backupdir {
New-Item -Path $Backupdir -ItemType Directory | Out-Null
sleep -Seconds 5
Logging "INFO" "Create Backupdir $Backupdir"
}
#Delete Backupdir
Function Delete-Backupdir {
$Folder=Get-ChildItem $Destination | where {$_.Attributes -eq "Directory"} | Sort-Object -Property CreationTime -Descending:$false | Select-Object -First 1
Logging "INFO" "Remove Dir: $Folder"
$Folder.FullName | Remove-Item -Recurse -Force
}
#Delete Zip
Function Delete-Zip {
$Zip=Get-ChildItem $Destination | where {$_.Attributes -eq "Archive" -and $_.Extension -eq ".zip"} | Sort-Object -Property CreationTime -Descending:$false | Select-Object -First 1
Logging "INFO" "Remove Zip: $Zip"
$Zip.FullName | Remove-Item -Recurse -Force
}
#Check if Backupdirs and Destination is available
function Check-Dir {
Logging "INFO" "Check if BackupDir and Destination exists"
if (!(Test-Path $BackupDirs)) {
return $false
Logging "Error" "$BackupDirs does not exist"
}
if (!(Test-Path $Destination)) {
return $false
Logging "Error" "$Destination does not exist"
}
}
#Save all the Files
# note - if the folders are empty that are being copied you will see errors
# this shouldn't affect the backup --Tom
Function Make-Backup {
Logging "INFO" "Started the Backup"
$Files=#()
$SumMB=0
$SumItems=0
$SumCount=0
$colItems=0
Logging "INFO" "Count all files and create the Top Level Directories"
}
foreach ($Backup in $BackupDirs) {
$colItems = (Get-ChildItem $Backup -Recurse -File | Where-Object {$_.mode -notmatch "h"} | Measure-Object -property length -sum)
$Items=0
$FilesCount += Get-ChildItem $Backup -Recurse -File | Where-Object {$_.mode -notmatch "h"}
Copy-Item -Path $Backup -Destination $Backupdir -Force -ErrorAction SilentlyContinue
$SumMB+=$colItems.Sum.ToString()
$SumItems+=$colItems.Count
$TotalMB="{0:N2}" -f ($SumMB / 1MB) + " MB of Files"
Logging "INFO" "There are $SumItems Files with $TotalMB to copy"
foreach ($Backup in $BackupDirs) {
$Index=$Backup.LastIndexOf("\")
$SplitBackup=$Backup.substring(0,$Index)
$Files = Get-ChildItem $Backup -Recurse | select * | Where-Object {$_.mode -notmatch "h" -and $_.fullname -notmatch $exclude} | select fullname #$_.mode -notmatch "h" -and
foreach ($File in $Files) {
$restpath = $file.fullname.replace($SplitBackup,"")
try {
Copy-Item $file.fullname $($Backupdir+$restpath) -Force -ErrorAction SilentlyContinue |Out-Null
Logging "INFO" "$file was copied"
}
catch {
$ErrorCount++
Logging "ERROR" "$file returned an error an was not copied"
}
$Items += (Get-item $file.fullname).Length
$status = "Copy file {0} of {1} and copied {3} MB of {4} MB: {2}" -f $count,$SumItems,$file.Name,("{0:N2}" -f ($Items / 1MB)).ToString(),("{0:N2}" -f ($SumMB / 1MB)).ToString()
$Index=[array]::IndexOf($BackupDirs,$Backup)+1
$Text="Copy data Location {0} of {1}" -f $Index ,$BackupDirs.Count
Write-Progress -Activity $Text $status -PercentComplete ($Items / $SumMB*100)
if ($File.Attributes -ne "Directory") {$count++}
}
}
$SumCount+=$Count
$SumTotalMB="{0:N2}" -f ($Items / 1MB) + " MB of Files"
Logging "INFO" "----------------------"
Logging "INFO" "Copied $SumCount files with $SumTotalMB"
Logging "INFO" "$ErrorCount Files could not be copied"
# Send e-mail with reports as attachments
if ($SendEmail -eq $true) {
$EmailSubject = "Backup Email $(get-date -format MM.yyyy)"
$EmailBody = "Backup Script $(get-date -format MM.yyyy) (last Month).`nYours sincerely `Matthew - SYSTEM ADMINISTRATOR"
Logging "INFO" "Sending e-mail to $EmailTo from $EmailFrom (SMTPServer = $EmailSMTP) "
### the attachment is $log
Send-MailMessage -To $EmailTo -From $EmailFrom -Subject $EmailSubject -Body $EmailBody -SmtpServer $EmailSMTP -attachment $Log
}
}
#create Backup Dir
Create-Backupdir
Logging "INFO" "----------------------"
Logging "INFO" "Start the Script"
#Check if Backupdir needs to be cleaned and create Backupdir
$Count=(Get-ChildItem $Destination | where {$_.Attributes -eq "Directory"}).count
Logging "INFO" "Check if there are more than $Versions Directories in the Backupdir"
if ($count -gt $Versions)
{
Delete-Backupdir
}
$CountZip=(Get-ChildItem $Destination | where {$_.Attributes -eq "Archive" -and $_.Extension -eq ".zip"}).count
Logging "INFO" "Check if there are more than $Versions Zip in the Backupdir"
if ($CountZip -gt $Versions) {
Delete-Zip
}
#Check if all Dir are existing and do the Backup
$CheckDir=Check-Dir
if ($CheckDir -eq $false) {
Logging "ERROR" "One of the Directory are not available, Script has stopped"
} else {
Make-Backup
$Enddate=Get-Date #-format dd.MM.yyyy-HH:mm:ss
$span = $EndDate - $StartDate
$Minutes=$span.Minutes
$Seconds=$Span.Seconds
Logging "INFO" "Backupduration $Minutes Minutes and $Seconds Seconds"
Logging "INFO" "----------------------"
Logging "INFO" "----------------------"
if ($Zip)
{
Logging "INFO" "Compress the Backup Destination"
if ($Use7ZIP)
{
Logging "INFO" "Use 7ZIP"
if (-not (test-path "$env:ProgramFiles\7-Zip\7z.exe")) {Logging "WARNING" "7Zip not found"}
set-alias sz "$env:ProgramFiles\7-Zip\7z.exe"
#sz a -t7z "$directory\$zipfile" "$directory\$name"
if ($UseStaging -and $Zip)
{
$Zip=$Staging+("\"+$Backupdir.Replace($Staging,'').Replace('\','')+".zip")
sz a -t7z $Zip $Backupdir
Logging "INFO" "Move Zip to Destination"
Move-Item -Path $Zip -Destination $Destination
if ($ClearStaging)
{
Logging "INFO" "Clear Staging"
Get-ChildItem -Path $Staging -Recurse -Force | remove-item -Confirm:$false -Recurse
}
}
else
{
sz a -t7z ($Destination+("\"+$Backupdir.Replace($Destination,'').Replace('\','')+".zip")) $Backupdir
}
}
else
{
Logging "INFO" "Use Powershell Compress-Archive"
Compress-Archive -Path $Backupdir -DestinationPath ($Destination+("\"+$Backupdir.Replace($Destination,'').Replace('\','')+".zip")) -CompressionLevel Optimal -Force
}
If ($RemoveBackupDestination)
{
Logging "INFO" "Backupduration $Minutes Minutes and $Seconds Seconds"
#Remove-Item -Path $BackupDir -Force -Recurse
get-childitem -Path $BackupDir -recurse -Force | remove-item -Confirm:$false -Recurse
get-item -Path $BackupDir | remove-item -Confirm:$false -Recurse
}
}
}
Write-Host "Press any key to close ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
The output of the log file shows the failure here:
03.05.2019-15:01:04 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\Microsoft Edge.lnk} returned an error an was not copied
03.05.2019-15:01:04 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\Microsoft Teams.lnk} returned an error an was not copied
03.05.2019-15:01:04 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\PRMS Multi-Session.lnk} returned an error an was not copied
03.05.2019-15:01:04 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\PRMS.lnk} returned an error an was not copied
Here is the output Powershell shows
03.05.2019-15:36:07 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\desktop.ini} returned an error an was not copied
03.05.2019-15:36:07 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\REDACTED Logos & Documents.lnk} returned an error an was not copied
03.05.2019-15:36:07 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\REDACTED VPN - Shortcut.lnk} returned an error an was not copied
03.05.2019-15:36:07 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\REDACTED_DigitalNET (J) - Shortcut.lnk} returned an error an was not copied
03.05.2019-15:36:07 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\REDACTED_Sales (S) - Shortcut.lnk} returned an error an was not copied
03.05.2019-15:36:07 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\Slack.lnk} returned an error an was not copied
03.05.2019-15:36:07 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\REDACTED (U) - Shortcut.lnk} returned an error an was not copied
03.05.2019-15:36:07 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\Visual Studio 2019.lnk} returned an error an was not copied
03.05.2019-15:36:07 - INFO: #{FullName=C:\Users\REDACTED\Documents\ConnectWiseControl} was copied
03.05.2019-15:36:07 - INFO: #{FullName=C:\Users\REDACTED\Documents\OneNote Notebooks} was copied
03.05.2019-15:36:07 - INFO: #{FullName=C:\Users\REDACTED\Documents\Visual Studio 2019} was copied

Related

PowerShell Event Viewer Errors

I am running a PowerShell script which I have a list of IDs in a text file that matches to files on a server and then Robocopy copies them to other servers. Recently a file that is present on a server doesn't get copied to 1 out of 2 destinations. The weird thing is it only happens approximately 10 files out of 500.
I am seeing weird errors in EventViewer. Would this cause the issue?
Event ID 400 Engine state is changed from None to Available.
Details: NewEngineState=Available PreviousEngineState=None
Event ID 403
Engine state is changed from Available to Stopped.
Details: NewEngineState=Stopped PreviousEngineState=Available
Changing copy-item to robocopy in the scripts
$CC="S:\CC 2019"
$Daily_Results="S:\~Copy_Move Daily Results\"
$Missing_Files = "S:\~Missing Files\Results\"
$Lab = "\\********\E-Drive\Logs\Files"
$Source = "S:\"
foreach ($ID in Get-Content 'S:\~Master CSC Location Files\CC_Listings.txt') {
$ID
$Count=0
Get-ChildItem -Path $Source -ErrorAction SilentlyContinue | where {$_.name -match $ID} |foreach {
$Path="S:\"+$_.name
Robocopy $Source $Lab $_.name /COPY:DAT /IS
Robocopy $Source $CC $_.name /MOV /IS
Write-Host $_.name
"File copied"
Write-Output $ID "File copied" | Out-File $Daily_Results\$(get-date -f yyyy-MM-dd)_CC_CopyMove_Results.txt -append
Write-Output $_.name | Out-File $Daily_Results\$(get-date -f yyyy-MM-dd)_CC_CopyMove_Results.txt -append
$Count++
}
If($Count –eq 0){
Write-Host $ID "No File Found"
Write-Output $ID "No File Found at $(get-date -f hh:mm:ss)" | Out-File $Missing_Files\$(get-date -f yyyy-MM-dd)_CC_Missing_Files_Results.txt -append
}
}

Delete user profiles with powershell

I'm trying to create a powershell script that deletes user profiles older than 30 days with powershell and excluding some users like admins accounts.
I've though maybe the script has to be signed by the domaincontroller or something, but i'm not sure if that will be the solution.
When i try to run it on a other directory it works but when i use it on c:\Users i get an error
Does anyone know what i have to change?
Error:
Set-ExecutionPolicy : Windows PowerShell updated your execution policy successfully, but the setting is overridden by a
policy defined at a more specific scope. Due to the override, your shell will retain its current effective execution
policy of RemoteSigned. Type "Get-ExecutionPolicy -List" to view your execution policy settings. For more information p
lease see "Get-Help Set-ExecutionPolicy".
At line:1 char:46
+ ... -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & 'H ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (:) [Set-ExecutionPolicy], SecurityException
+ FullyQualifiedErrorId : ExecutionPolicyOverride,Microsoft.PowerShell.Commands.SetExecutionPolicyCommand
The Code:
$Now = Get-Date
$Days = "15"
$TargetFolder = "C:\Users"
$LastWrite = $Now.AddDays(-$Days)
$Folders = get-childitem -path $TargetFolder |
Where {$_.psIsContainer -eq $true} |
Where {$_.LastWriteTime -le "$LastWrite"}
foreach ($Folder in $Folders)
{
if($Folder -notlike "user1")
{
if($Folder -notlike "Administrator")
{
if($Folder -notlike "user2")
{
if($Folder -notlike "Public")
{
if($Folder -notlike "NetworkService")
{
if($Folder -notlike "LocalService")
{
if($Folder -notlike "user3")
{
if($Folder -notlike "user4")
{
write-host "Deleting $Folder" -ForegroundColor Green
Remove-Item -recurse -Force C:\Users\$Folder
#Write-Host -NoNewLine "Press any key to continue... `n";
#$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown");
}
else
{
write-host "Cannot delete $Folder" -ForegroundColor Red
}
}
else
{
write-host "Cannot delete $Folder" -ForegroundColor Red
}
}
else
{
write-host "Cannot delete $Folder" -ForegroundColor Red
}
}
else
{
write-host "Cannot delete $Folder" -ForegroundColor Red
}
}
else
{
write-host "Cannot delete $Folder" -ForegroundColor Red
}
}
else
{
write-host "Cannot delete $Folder" -ForegroundColor Red
}
}
else
{
write-host "Cannot delete $Folder" -ForegroundColor Red
}
}
else
{
write-host "Cannot delete $Folder" -ForegroundColor Red
}
}
Here is my script which I have used sometime ago:
Most code is commented, so that should be clear. If you have any questions please ask.
# ********************************************************************************************************(**
# * **
# * Short description: Check profiles if they can be deleted - unused profiles will be deleted. **
# * Full description: * User running this script can specify the time which will check if profile contains **
# * any newer files than limit. If yes such profile is skipped. **
# * * User can specify which directories will be excepted from this search **
# * * User can specify which file suffixes will be ignored when the date will be checked **
# * * User can specify custom path for the profiles **
# * **
# * Creator : Patrik Svestka **
# * Created : 21/08/2017 **
# * Version : 1.0.1 **
# * **
# * Changes description: 1.0.0 - First Public version - Init release **
# * 1.0.1 - Added license type, minor changes to the header **
# * **
# * PowerShell compatibility: 2.0 , 4.0 and probably newer (untested) **
# * PowerShell tested versions: v2.0.50727, v4.0.30319 **
# * **
# * License: MIT **
# * **
# * TODO: ability to run the script remotely **
# to test remote connection - Get-WmiObject -ComputerName <server_name> Win32_Service -Credential $credentials
# Or manually from PowerShellEnter-PSSession <server_name> -Credential domain\<user_id>
# ***********************************************************************************************************
# **********************************************************
# Test run?
# **********************************************************
# when you want to test what will be deleted
$test_run = $true;
If ($test_run) {
Write-Warning -message 'Test run ENABLED - for actual DELETION set $test_run to $false' -verbose;
"`n";"`n";
}
# **********************************************************
# User configuration
# **********************************************************
# $credentials = 'domain\<user_id>';
# $server_name = '<server>';
# Profiles that contain file newer than 90 days will be exempted from deletion
$time_definition=#{'1m'="-0"};
# TODO: test for more periods - not tested yet!
# e.g more time frames - $time_definition=#{'1m'="-30"; '3m'="-90"; '6m'="-180"; '12m'="-360"; '18m'="-540"}
# running script path
$current_path = (Resolve-Path .\).Path;
$log_file = "$($current_path)\delete_files.log";
$folder_to_cleanse = 'E:\t\temp_profiles\'; #'C:\prg'
$excluded_directories = [System.Collections.ArrayList]#();
# All excluded profiles:
$excluded_directories.Add('All Users') | Out-null;
$excluded_directories.Add('Administrator') | Out-null;
$excluded_directories.Add('Default User') | Out-null;
$excluded_directories.Add('LocalService') | Out-null;
$excluded_directories.Add('NetworkService') | Out-null;
# Extensions excluded from date validation - these files will not influence the date check
# (will be deleted too if all others are found older)
$excluded_file_types = [System.Collections.ArrayList]#();
#$excluded_file_types.Add("*.bat", "*.cmd", "*.ps1") | Out-null;
$profile_directories = [System.Collections.ArrayList]#();
# **********************************************************
# The script's start
# **********************************************************
$newer_file_exist = $Null;
$files_to_delete = $Null;
# If previous log file exists delete it (only during test run)
If ((Test-Path -Path "$log_file") -and ($test_run)) {
Write-Verbose "Deleting previous log file $log_file." -verbose;
Remove-Item $log_file
}
# get all directories except excluded ones
$profile_directories = Get-ChildItem -Path $folder_to_cleanse -exclude $excluded_directories | Where-Object {$_.PSIsContainer -eq $True} | % { $_.Name }
# if $profile_directories found to be deleted => exit
If ([String]::IsNullOrEmpty($profile_directories)) {
Write-Warning -message "No profile directories to delete. Exiting." -verbose;
Exit;
}
# search in profile directories that are left after exclusion
# for all periods defined in time_definition
ForEach ($profile in $profile_directories) {
ForEach ($time in $time_definition.GetEnumerator()) {
Write-Verbose -message "Now processing the following profile: $folder_to_cleanse$profile." -verbose;
$test_current_pathPath = Test-Path -Path "$folder_to_cleanse$profile";
If ($test_current_pathPath) {
# check if any newer than $time_definition are present within the profile structure
# LastAccesstime can be empty! It is better, less issues, to use LastWriteTime. If you must use LastAccessTime use a check for ::IsNullOrEmpty
# LastWriteTime must be greater than current day - $time.Name (e.g. -90 days)
$newer_file_exist += Get-ChildItem -Path "$folder_to_cleanse$profile" -recurse -Force -exclude $excluded_file_types | Where-Object {$_.PSIsContainer -eq $FALSE} | where {($_.LastWriteTime).ToString('yyyy-MM-dd') -gt (get-date).adddays($time_definition.$($time.Name)).ToString('yyyy-MM-dd')};
}
# if any new file than the limit found the whole profile directory will be skipped (testing if $newer_file_exist $null)
If ($newer_file_exist) {
# add the top directory into excluded directory
$excluded_directories.Add($profile) | Out-null;
$newer_file_exist=$Null;
Write-Verbose -message "The profile $profile will be excluded from deletion process." -verbose;
continue;
}
}
}
# excluding the directories with newer files than limit defined by user
$profiles_with_path = Get-ChildItem -Path $folder_to_cleanse -exclude $excluded_directories | Where-Object {$_.PSIsContainer -eq $True}
# perhaps all $directories are now excluded?
If ([String]::IsNullOrEmpty($profiles_with_path)) {
Write-Warning -message "No directories to delete all probably filtered. Exiting." -verbose;
Exit;
}
# get all files to be deleted
ForEach ($dir in $profiles_with_path) {
# to check
$test_current_pathPath = Test-Path -Path $dir
If ($test_current_pathPath) {
#write-host 'Currently writing for these months:'$($time.Name);
$files_to_delete += Get-ChildItem -Path $dir -recurse -Force | Where-Object {$_.PSIsContainer -eq $FALSE} | % { $_.FullName }
}
}
# **********************************************************
# Messages for the user
# **********************************************************
Write-Verbose -message "List of profiles to be deleted:" -verbose;
ForEach ($profile_to_delete in $profiles_with_path) {
Write-Verbose -message "$profile_to_delete`n" -verbose;
}
Write-Verbose -message "The total count of non-excluded profile directories: $($profiles_with_path.Count)" -verbose;
Write-Verbose -message "==========================`n`n" -verbose;
Write-Verbose -message "List of excluded directories:`n" -verbose;
ForEach ($excluded_profile in $excluded_directories) {
Write-Verbose -message "$folder_to_cleanse$excluded_profile`n" -verbose;
}
Write-Verbose -message "Total count of excluded directories: $($excluded_directories.Count)" -verbose;
Write-Verbose -message "==========================`n`n" -verbose;
Write-Verbose -message "Total directory count (both to be deleted and excluded): $($($profiles_with_path.Count)+ $($excluded_directories.Count))`n" -verbose;
# **********************************************************
# Test run or actual deletion process
# **********************************************************
If ($test_run) {
ForEach ($file in $files_to_delete) {
$file | Out-file -Encoding 'Unicode' -FilePath $log_file -Append # >> $log_file
}
Write-Verbose 'This number of files would be deleted:' -verbose;
Write-Verbose "Found $($files_to_delete.Count) files marked for deletion." -verbose;
} Else {
$files_deleted = 0;
# delete files
If ($files_to_delete) {
ForEach ($file in $files_to_delete) {
#Remove-Item $file -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item $file -Force -ErrorAction SilentlyContinue
If ($? -eq $true) {
$files_deleted ++;
#Write-Verbose -Verbose "$File deleted successfully!"
}
}
}
# delete directories
$directories_deleted = 0;
ForEach ($dir in $profiles_with_path) { #
Remove-Item $dir -Recurse -Force -ErrorAction SilentlyContinue
If ($? -eq $true) {
$directories_deleted ++;
#Write-Verbose -Verbose "$File deleted successfully!"
}
}
Return "Total files to be deleted: $($files_to_delete.count)","Total files Deleted: $files_deleted", "Total Directories deleted: $directories_deleted"
}

Adding files to archive

I have a script that zips up all files and folders inside a Source folder, and copies them to the Destination folder, then deletes them.
I have added error logging as well.
I am a newbie at Powershell, and although the script works most of the time, some times it does not add the files to the archive, and of course deletes it afterwards so I have no record.
The error logging does not catch this
$Log = "c:\support\scripts\CommsLogArchiveDMLog.txt"
$DestZip="D:\SDM\Fltctrl\MsgBackup\"
$Source = "D:\SDM\Fltctrl\Msglog\ANZ\"
$folder = Get-Item -Path $Source
$ZipTimestamp = Get-Date -format yyyyMMdd-HHmmss;
$ZipFileName = $DestZip + $ZipTimestamp + "_Comms" + ".zip"
$Source
write-output "" >> $Log
write-output $ZipTimestamp >> $Log
Write-output "... Waiting for the zip file to be created" >> $Log
Try
{
set-content $ZipFileName ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
while (!(Test-Path -PathType leaf -Path $ZipFileName))
{
Start-Sleep -s 20
}
}
catch
{
Write-Output "Ran into an issue: $($PSItem.ToString())" >> $Log
}
Try
{
$ZipFile = (new-object -com shell.application).NameSpace($ZipFileName)
}
catch
{
Write-Output "Ran into an issue: $($PSItem.ToString())" >> $Log
}
Write-Output "... Zip file created" >> $Log
Start-Sleep -s 10
write-output "... Adding files to archive" >> $Log
Try
{
$ZipFile.CopyHere($Source)
}
catch
{
Write-Output "Ran into an issue: $($PSItem.ToString())" >> $Log
}
Try
{
$ZipFileName
}
catch
{
Write-Output "Ran into an issue: $($PSItem.ToString())" >> $Log
}
write-output "... Successfully added files to archive" >> $Log
Start-Sleep -s 10
write-output "... Deleting source files" >> $Log
Try
{
Get-ChildItem -Path $Source -Recurse -force |
Where-Object { -not ($_.psiscontainer) } |
Remove-Item –Force
}
catch
{
Write-Output "Ran into an issue: $($PSItem.ToString())" >> $Log
}
write-output "... Successfully deleted source files" >> $Log
Any suggestions o how to get this working as expected would be much appreciated.
Ideally I would like the files to only be deleted if it has been added to the archive successfully.
You should try using the Compress-Archive function. I've never used it before, but it could make your code a little cleaner. Here is what I came up with, but it is untested:
[CmdletBinding(SupportsShouldProcess = $true)]
param (
$Source = "D:\SDM\Fltctrl\Msglog\ANZ\",
$Destination = "D:\SDM\Fltctrl\MsgBackup\",
$Log = "c:\support\scripts\CommsLogArchiveDMLog.txt"
)
function Log ( [String] $Message ) {
Write-Verbose -Message $Message
if ( $Log )
{
"$(Get-Date -Format yyyyMMdd-HHmmss): $Message" | Add-Content $Log
}
}
# Generate .zip filename
$ArchiveFilePath = Join-Path -Path $Destination -ChildPath "$(Get-Date -Format yyyyMMdd-HHmmss)_Comms.zip"
Log -Message "Destination archive filepath: $ArchiveFilePath"
# Compress files
try
{
Compress-Archive -Path $Source -DestinationPath $ArchiveFilePath -CompressionLevel Optimal
}
catch
{
Log -Message "An error occurred creating archive: $($_.ToSTring()) Terminating script."
throw $_
}
# Remove source files
try
{
Get-ChildItem -Path $Source -Recurse -force `
| Where-Object -Property PSIsContainer -EQ -Value $false `
| ForEach-Object `
-Begin { Log -Message "Removing file(s) from $Source"; $Count = 1 } `
-Process {
Log -Message "Removing item: $($_.FullName)"
$_ | Remove-Item -Force
$Count ++
} `
-End { Log -Message "Removed $Count file(s) from $Source" }
}
catch
{
Log -Message "An error occurred removing files: $($_.ToSTring()) Terminating script"
throw $_
}

Unable to delete zip folders older than 14 days

I am unable to delete zip folders older than 14 days from a directory. The rest of my script works fine, however the following code block is failing:
It has not thrown any errors, the path has been sanity checked, however, I placed old documents in to see if they are cleared up to no avail. It prints the statement that the folder path exists however does not delete anything from the folder.
if (!(Test-Path $folderpath)) {
New-Item -ItemType Directory -Path $folderpath
Write-Host "$folderpath created"
} else {
Write-Host "$folderpath already exists, will remove old items"
$HowOld = -14
Get-ChildItem $Path -Recurse |
where {$_.LastWriteTime -lt (Get-Date).AddDays($HowOld) -and -not $_.PSIsContainer} |
% {Remove-Item $_.FullName -Force -WhatIf}
}
Here is the full script for completeness:
#Get backup folder drive letter
$letter = [System.IO.DriveInfo]::getdrives() | Where-Object {$_.DriveType -eq 'Fixed' -and $_.Name -notlike '*C*'} | Select-Object -Property Name
[string] $drive = "$letter"
$Drive2 = $null
$Drive2 = $drive.Substring($drive.IndexOf('=')+1)
$BackupDrive = $Drive2.Substring(0, $Drive2.IndexOf('}'))
#Check the programname log path.
$logspath = "C:\ProgramData\programname\programname4.0\Logs"
If (!(test-path $logspath))
{
$IQlogspath = "C:\ProgramData\programname\iQSonar4.0\Logs"
}
Else
{
$IQlogspath = "C:\ProgramData\programname\programname4.0\Logs"
}
#check if backup folder exists, clean if exists and if not create it.
$folderpath = $BackupDrive + "programname_logs"
If(!(test-path $folderpath))
{
New-Item -ItemType Directory -Path $folderpath
write-host "$folderpath created"
}
Else
{
write-host "$folderpath already exists, will remove old items"
$HowOld = -14
get-childitem $Path -recurse | where {$_.lastwritetime -lt (get-date).adddays($HowOld) -and -not $_.psiscontainer} |% {remove-item $_.fullname -force -whatif}
}
#check if todays folder exists, if not create it
$todaysdate = (Get-Date).ToString('dd-MM-yyyy')
$todaysbackup = $folderpath + "\Logs_Backup_" + $todaysdate
$todaysbackupzip = $todaysbackup + ".zip"
If(!(test-path $todaysbackup))
{
New-Item -ItemType Directory -Path $todaysbackup
write-host "$todaysbackup created, now moving items"
#select and move files to backup folder
get-childitem -Path $IQlogspath |
where-object {$_.LastWriteTime -lt (get-date).AddDays(-7) -and $_.Name -notmatch "Service"} |
move-item -destination $todaysbackup
Start-Sleep -s 10
write-host "checking for zip"
If(Test-path $todaysbackupzip) {
write-host "$todaysbackupzip already exists, changing name"
$todaysbackupzip = $null
$todaysbackupzip = $folderpath + "\Logs_Backup_" + $todaysdate + ".re-run" + ".zip"
Add-Type -assembly "system.io.compression.filesystem"
[io.compression.zipfile]::CreateFromDirectory($todaysbackup, $todaysbackupzip)
write-host "$todaysbackupzip created"
Remove-Item -Recurse -Force $todaysbackup
write-host "$todaysbackup removed"
exit
}
write-host "creating zip folder, $todaysbackupzip"
Add-Type -assembly "system.io.compression.filesystem"
[io.compression.zipfile]::CreateFromDirectory($todaysbackup, $todaysbackupzip)
write-host "$todaysbackupzip created"
Remove-Item -Recurse -Force $todaysbackup
write-host "$todaysbackup removed"
exit
}
Else
{
write-host "$todaysbackup already exists, attempting to zip"
#check if zip backup folder already exists
If(Test-path $todaysbackupzip) {
write-host "$todaysbackupzip already exists, changing name"
$todaysbackupzip = $null
$todaysbackupzip = $folderpath + "\Logs_Backup_" + $todaysdate + ".re-run" + ".zip"
[io.compression.zipfile]::CreateFromDirectory($todaysbackup, $todaysbackupzip)
write-host "$todaysbackupzip created"
Remove-Item -Recurse -Force $todaysbackup
write-host "$todaysbackup removed"
exit
}
Else
{
Start-Sleep -s 10
write-host "creating zip folder, $todaysbackupzip"
Add-Type -assembly "system.io.compression.filesystem"
[io.compression.zipfile]::CreateFromDirectory($todaysbackup, $todaysbackupzip)
write-host "$todaysbackupzip created"
Remove-Item -Recurse -Force $todaysbackup
write-host "$todaysbackup removed"
exit
}
}
#Get OS disk label
$OSDisk = Get-WmiObject Win32_OperatingSystem | Select-Object WindowsDirectory
[string] $drive = "$OSDisk"
$Drive2 = $null
$Drive2 = $drive.Substring($drive.IndexOf('=')+1)
$OSDrive = $Drive2.Substring(0, $Drive2.IndexOf('\'))
$OSDrive2 = "'$OSDrive'"
$disk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID=$OSDrive2"| Select-Object FreeSpace
[INT] $FreeSpace = $disk.FreeSpace /1GB
If ($FreeSpace -gt 5) {
write-host "no additional backup requirement, exiting script"
exit
}
Else {
write-host "Running one off clear"
$OneOff = $IQlogspath + "\Logs_One_Off_" + $todaysdate
$OneOffZip = $OneOff + ".zip"
If(!(test-path $OneOff))
{
New-Item -ItemType Directory -Path $OneOff
write-host "$OneOff created"
}
Else {
write-host "folder already exists"
}
#select and move files to backup folder
write-host "moving logs to $OneOff"
get-childitem -Path $IQlogspath |
where-object {$_.Name -notmatch "Service"} |
move-item -destination $OneOff
Start-Sleep -s 10
write-host "creating zip folder, $todaysbackupzip"
Add-Type -assembly "system.io.compression.filesystem"
[io.compression.zipfile]::CreateFromDirectory($OneOff, $OneOffZip)
write-host "$todaysbackupzip created"
Remove-Item -Recurse -Force $todaysbackup
write-host "$todaysbackup removed"
exit
}

PowerShell Move-Item $filename

I searched, i googled.. about to smash my head on the table
how come this will not work?
move-Item $path$file $targetdir
it gives me an error
Move-Item : An object at the specified path C:\Repository\test.csv
does not exist.
now if i debug this and i output using
write-output move-Item $path$file $targetdir
and take that output and paste it (file name with path and destination) it works!
and trust me the file is there. =\
Code below
$path = 'C:\test\'
$TimeStamp = Get-Date -Format "MM-dd-yyyy_hh-mm-ss"
$LogFile = Get-Date -Format "MM_dd_yyyy"
$targetdir = "C:\test\Uploaded\"
#Get-ChildItem -path $path\* -Include *.csv | foreach-object {$_.Fullname} | Format-Table name -hidetableheaders | Out-File $path\list.txt
Get-ChildItem -path $path\* -Include *.csv | Format-Table name -hidetableheaders | Out-File $path\list2.txt
get-content C:\test\list2.txt | where {$_ -ne ""} | out-file C:\test\list.txt
Remove-Item C:\test\list2.txt
$list = get-content C:\test\list.txt
foreach ($file in $list)
{
$ftp = "ftp://REMOVED/$file"
"ftp url: $ftp"
$webclient = New-Object System.Net.WebClient
$uri = New-Object System.Uri($ftp)
"Uploading $file..."
$succeeded = $true;
& {
trap { $script:succeeded = $false; continue }
$webclient.UploadFile($uri, $path+$file)
}
if ($succeeded)
{
echo $file 'Was successfully uploaded!' $Timestamp >> logfile$LogFile.log
move-Item -path $path$file -destination $targetdir
#test-path $path$file
}
else
{
echo $file 'Was not successfully uploaded, will retry later' $Timestamp >> logfile$LogFile.log
}
}
exit
Basics are:
Test-Path before you move it (file and destination)
Move the file, ensure you have permission (force it to move)
so:
echo $targetdir
echo "$path$file"
if (!(Test-Path $targetdir)) {
New-Item -ItemType directory $targetdir
}
if(Test-Path "$path$file") {
Move-Item "$path$file" $targetdir -Force
} else {
echo "file does not exist"
}
If you loop over a collection you have to use the ".FullName" property of the object:
Get-ChildItem $path | ForEach-Object { Move-Item $_.FullName $targetdir -Force }
Does the target directory already exist? I believe Move-Item will fail if the target directory doesn't exist. If that's the case, you can simply test for existence of the directory beforehand and then create as necessary.
If (!(Test-Path -Path $targetdir)) {
New-Item -ItemType directory -Path $targetdir
}
This worked for me. Thank you #TheMadTechnician. Hopes this helps everyone
$TimeStamp = Get-Date -Format "MM-dd-yyyy_hh-mm-ss"
$LogFile = Get-Date -Format "MM_dd_yyyy"
$path='C:\test\'
$targetDir = 'C:\test\Uploaded\'
$fileList = Get-ChildItem $path*.csv
If(!(Test-Path $TargetDir)){New-Item -ItemType Directory -Path $TargetDir|Out-Null}
$fileList | Select -ExpandProperty Name | Out-File 'C:\test\list.txt'
$list = get-content C:\test\list.txt
foreach ($file in $list)
{
$ftp = "ftp://REMOVED/$file"
"ftp url: $ftp"
$webclient = New-Object System.Net.WebClient
$uri = New-Object System.Uri($ftp)
"Uploading $file..."
$succeeded = $true;
& {
trap { $script:succeeded = $false; continue }
$webclient.UploadFile($uri, $path+$file)
}
if ($succeeded)
{
echo $file 'Was successfully uploaded!' $Timestamp >> logfile$LogFile.log
move-Item -path $path$file -destination $targetdir$Timestamp"_"$file
#test-path $path$file
}
else
{
echo $file 'Was not successfully uploaded, will retry later' $Timestamp >> logfile$LogFile.log
}
}
exit
How about this then:
ForEach($File in $List){
Join-Path $path $file | Move-Item -Dest $Targetdir
}
Edit: Also... your creation of list.txt, it bothered me so I had to comment. Format-Table should be used for formatting text, not for selecting a value to output to a file. There's a better way to do that, consider this alternative:
Get-ChildItem "$path*.csv" | Select -ExpandProperty Name | Out-File $pathlist.txt
Since you say that $path = 'C:\test\' you are adding extra backslashes in there that may cause issues for some commands.
Edit2: Ok, if that doesn't work, why not work with the files themselves instead of outputting to a file, importing from that file, and then working with things.
$path='c:\test\'
$TargetDir = 'c:\test\NewDir'
$FileList = Get-ChildItem $path*.csv
If(!(Test-Path $TargetDir)){New-Item -ItemType Directory -Path $TargetDir|Out-Null}
$FileList | Move-Item -Destination $TargetDir
Then if you really want a list of those file names just pipe $FileList to Select and then to Out-File
$FileList | Select -ExpandProperty Name | Out-File 'C:\Test\list.txt'
Here, look through this and see if there's anything you like. I made a few changes, such as declaring paths at the beginning for everything, I moved the WebClient object creation outside of the loop, and changed how things are displayed on screen. Plus I skip the entire exporting to text file and re-importing it.
$path = 'C:\test'
$ftpaddr = 'ftp://ftp.example.com/uploads'
$TimeStamp = Get-Date -Format "MM/dd/yyyy hh:mm:ss tt"
$LogFile = Get-Date -Format "MM_dd_yyyy"
$LogDir = "C:\Test\Logs"
If(!(test-path $LogDir)){New-Item -ItemType Directory -Path $LogDir | Out-Null}
$targetdir = 'C:\test\Uploaded'
If(!(test-path $targetdir)){New-Item -ItemType Directory -Path $targetdir | Out-Null}
$list = Get-ChildItem -path $path\* -Include *.csv
$webclient = New-Object System.Net.WebClient
"ftp url: $ftpaddr"
foreach ($file in ($list|select -ExpandProperty Name))
{
$uri = New-Object System.Uri(("$ftpaddr/$file"))
Write-Host "Uploading $file... " -NoNewline -ForegroundColor White
$succeeded = $true
& {
trap { $script:succeeded = $false; continue }
$webclient.UploadFile($uri, "$Path\$file")
}
if ($succeeded)
{
Write-Host "Success!" -ForegroundColor Green
"$Timestamp`t$File was successfully uploaded!" | Out-File "$logdir\logfile$LogFile.log" -Append
move-Item -path "$path\$file" -destination $targetdir
}
else
{
Write-Host "Failed! Will retry later." -ForegroundColor Red
"$Timestamp`t$File was not successfully uploaded, will retry later" | Out-File "$logdir\logfile$LogFile.log" -Append
}
}