I am trying to make a hidden file in Windows using Python, but after I make it hidden it becomes impossible to write. However, reading this file is possible.
import ctypes
with open("test.txt", "r") as f: print('test')
ctypes.windll.kernel32.SetFileAttributesW("test.txt", 0x02) # adding h (hidden) attribute to a file
with open("test.txt", "r") as f: print('test') # works
with open("test.txt", "w") as f: print('test') # error
Error:
Traceback (most recent call last):
File "C:\Users\user\Documents\client\test.py", line 8, in <module>
with open("test.txt", "w") as f: print('test') # error
PermissionError: [Errno 13] Permission denied: 'test.txt'
Using 0x22
(which is a
attribute and h
attribute) instead of 0x02
doesnt't help. The same error occurs.
After making the file visible again via attrib -H test.txt
it becomes possible to open it in write mode. However, as far as I know, hidden files should be writable in Windows.
OS: Windows 11
Python version: Python 3.10.2
I haven't seen specific Python documentation on this behavior, but believe it is because at the implementation level, 'w'
eventually is calling The Windows API CreateFileW
which has this note:
If CREATE_ALWAYS and FILE_ATTRIBUTE_NORMAL are specified, CreateFile fails and sets the last error to ERROR_ACCESS_DENIED if the file exists and has the FILE_ATTRIBUTE_HIDDEN or FILE_ATTRIBUTE_SYSTEM attribute. To avoid the error, specify the same attributes as the existing file.
Opening for writing mode='w'
would eventually use CREATE_ALWAYS with FILE_ATTRIBUTE_NORMAL and would return access denied; whereas opening for reading and updating mode='r+'
or appending mode='a'
would work because OPEN_EXISTING would be used.
Demonstrated below with Python:
import os
import ctypes
FILE_ATTRIBUTE_HIDDEN = 0x2
FILE_ATTRIBUTE_NORMAL = 0x80
# Ensure file is deleted first for script repeatability.
try:
ctypes.windll.kernel32.SetFileAttributesW("test.txt", FILE_ATTRIBUTE_NORMAL)
os.remove('text.txt')
except Exception as e:
pass
# Create the file and hide it
with open('test.txt', 'w') as f:
print('test', file=f)
ctypes.windll.kernel32.SetFileAttributesW("test.txt", FILE_ATTRIBUTE_HIDDEN)
with open('test.txt', 'r') as f: # read it
print('read:', f.read())
with open('test.txt', 'r+') as f: # update it
f.truncate()
print('written', file=f)
with open('test.txt', 'r') as f: # read it back
print('write:', f.read())
Output:
read: test
write: written
The command prompt works the same way:
C:>attrib -h test.txt
C:>del test.txt
C:>echo line1 >test.txt
C:>attrib +h test.txt
C:>type test.txt
line1
C:>echo line2 >test.txt # can't be directly written
Access is denied.
C:>echo line2 >>test.txt # CAN be appended (updated).
C:>type test.txt
line1
line2