UnauthorizedAccessException using Copy-Item on remote fileserver - powershell

I'm trying to copy about 10 folders each containing a ~3KB .txt file onto a remote fileshare with some seconds latency. I'm using Powershells Copy-Item like this:
try
{
Copy-Item -Path $source -Destination $destination -Recurse -ErrorAction Stop
}
catch
{
Write-Error $_.Exception.ToString()
}
The user running the script has read, write and execute permissions on the fileserver share and on the local source.
On first run, the destination folder is empty. Everything works fine.
On second run, the files and folders already exist. So before running the code above I first run a check using Test-Path and in case the folder exists a delete using Remove-Item like this:
try
{
if(Test-Path -Path $path -ErrorAction Stop)
{
Remove-Item -Recurse -Path $path -ErrorAction Stop
}
}
catch
{
Write-Error $_.Exception.ToString()
}
Nobody else edits those files. However, when running the script a dozent times, once in a while, for a reason I don't understand, i'm suddenly getting UnauthorizedAccessException errors for some of the folders while copying. The exact error is:
System.UnauthorizedAccessException: access denied
---> System.ComponentModel.Win32Exception: access denied
in Microsoft.PowerShell.Commands.FileSystemProvider.NativeDirectoryExists(String
path) in
System.Management.Automation.SessionStateInternal.IsItemContainer(CmdletProvider
providerInstance, String path, CmdletProviderContext context
please note: I'm getting those errors AFTER the deletion of the old files on the remote fileserver has compleated successfully.

This is a years old post but maybe one can benefit from that. You don't have to remove beforehand. You can just use -Force to override existing files.
try
{
Copy-Item -Path $source -Destination $destination -Recurse -ErrorAction Stop -Force
}
catch
{
Write-Error $_.Exception.ToString()
}

You may need try to run the command line as Administrator.

Masi, Powershell copy-item function is not really that great IMO. Why not use robocopy/Powershell hybrid here?
Example:
$source = "C:\temp"
$destination ="\\\RemoteServer\Temp"
robocopy $source $destination /s /mt:8

Related

PowerShell Remove-Item return error even if set to SilentlyContinue

I have a PowerShell script to execute a deployment of our application. At one point I want to delete a file to clean stuff up so I have this snippet :
try {
# More code here
}
finally
{
if (Test-Path $tmpFile -PathType Leaf) {
Remove-Item $tmpFile -ErrorAction SilentlyContinue
# I also tried to command from another Stack post, as shown in the PowerShell Screenshot
# Remove-Item $tmpFile -EV Err -EA SilentlyContinue
}
}
Two problems happen now... It says the file doesn't exist even though it does. (the Test-Path returned true). Also, the script doesn't continue even though it's set to SilentlyContinue.
I feel like the problem might be due to the shortpath, but PowerShell can resolve it with no issue.
Does anyone knows how to fix it so it can delete the file... or just not emit an error?
Edit :
This is because of the TEMP directory location.
A better fix would be to change the path of the environment variable "TEMP" and "TMP" to something like c:\temp
Source :
https://superuser.com/questions/1524767/powershell-uses-the-short-8-3-form-for-envtemp
When I wrote this post, I thought that the issue might be the shortpath... so I decided to change my script like so :
finally
{
$fullTmpFile = (Get-Item -LiteralPath $tmpFile).FullName
if (Test-Path $fullTmpFile -PathType Leaf) {
Remove-Item $fullTmpFile -ErrorAction SilentlyContinue
}
}
And it's working perfectly. PowerShell and shortpath = bad.

Check if file exists, then move it

I'm trying to write a few lines of code in powershell, to check if a file arrived to a specific folder. If the file is there, copy it to another folder. No action required if the file is not there. So far I have only the copying part:
cd C:\
Move /y "C:\myfolder\*.csv" "C:\MyDestinationFolder"
I can't find a simple code to check if the file is present.
Maybe you can use this:
$SourceFile = "C:\source\file.txt"
$Destination = "C:\destination\"
if(Test-Path -Path $SourceFile)
{
Copy-Item -Path $SourceFile -Destination $Destination
}
try this :
move-Item "C:\myfolder\*.csv" "C:\MyDestinationFolder" -Force -ErrorAction SilentlyContinue

Test a Path and a File (Nested IFs)

Long day, might be missing something obvious, but the nested IF statements below should work. Any suggestions?
Basically, what I am trying to do:
Take a given hostname (this will later on be incorporated into a loop).
Take a log file and move it from one location to another (location is always constant).
2A. Test IF the folder exists:
2A-1. If the folder exists, test if the file is in the folder.
2A-1a. True: Delete the file
2A-1b. False: Copy the file to the folder.
2A-2. Else: Copy the file to the folder.
2B. ELSE:
2B-1. Create the folder.
2B-2. Copy the file to the folder
I did the below:
$Computer = "hostName"
Enter-PSSession -ComputerName $($Computer)
$LogFileName = "program_" + $Computer + ".log"
$LogFilePath = "\\$Computer\C$\users\$env:USERNAME\desktop\$LogFileName"
$DestPath = "\\$Computer\C$\users\$env:USERNAME\ProgramTest\"
$LogCopy = "programCopy_" + $Computer + ".log"
IF(Test-Path $($DestPath)){
If(Test-Path "$DestPath\$LogCopy"){
Remove-Item "$DestPath\$LogCopy"
Copy-Item $($LogFilePath) $($DestPath)
}
Else{
Copy-Item $($LogFilePath) $($DestPath)
}
ELSE{
New-Item -ItemType directory -Path $($DestPath)
Copy-Item $($LogFilePath) $($DestPath)
}
}
I see you have already accepted an answer but I wanted to offer and improvement on the logic. The nested if's, while do work, have some redundancies in them. Assuming I understand your intention...
# If the folder does not exist create it. If it does move on
If(!(Test-Path $DestPath)){New-Item -ItemType directory -Path $DestPath}
# If the log file already exists. Remove It.
If(Test-Path "$DestPath\$LogCopy"){Remove-Item "$DestPath\$LogCopy"}
# Regardless of what happens we are going to copy the file. No need to repeat the code.
Copy-Item $($LogFilePath) $($DestPath)
While that is an improvement on the logic we can take this a little further. If you want to be sure the file is fresh and overwritten Copy-Item will handle that for you.
# If the folder does not exist create it. If it does move on
If(!(Test-Path $DestPath)){New-Item -ItemType directory -Path $DestPath}
# Regardless of what happens we are going to copy the file. No need to repeat the code.
Copy-Item $LogFilePath $DestPath -Confirm:$false -Force
$() is the notation for a subexpression. A common use in similar context would be to ensure that a variable expands properly in a string. As shown in the following example
PS C:\Users\Cameron> $data = #{Matt="Awesome"}
PS C:\Users\Cameron> "$data.Matt"
System.Collections.Hashtable.Matt
PS C:\Users\Cameron> "$($data.Matt)"
Awesome
Currently in your code, while causing no harm, it is redundant.
Beyond the dubious use of $($Variable) (completely redundant; just use $Variable), you've misplaced a closing brace. The last five lines should look like this:
}
ELSE{
New-Item -ItemType directory -Path $($DestPath)
Copy-Item $($LogFilePath) $($DestPath)
}
If that doesn't work, let us know what's actually happening: errors and such when you try to run it.

