Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powershell copy a file or get the content without lock it

Tags:

powershell

We have some scheduled scripts. They have to access a file "Functions.ps1" with dot sourced functions. This "Functions.ps1" is located on a share. Because the ExecutionPolicy I can't load the file like this:

. \\share\folder\Functions.ps1

The scheduled script must do a copy to the local C:\ and load the file:

$str_ScriptPath = "$($env:LOCALAPPDATA)\$(Get-Random -Minimum 0 -Maximum 100000)_Functions.ps1"
Copy-Item -Path "$str_Share\Functions.ps1" -Destination $str_ScriptPath -Force   
. $str_ScriptPath
Remove-Item -Path $str_ScriptPath 

The problem is that some scripts are scheduled at the same time.
In this case it occures an error:

The process cannot access the file 'C:\Windows\system32\config\systemprofile\AppData\Local\88658_Functions.ps1' because it is being used by another process. 
At line:46 char:14
+     Copy-Item <<<<  -Path "$str_Share\Functions.ps1" -Destination $str_ScriptPath -Force

I don't see the reason why the error tells the local file is locked. It should be an unique file name and the file does not exist.
I think because the Copy-Item the source ($str_Share\Functions.ps1) is locked.
My question:
1) Is there a better way to handle this?
2) Or is there a workarround?

Thanks for help
Patrick

like image 340
Patrick Avatar asked Oct 14 '25 04:10

Patrick


1 Answers

You should be able to obtain a non-exclusive read-only handle to the file with [System.IO.File]::Open():

function Copy-ReadOnly
{
    param(
        [Parameter(Mandatory)]
        [string]$Path,
        [Parameter(Mandatory)]
        [string]$Destination
    )

    # Instantiate a buffer for the copy operation
    $Buffer = New-Object 'byte[]' 1024

    # Create a FileStream from the source path, make sure you open it in "Read" FileShare mode
    $SourceFile = [System.IO.File]::Open($Path,[System.IO.FileMode]::Open,[System.IO.FileAccess]::Read,[System.IO.FileShare]::Read)
    # Create the new file
    $DestinationFile = [System.IO.File]::Open($Destination,[System.IO.FileMode]::CreateNew)

    try{
        # Copy the contents of the source file to the destination
        while(($readLength = $SourceFile.Read($Buffer,0,$Buffer.Length)) -gt 0)
        {
            $DestinationFile.Write($Buffer,0,$readLength)
        }
    }
    catch{
        throw $_
    }
    finally{
        $SourceFile.Close()
        $DestinationFile.Close()
    }
}
like image 50
Mathias R. Jessen Avatar answered Oct 18 '25 04:10

Mathias R. Jessen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!