Read files that are in use

I am trying to read a log file using Get-Content so I can keep track of the progress of the application that is creating the file. Unfortunately PowerShell gives me the following error message: “The process cannot access the file ‘[FileName]’ because it is being used by another process.”

Apparently the process that is creating the file is still writing to the file, essentially blocking all access to the file. With some other applications it works to copy/paste the file to a new file, but this doesn’t work in this case.

Is there a way to read files that are in use by other processes? Opening the file in Read-Only mode is no problem.

I found this online…here.

Worked for me when I tested.

[System.IO.FileStream]$fileStream = [System.IO.File]::Open($inFile, [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()
</pre<

Unfortunately this does not work.

More background info: I am trying to read the DSC json log file, which is being created in C:\Windows\System32\Configuration\ConfigurationStatus. You example code throws the exact same error:

[pre]Exception calling “Open” with “4” argument(s): “The process cannot access the file
‘C:\Windows\System32\Configuration\ConfigurationStatus{991F9D8A-AEF6-11E9-80C4-000D3A2D992C}-0.details.json’ because it is being
used by another process.”
At line:5 char:1

  • [System.IO.FileStream]$fileStream = [System.IO.File]::Open($file.Full …
  • CategoryInfo : NotSpecified: (:slight_smile: , MethodInvocationException
  • FullyQualifiedErrorId : IOException[/pre]

You are not showing any code, thus leaving us to guess at what is really the deal.

As per windows proper, you can read any file open by another process. Of course you can’t do anything to it. I do this every day for log (syslog’s, txt, winevent logs, etc.) monitoring during troubleshooting efforts. Just doing stuff like this…

# Get and show the latest selected current log.
'The current log fie is: '
(
    $latest = Get-ChildItem -Path $LogPath | 
    Sort-Object LastAccessTime -Descending | 
    Select-Object -First 1
)

# Show the log lines real time
Get-Content -Path $latest.FullName -tail 0 -Wait | 
Out-GridView -PassThru -Title $LogName

 

 

The article Iain was referring to, also mentioned a different solution: Using ShadowCopy.

This worked perfectly:

$s1 = (Get-WmiObject -List Win32_ShadowCopy).Create("C:\", "ClientAccessible")

$s2 = Get-WmiObject Win32_ShadowCopy | Where-Object { $_.ID -eq $s1.ShadowID }
$d = $s2.DeviceObject + "\" #
cmd /c mklink /d C:\dsc_logs "$d" | Out-Null

Start-Sleep -Seconds 2     # Have the Shadow Copy mount properly.

$scpath = 'C:\dsc_logs\Windows\System32\Configuration\ConfigurationStatus'
$logfile = Get-ChildItem $scpath -Filter *.json | Sort-Object -Property LastWriteTime -Descending | Select-Object -First 1
$fullPath = Join-Path -Path $scpath -ChildPath $logfile

cmd /c notepad $fullPath