Pyrevit Bundle Create - Access Denied Error & Other errors

Hello. Very new to the programming world as well as PyRevit.

I’d love to use PyRevit to create buttons. I started to do this by creating a series of folders and then addinig a .py file to the folder but I come up with errors where it basically gives me a couple errors and then tells me a the source file cannot be found and may have been deleted. Then I realized there was a bundle creator extension so Im trying that route now.

The issue is that I am getting errors with the bundle creator to. Do I just need to reinstalll this in a different location??

Error is below:

IronPython Traceback:
Traceback (most recent call last):
File “C:\Program Files\pyRevit-Master\extensions\pyRevitBundlesCreatorExtension.extension\pyRevit Bundles Creator.tab\Button creation.panel\Button Creator.pushbutton\script.py”, line 24, in
WindowsError: [Errno 13] [Errno 5] Access to the path ‘C:\Program Files\pyRevit-Master\extensions\pyRevitBundlesCreatorExtension.extension\pyRevit Bundles Creator.tab\My New Panel Name.panel’ is denied.

Script Executor Traceback:
System.ComponentModel.Win32Exception (0x80004005): WindowsError
at IronPython.Modules.PythonNT.mkdir(String path)
at Microsoft.Scripting.Interpreter.ActionCallInstruction1.Run(InterpretedFrame frame) at Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame) at Microsoft.Scripting.Interpreter.LightLambda.Run4[T0,T1,T2,T3,TRet](T0 arg0, T1 arg1, T2 arg2, T3 arg3) at System.Dynamic.UpdateDelegates.UpdateAndExecute3[T0,T1,T2,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2) at Microsoft.Scripting.Interpreter.DynamicInstruction4.Run(InterpretedFrame frame)
at Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame)
at Microsoft.Scripting.Interpreter.LightLambda.Run2[T0,T1,TRet](T0 arg0, T1 arg1)
at IronPython.Compiler.PythonScriptCode.RunWorker(CodeContext ctx)
at PyRevitLabs.PyRevit.Runtime.IronPythonEngine.Execute(ScriptRuntime& runtime)

Hi Nicholas and welcome.
Would you mind sharing the code in C:\Program Files\pyRevit-Master\extensions\pyRevitBundlesCreatorExtension.extension\pyRevit Bundles Creator.tab\Button creation.panel\Button Creator.pushbutton\script.py

Yes - will do. However, all I did was hit the existing sample button to create another button and then I gave the button a name. Once I did that, that error came up. I’m assuming Pyrevit just created a that file as a sample

I will send ASAP. Thanks!!

Sorry this took so long.

Please see below. Doesent look like I can insert an attachment here so copying the code. Theres also a yaml file in there, along with an icon.

# -*- coding=utf-8 -*-
"""
Create a new button from a template of button bundles.
"""


import os
import shutil
from pyrevit.forms import ask_for_string, alert, CommandSwitchWindow
from pyrevit import script, forms
from pyrevit.loader import sessionmgr

# base folders structure
current_folder = os.path.dirname(__file__)
up_1_folder = os.path.dirname(current_folder)
button_types_folder = "button_types"
button_types_folder = os.path.join(up_1_folder, button_types_folder)
up_2_folder = os.path.dirname(up_1_folder)

# get panel name and create folder
panel_name = forms.ask_for_string(
    default="My New Panel Name", title="New panel", prompt="Get your new panel a name")
panel_folder = os.path.join(up_2_folder, panel_name + ".panel")
if not os.path.exists(panel_folder):
    os.mkdir(panel_folder)

# to extend add entry to dict: {"button type": ["bundle extension", "button template folder"]}
buttton_type_dict = {"pushbutton": ["pushbutton", "pushbutton"],
                     "pushbutton with config": ["pushbutton", "pushbutton_with_config"],
                     "pushbutton for Dynamo script": ["pushbutton", "pushbutton_for_dynamo_script"],
                     "content button": ["content", "content_button"],
                     "url button": ["urlbutton", "url_button"],
                     "invoke C# dll button": ["invokebutton", "invoke_dll_button"],
                     }


def button_template(button_type):
    button_folder = "pushbutton"
    button_template_folder_str = "pushbutton"
    if button_type in buttton_type_dict:
        button_folder = buttton_type_dict[button_type][0]
        button_template_folder_str = buttton_type_dict[button_type][1]
    button_template_folder = os.path.join(
        button_types_folder, button_template_folder_str)
    return button_folder, button_template_folder


def create_button(button_type):
    button_folder, button_template_folder = button_template(button_type)
    newname = ask_for_string(
        title="New Folder", instructions="Specify name for new button")
    if not newname:
        alert("No name specified, will exit")
        script.exit()
    new_button_folder = os.path.join(
        panel_folder, newname + "." + button_folder)

    if os.path.exists(new_button_folder):
        alert("Folder already exists")
    else:
        os.mkdir(new_button_folder)
        for f in os.listdir(button_template_folder):
            file = os.path.join(button_template_folder, f)
            shutil.copy(file, new_button_folder)
            # copy bin folder to root of newfolder in invokebutton
            if button_type == "invoke C# dll button":
                bin_template_folder = os.path.join(button_types_folder, "bin")
                bin_folder = os.path.join(panel_folder, "bin")
                if not os.path.exists(bin_folder):
                    os.mkdir(bin_folder)
                for f in os.listdir(bin_template_folder):
                    file = os.path.join(bin_template_folder, f)
                    shutil.copy(file, bin_folder)

        for copied_file in os.listdir(new_button_folder):
            if copied_file.endswith(".yaml"):
                # get english title string and replace with newname
                path = os.path.join(new_button_folder, copied_file)
                with open(path, "r") as f:
                    lines = f.readlines()
                with open(path, "w") as f:
                    for line in lines:
                        if "  en_us: english title" in line:
                            line = "  en_us: {}\n".format(newname)
                        f.write(line)


while True:
    button_type_selected = CommandSwitchWindow.show(
        buttton_type_dict.keys(), message="Select button type")
    if button_type_selected:
        create_button(button_type_selected)
    res = alert("Create another one?", title="Create another button?", yes=True,
                no=True, ok=False, warn_icon=False, footer="pyRevit Bundle Creator")
    if res is False:
        sessionmgr.reload_pyrevit()
        break

@Jean-Marc


Hi @NickNPS, are you an administrator of your computer?

The script tries to create a folder inside the program files directory, but only administrators can write there.

One practical solution to be able to use the UI creator is to install pyrevit as single, normal user, if you can.

If you are an administrator instead, try to run revit as administrator and see if it solves the problem.

Either way I think it could be considered a bug, isn’t it @Jean-Marc ?

you are right @sanzoghenzo
it is due to the use of the admin installer.
The bundle creator routine uses the current folder as a base to push the extension button. I could eventually fix it but it would imply to refactor where I put the content of this ‘new’ extension created by the bundle. It would probably require adding an extension folder path to the pyrevit config while at it.

I will think about it and see if I can make time for it, unless you want to take a shot at it.

@NickNPS can you install pyrevit with the regular installer?

OfCourse. Yes, im an administrator on the PC. Ill go-ahead and uninstall + reinstall.

I think im having this issue with other programs and im actually kind of happy this happened. There are a couple other Revit add-ins that are giving me errors outside of pyrevit and never would have figured this out without the command prompt errors.

Ill circle back.

Thanks!