I had experienced several times similar issues using Windows DLL
s.
For performances optimization, security purposes and a bounch of other low level but nonetheless important details I didn't dig into, DLL
s in Windows are loaded once (per platform/version/culture/...). So when you refere them, as you did in your code, if they have been already loaded by some other process they have also already loaded their data, security context and so on.
In this case the call to the DLL
even if it's performed by your process has a different context: here is where the sharing thing starts making sense.
As you already know, Python is a general purpose, multiplatform programming language, so it's main aim is to give you an interface to the underlying OS features indipendently of how it exposes them.
Well, it turns out that the windows CreateFile
function as a significant high number of options that can be delivered to it and does not apply to other OS, one of which is dwShareMode
that dictates how the file is shared with other processes. (Here the ufficial documentation).
If this parameter is zero and CreateFile succeeds, the file or device cannot be shared and cannot be opened again until the handle to the file or device is closed.
You cannot request a sharing mode that conflicts with the access mode that is specified in an existing request that has an open handle. CreateFile would fail and the GetLastError function would return ERROR_SHARING_VIOLATION.
I think core python developers, if using that function at all (not the posix one if supported by windows), had left the value of that variable to 0 leading to the behaviour you're experiencing.
In order for your process to be able to call the DLL
s functions that deals with the files created by your own code you have to be sure you do not have "non shared" descriptors open to them.
You have at least two options:
- Create the file calling directly the Windows API and specifying the sharing behaviour you desire.
- Opening file through context manager
Solution 2
is easier and more "pythonic" so I'll go with it:
import os
import ctypes
fname1 = 'test1.txt'
fname2 = 'test2.txt'
with open(fname1, 'w') as f1:
f1.write(fname1)
with open(fname2, 'w') as f2:
f2.write(fname2)
ctypes.windll.kernel32.ReplaceFileW(fname2, fname1, 'tmp123', 0, None, None)