3

I need to read a file on a remote pc which is frequently modified. As it so happens, it appears that my script is sometimes colliding with a write on the file, rendering it inaccessible. I cannot change the way the file is written to so I have to work with what I have.

I ran a test by having a script continuously reading a file with Get-Content and subsequently starting another script which writes to the file at frequent intervals. At times, the write operation was not possible.

Is it possible that I use get-content on a remote pc without locking the file?

1
[System.IO.FileStream]$fileStream = [System.IO.File]::Open("\\remote\share\Text Document.txt", [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite)
$byteArray = New-Object byte[] $fileStream.Length
$encoding = New-Object System.Text.UTF8Encoding $true
while ($fileStream.Read($byteArray, 0 , $byteArray.Length)) {
    $encoding.GetString($byteArray)
}
$fileStream.Dispose()
  • Thank you for your input, however this still locks the file to a write, if my testing is correct. – lcam Mar 6 '17 at 13:19
  • How do you perform your testing? I didn't get any locks while testing this code snippet. – t1meless Mar 12 '17 at 19:44
  • Never mind, my testing was in fact incorrect. I researched a bit so I could modify your code to read the last couple of lines of the file rather than read the whole lot of it as that was taking some time and conflicting with a write. This seemed to have solved the issue, thanks! – lcam Mar 16 '17 at 15:53
6

The content that is being written cannot be read on the same time.

As a solution for you, you could read the file using shadow copy. For that, you will need to mount a shadow copy.

$s1 = (Get-WmiObject -List Win32_ShadowCopy).Create("X:\", "ClientAccessible")
$s2 = Get-WmiObject Win32_ShadowCopy | Where-Object { $_.ID -eq $s1.ShadowID }
$d  = $s2.DeviceObject + "\"   # 
cmd /c mklink /d X:\tmpshacpy "$d"

After this, you can access the mounted location ( X:\tmpshacpy) and read the file just fine.

To unmount the shadow copy after the read is done, use $s2.Delete().

  • Thanks for your input. I read about this feature and it looks amazing, however I forgot to mention that I need to this on a remote computer. – lcam Mar 3 '17 at 13:45
  • "I forgot to mention that I need to this on a remote computer" Use Invoke-Command for that. – Ƭᴇcʜιᴇ007 Mar 3 '17 at 14:01
  • You can use remote commands just fine (with invoke) and you will have to provide credentials (just another additional parameter). – Overmind Mar 6 '17 at 9:43
  • Thanks all. Unfortunately it understandably is taking some time to create and mount the shadow copy on the remote pc, and I need this script to go over 100 pc's after each other... but perhaps I am asking for the impossible now. If only there was some way to kind of get a shadow copy of a single file... Thanks anyway! – lcam Mar 6 '17 at 13:17
  • If the shadow is mounted, you can copy a single file from that mount, should be no issue here. – Overmind Mar 7 '17 at 8:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.