5

Trying to hide folder without success. I've found this :

import ctypes
ctypes.windll.kernel32.SetFileAttributesW('G:\Dir\folder1', 2)

but it did not work for me. What am I doing wrong?

martineau
  • 119,623
  • 25
  • 170
  • 301
IKA
  • 151
  • 1
  • 3
  • 11

2 Answers2

13

There are two things wrong with your code, both having to do with the folder name literal. The SetFileAttributesW() function requires a Unicode string argument. You can specify one of those by prefixing a string with the character u. Secondly, any literal backslash characters in the string will have to be doubled or you could [also] add an r prefix to it. A dual prefix is used in the code immediately below.

import ctypes
FILE_ATTRIBUTE_HIDDEN = 0x02

ret = ctypes.windll.kernel32.SetFileAttributesW(ur'G:\Dir\folder1',
                                                FILE_ATTRIBUTE_HIDDEN)
if ret:
    print('attribute set to Hidden')
else:  # return code of zero indicates failure -- raise a Windows error
    raise ctypes.WinError()

You can find Windows' system error codes here. To see the results of the attribute change in Explorer, make sure its "Show hidden files" option isn't enabled.

To illustrate what @Eryk Sun said in a comment about arranging for the conversion to Unicode from byte strings to happen automatically, you would need to perform the following assignment before calling the function to specify the proper conversion of its arguments. @Eryk Sun also has an explanation for why this isn't the default for pointers-to-strings in the W versions of the WinAPI functions -- see the comments.

ctypes.windll.kernel32.SetFileAttributesW.argtypes = (ctypes.c_wchar_p, ctypes.c_uint32)

Then, after doing that, the following will work (note that an r prefix is still required due to the backslashes):

ret = ctypes.windll.kernel32.SetFileAttributesW(r'G:\Dir\folder1',
                                                FILE_ATTRIBUTE_HIDDEN)
martineau
  • 119,623
  • 25
  • 170
  • 301
  • Surely this can be done without raw win32 in a platform independent way – David Heffernan Oct 27 '13 at 20:43
  • David Heffernan, how? If it not a secret? :) – IKA Oct 27 '13 at 21:02
  • Just one more qustion - why 0x02 and not just 2? – IKA Oct 27 '13 at 21:33
  • I wrote it that way because there's a [bunch of other ones](http://msdn.microsoft.com/en-us/library/windows/desktop/aa365535%28v=vs.85%29.aspx) that correspond to different bits being on and that's easier to see in hexadecimal the decimal. Please consider also up-voting my answer if you think it's worthy. – martineau Oct 28 '13 at 00:54
  • @David: You might think that, however the only thing in the standard library that would do something like this that I know of is [`os.chflags()`](http://docs.python.org/2/library/os.html?highlight=chflags#os.chflags), but it's not available on Windows - I just tried it and got an `AttributeError: 'module' object has no attribute 'chflags'`. – martineau Oct 28 '13 at 01:15
  • If you set the function's `argtypes` to use `ctypes.wintypes.LPCWSTR` (i.e. `ctypes.c_wchar_p`), as should be done anyway, then you can also use a byte string here. In 2.x `ctypes.set_conversion_mode` can be used to set the conversion `encoding` and `errors`. On Windows it defaults to 'mbcs' and 'ignore'. – Eryk Sun Oct 28 '13 at 02:56
  • 2
    Also if the call fails just `raise ctypes.WinError()`. The `WinError()` function defaults to using `ctypes.GetLastError` and `ctypes.FormatError` to return a `WindowsError` exception. – Eryk Sun Oct 28 '13 at 03:01
  • @eryksun: How would you change an existing function's `argtypes` (in Python 2.x)? – martineau Oct 28 '13 at 03:24
  • 1
    `argtypes` is an attribute of the ctypes function pointer. Just assign a sequence of ctypes data types. The descriptor is implemented by [`PyCFuncPtr_set_argtypes`](http://hg.python.org/cpython/file/ab05e7dd2788/Modules/_ctypes/_ctypes.c#l3083) and [`PyCFuncPtr_get_argtypes`](http://hg.python.org/cpython/file/ab05e7dd2788/Modules/_ctypes/_ctypes.c#l3106). – Eryk Sun Oct 28 '13 at 03:36
  • As BSD general command CHFLAGS works fine on OS X. CHFLAGS HIDDEN ~/PathToFolder. – IKA Oct 28 '13 at 07:29
  • @martineau, Your answer is very useful and it solved my problem and I would like to vote up but my reputation don't permit this action(need 15) – IKA Oct 28 '13 at 07:34
  • @iRex" Yes, `os.chflags()` works on Unix and derivative OSs. I understand about the lack of rep issue -- no worries. – martineau Oct 28 '13 at 07:44
  • FWIW, raising `ctypes.WinError()` when the return code is zero results in the error message: `WindowsError: [Error 123] The filename, directory name, or volume label syntax is incorrect` being printed, so I have to agree that might be an easier way to handle call failures. – martineau Oct 28 '13 at 07:58
  • `windll` is a `LibraryLoader` for `WinDLL`, which subclasses `CDLL`. Its `__getattr__` binds a function pointer that has `restype == c_int` and `argtypes == None`. There are defaults for converting some built-in Python objects as arguments, but explicit is better, and often necessary. – Eryk Sun Oct 28 '13 at 10:22
  • @eryksun: That sounds fine as a default for an unknown API function, but it seems like the user-base is large enough and the API stable enough for the proper argument types of most if not all known functions to have done already -- rather than everyone having to reinvent the wheel whenever they want to use one from Python. – martineau Oct 28 '13 at 14:43
  • 1
    It sounds like you want something like [`jaraco.windows`](https://bitbucket.org/jaraco/jaraco.windows/overview). I haven't used it. PyWin32 also works, but it's a big dependency: `win32file.SetFileAttributes(r'G:\Dir\folder1', win32file.FILE_ATTRIBUTE_HIDDEN)`. – Eryk Sun Oct 28 '13 at 15:15
  • Using os.walk I think returns windows-1252 path strings for me, I'm using path.decode("windows-1252") to get the unicode path. – Tahlor Jun 23 '17 at 14:56
  • Can anybody verify that the Unicode variant still works in Python 3, it seems sketchy to me at best? (Python 3.3+ will alternative the internal Unicode representation based on the storage requirements of the largest scalar value [“character”], hence the question.) – ntninja Mar 10 '20 at 18:55
2

Try this code:

import os
os.system("attrib +h " + "your file name")
Phistrom
  • 539
  • 5
  • 20
Nightwing
  • 29
  • 1