1

I'm trying to change iconresource on desktop.ini file after changing folder icon with this python script but I got this:

Exception has occurred: PermissionError [Errno 13] Permission denied: 'desktop.ini'

I've tried run as administrator, disabling UAC, and changing security permissions of file but no answer.

import configparser
config = configparser.ConfigParser()
config.read('desktop.ini')
pieces = config['.ShellClassInfo']['iconresource'].split('\\')
del pieces[:-1]
config['.ShellClassInfo']['iconresource'] = pieces[0]
with open('desktop.ini','w') as configfile:
    config.write(configfile)

Exception has occurred: PermissionError [Errno 13] Permission denied: 'desktop.ini'

hem
  • 1,012
  • 6
  • 11
Araeek
  • 11
  • 1
  • Did you try [this answer](https://stackoverflow.com/questions/36434764/permissionerror-errno-13-permission-denied/36469464) ? – IMCoins Aug 05 '19 at 08:41
  • Did you manage to get this working? I have the exact same issue. I first thought that it was because I was running in a venv, but outside that the issue still persists. – Matthieu Mar 27 '20 at 20:42

1 Answers1

0

Short answer

If you're adding content to the ini file, use the r+ mode in the open() function, instead of the w mode.

with open(ini_path, "r+") as file:
    file.write(ini_content)

Otherwise look for "method 2" below.

Long answer

A great answer is provided for this question on why a permission error is raised when trying to call the function open(some_path, 'w') on files with a hidden (H) or system (S) attribute. You can experiment it by manually creating a new hidden file, and then using open(hidden_file_path, 'w'); it will raise the same error.

When looking around about the more general case of hidden files, you can find answers of people suggesting to temporarily remove the hidden attribute, overwrite the file, and then add the attribute back.

import os
os.system(f"attrib -h {hidden_file_path}") # remove the "hidden" attribute
with open(hidden_file_path, 'w') as file:
    file.write(new_content)                # overwrite the file
os.system(f"attrib +h {hidden_file_path}") # add back the "hidden" attribute

This can be unsafe if for any reason you don't control the declaration of the hidden_file_path variable (see "OS command injection"). Also, if you try to use it for overwriting a desktop.ini file, it won't work. Further inspection with the attrib command (os.system(f"attrib {hidden_file_path}") in python, or directly from the command line) reveals that, as expected, these files have both hidden and system attributes (SH). That means that the previous approach should consider both attributes simultaneously.

# method 1
import os
os.system(f"attrib -h -s {ini_path}")
with open(ini_path, 'w') as file:
    file.write(new_content)
os.system(f"attrib +h +s {ini_path}")

Alternatively, a cleaner option is just using the r+ mode instead of w when calling open(). It has worked for me so far when adding stuff to desktop.ini files.

# method 2
with open(ini_path, "r+") as file:
    file.write(ini_content)

Quick note: this approach overwrites completely the file only if the amount of characters in the previous content is less or equal than the amount of characters on the new content. For example, if the file's content is 12345 and you want to write abc, the updated file will contain abc45; whereas if you write abcdefg, the updated file will contain abcdefg.

So, if you're planning to update your ini file with, for example, a shorter path for your iconresource, maybe it's better to use method 1.

Tested using python 3.10.5

Diego BM
  • 409
  • 4
  • 5