Why is PowerShell copying to a random location?

I have the following simple script:
$workingDir = "C:\foo\bar"
$projectsDir = "C:\foo"
Copy-Item -Path "$projectsDir\some subpath\MyFile1.dll" -Destination $workingDir
Copy-Item -Path "$projectsDir\somewhere else\MyFile2.dll" -Destination $workingDir
Copy-Item -Path "$projectsDir\another place\MyFile3.dll" -Destination $workingDir
For some unknown reason, every time I run this script it copies the files to the correct location ($workingDir) and also copies them to $projectsDir\some subpath\something\else. I have to go delete the extra files from the other location every time this script is run.
So far I've tried:
changing variable names
specifying -Destination "$workingDir\MyFile1.dll"
using $null = Copy-Item -Path "...."
I even tried replacing Copy-Item with xcopy.exe
and nothing changes. I put a breakpoint on the first Copy-Item command and looked at the variables - they all looked right. What's going on here?
The only other thing I could think of is to run the copy-item like this:
Copy-Item -Path $($projectsDir + "\some subpath\MyFile1.dll") -Destination $workingDir
This is how I declare almost all of my Variable + SomethingElse scenarios. Since I haven't scene this behavior, I'll go back and test it some more to see what I can find. If I come up with something else, I redo my answer.
I rebooted my computer. Problem solved.

PowerShell - suppress Copy-Item 'Folder already exists' error

When I run a recursive Copy-Item from a folder that has sub folders to a new folder that contains the same sub folders as the original, it throws an error when the subfolders already exist.
How can I suppress this because it is a false negative and can make true failures harder to see?
Example:
Copy-Item "C:\realFolder\*" "C:\realFolder_new" -recurse
Copy-Item : Item with specified name C:\realFolder_new\subFolder already exists.
You could try capturing any errors that happen, and then decide whether you care about it or not:
Copy-Item "C:\realFolder\*" "C:\realFolder_new" -recurse -ErrorVariable capturedErrors -ErrorAction SilentlyContinue
$capturedErrors | foreach-object { if ($_ -notmatch "already exists") { write-error $_ } }
If you add -Force to your command it will overwrite the existing files and you won't see the error.
-Recurse will replace all items within each folder and all subfolders.
Copy-Item "C:\realFolder\*" "C:\realFolder_new" -Recurse -Force
You can set the error handling behavior to ignore using:
Copy-Item "C:\realFolder\*" "C:\realFolder_new" -recurse -ErrorAction SilentlyContinue
However this will also suppress errors you did want to know about!