Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell locking File

Tags:

powershell

I am trying to do something very simple in PowerShell.

  1. Reading the contents of a file
  2. Manipulation some string
  3. Saving the modified test back to the file

    function Replace {
      $file = Get-Content C:\Path\File.cs
      $file | foreach {$_ -replace "document.getElementById", "$"} |out-file -filepath C:\Path\File.cs
    }
    

I have tried Set-Content as well.

I always get unauthorized exception. I can see the $file has the file content, error is coming while writing the file.

How can I fix this?

like image 617
Ben Avatar asked Jun 16 '10 22:06

Ben


People also ask

How do you unlock a file in PowerShell?

The Unblock-File cmdlet lets you open files that were downloaded from the internet. It unblocks PowerShell script files that were downloaded from the internet so you can run them, even when the PowerShell execution policy is RemoteSigned. By default, these files are blocked to protect the computer from untrusted files.

What does locking a file do?

Locking a file File locking allows you to prevent other users from editing or replacing a file on which you are currently working.

How do you check if a file is locked?

The easiest way to tell if a file is locked is when the operating system tells you so after you've tried to modify it or move it from where it's at. For example, if you open a DOCX file for editing in Microsoft Word, that file will be locked by that program.


2 Answers

This is likely caused by the Get-Content cmdlet that gets a lock for reading and Out-File that tries to get its lock for writing. Similar question is here: Powershell: how do you read & write I/O within one pipeline?

So the solution would be:

${C:\Path\File.cs} = ${C:\Path\File.cs} | foreach {$_ -replace "document.getElementById", '$'}
${C:\Path\File.cs} = Get-Content C:\Path\File.cs | foreach {$_ -replace  "document.getElementById", '$'}

$content = Get-Content C:\Path\File.cs | foreach {$_ -replace "document.getElementById", '$'}
$content | Set-Content C:\Path\File.cs

Basically you need to buffer the content of the file so that the file can be closed (Get-Content for reading) and after that the buffer should be flushed to the file (Set-Content, during that write lock will be required).

like image 124
stej Avatar answered Nov 10 '22 03:11

stej


The accepted answer worked for me if I had a single file operation, but when I did multiple Set-Content or Add-Content operations on the same file, I still got the "is being used by another process" error.

In the end I had to write to a temp file, then copy the temp file to the original file:

(Get-Content C:\Path\File.cs) | foreach {$_ -replace "document.getElementById", '$'} | Set-Content C:\Path\File.cs.temp
Copy-Item C:\Path\File.cs.temp C:\Path\File.cs
like image 1
pduncan Avatar answered Nov 10 '22 02:11

pduncan