Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to release (get-item c:\temp\a.log).OpenRead() from lock status?

Tags:

powershell

I use PowerShell command (get-item c:\temp\a.log).OpenRead() to test what happen with the file.

After file is opened to read, if I issue (get-item c:\temp\a.log).OpenWrite(), it will return the following error

Exception calling "OpenWrite" with "0" argument(s): "The process cannot access the file
'C:\temp\a.log' because it is being used by another process."  
+ (get-item c:\temp\a.log).OpenWrite()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : IOException

How can I release the OpenRead() status?

like image 380
Hsing Yi Avatar asked Oct 19 '25 14:10

Hsing Yi


2 Answers

Just to explain why you're seeing this behavior when you open a file with .OpenRead() and then again with .OpenWrite(), it's caused by sharing (or lack thereof), not locking. Sharing dictates what kind of access is allowed for other streams opened from the same file while the current stream is still open.

OpenRead and OpenWrite are convenience methods that wrap the FileStream constructor; OpenRead creates a read-only stream with read sharing allowed, and OpenWrite creates a write-only stream with no sharing allowed. You may notice that there is another method called simply Open with overloads that allow you to specify the access (second parameter) and sharing (third parameter) yourself. We can translate OpenRead and OpenWrite to Open, thus...

$read = (get-item c:\temp\a.log).OpenRead()
# The following line throws an exception
$write = (get-item c:\temp\a.log).OpenWrite()

...becomes...

$read = (get-item c:\temp\a.log).Open('Open', 'Read', 'Read')           # Same as .OpenRead()
# The following line throws an exception
$write = (get-item c:\temp\a.log).Open('OpenOrCreate', 'Write', 'None') # Same as .OpenWrite()

Either way you write it, the third line will fail to create a write-only stream because $read will only allow other streams to read as well. One way to prevent this conflict is to close the first stream before opening the second:

$read = (get-item c:\temp\a.log).Open('Open', 'Read', 'Read')           # Same as .OpenRead()
try
{
    # Use $read...
}
finally
{
    $read.Close()
}

# The following line succeeds
$write = (get-item c:\temp\a.log).Open('OpenOrCreate', 'Write', 'None') # Same as .OpenWrite()
try
{
    # Use $write...
}
finally
{
    $write.Close()
}

If you really do need a read-only and a write-only stream to be open on the same file simultaneously, you can always pass your own values to Open to allow this:

$read = (get-item c:\temp\a.log).Open('Open', 'Read', 'ReadWrite')
# The following line succeeds
$write = (get-item c:\temp\a.log).Open('OpenOrCreate', 'Write', 'Read')

Note that the sharing goes both ways: $read needs to include Write in its sharing value so that $write can be opened with Write access, and $write needs to include Read in its sharing value because $read is already open with Read access.

In any case, it is always good practice to call Close() on any Stream when you are done using it.

like image 71
Lance U. Matthews Avatar answered Oct 21 '25 03:10

Lance U. Matthews


I found a way to release the lock status

I just invoke another command:

$s = (get-item c:\temp\a.log).OpenRead()  

, then use

$s.close()

The file is not locked anymore

like image 45
Hsing Yi Avatar answered Oct 21 '25 03:10

Hsing Yi