Revit Link Path Type set as relative but not Found with any other user,
When I link Revit files stored in Autodesk Desktop Connector with Dynamo python script, by default the links path type is absolute, and manually I have to change all of them to relative path type, but when file is opened by any other user or computer, the links are not found even than the path that I read as relative is correct, then if I click one by one reload from…and the files are in Autodesk Desktop Connector drive in my computer, then the path type is called Cloud and cannot be modified which is what I want to get directly when linking files.
After changing path type to relative and opening in other computer:
Revit 2021, not going to upgrade to Revit 2022 in years so why not updating Revit 2021 as hotfix.
import clr
if IN[3] != None :
clr.AddReference("System")
from System.Collections.Generic import List
# Import ToDSType(bool) extension method
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
from System.Collections.Generic import *
# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)
import System
doc = DocumentManager.Instance.CurrentDBDocument
# Start Transaction
TransactionManager.Instance.EnsureInTransaction(doc)
if isinstance(IN[0], list) : in_links = IN[0]
else : in_links = [IN[0]]
if isinstance(IN[1], list) : in_ws = IN[1]
else : in_ws = [IN[1]]
pinned = IN[2]
if IN[3] != None :
if isinstance(IN[3], list) : closedwsnames = IN[3]
else : closedwsnames = [IN[3]]
else : closedwsnames = None
# number of elements
try : numlinks = len(in_links)
except : OUT = 'Input a filepath'
try : numworksets = len(in_ws)
except : numworksets = 0
#check list lengths
if numlinks == numworksets : listlength = True
else : listlength = False
def linkmodel (fpath, doc, pin) :
# Create the Revit Link Type
mpu = ModelPathUtils.ConvertUserVisiblePathToModelPath(fpath)
if closedwsnames == None :
lnkoptions = RevitLinkOptions("")
else :
#Workset configuration
try :
worksets = WorksharingUtils.GetUserWorksetInfo(mpu)
ows = []
for ws in worksets :
name = ws.Name
wsid = ws.Id
closed = []
for wsn in closedwsnames :
if wsn in name :
closed.append(wsid)
if wsid not in closed :
ows.append(wsid)
#The workset Ids collected put in an IList format
openwsids = List[WorksetId](ows)
#Directly creating the RevitLinkOptions raises an error, so I create it once, and then extract the Worksetconfiguration to modify it. Had some issues with the Close() method of the WorksetConfiguration, Open() worked instead
wc = WorksetConfiguration(WorksetConfigurationOption.CloseAllWorksets)
lnkoptions = RevitLinkOptions(False, wc)
wc2 = lnkoptions.GetWorksetConfiguration()
wc2.Open(openwsids)
lnkoptions = RevitLinkOptions(False, wc2)
except :
lnkoptions = RevitLinkOptions("")
#Create RevitLinkType
loadedLnkType = RevitLinkType.Create(doc, mpu, lnkoptions)
# Create the Revit Link Instance
lnkInstance = RevitLinkInstance.Create(doc, loadedLnkType.ElementId, ImportPlacement.Shared)
#Pin link
lnkInstance.Pinned = pin
return lnkInstance
try:
# Number of worksets input and filepaths input are different
if IN[1] and listlength == False :
OUT = "The number of worksets doesn't match the number of links"
# Multiple Worksets input
elif IN[1] and listlength == True :
#Get WorksetTable and current workset
wstable = doc.GetWorksetTable()
activewsid = wstable.GetActiveWorksetId()
#Create list for output
links = []
for fpath, ws in zip(in_links, in_ws) :
# Get WorksetId
wssimpleid = ws.Id
wsid = WorksetId(wssimpleid)
# Set the workset
WorksetTable.SetActiveWorksetId(wstable, wsid)
# Create the Revit Link Type and Link Instance
a = linkmodel(fpath, doc, pinned)
#add created link to output
links.append(a)
#reset current workset
WorksetTable.SetActiveWorksetId(wstable, activewsid)
#output
OUT = links
# No worksets input
else :
links = []
for fpath in in_links :
a = linkmodel(fpath, doc, pinned)
links.append(a)
OUT=links
except:
# if error accurs anywhere in the process catch it
import traceback
errorReport = traceback.format_exc()
OUT = errorReport
# End Transaction
TransactionManager.Instance.TransactionTaskDone()
Usually it is because it isn’t as simple as adding the feature, but involves enough changes to the codebase that when done you would have most of the new build but without having any tests run on it so it wouldn’t be stable for other core aspects (say, loading the homepage wouldn’t work but you would be able to programmatically set links) and tie up a development team for a significant chunk of the following release’s development cycle. As a rule if stuff can be backported to old builds without (1) breaking the software, (2) effectively rebuilding the entire code base so it is the new build, or (3) tying up a team long enough that work for the next release isn’t done, it will be added.
I’ll dig into options later, but asking on the Revit API forum is likely a better route as this is very code focused and entails a high degree of familiarity with a lot of rarely used classes.
well, I am sure there is a workaround or other API task for converting to cloud link path, but little experience on that as BIM360 is something new that it does not seem to be high demanded
Though I would be very happy to be proven wrong, I believe that this indicates that some forge processing will be required to get links to map to the GUIDs needed to create cloud paths, and even then I am not sure that setting the value without the flag will give you the desired result, as reading the remarks around ‘file path’ in the 2022 and 2021.1 APIs you’ll see there is a specific call out to ‘server, network, or cloud path’ while 2021.1 only indicates server.
Yes, this code was not possible to build until the API changes in 2022 which I previously highlighted, though if you’d like you can confirm with the code author directly on the GitHub (submit an issue or reach out to them via their GitHub profile).
This solution also requires Forge to parse and store GUIDs for models, so a pure Python solution won’t fit here - you’ll need C# and web API skills to build that specific solution, and likely any full scale solution would need such tools or a lot more - round about effort to get the necessary information, such as journal parsing, collaboration cache review. Those may or may not provide the needed info (the GUIDs but may not align), but I believe it would take significantly longer as you’d have to upload all models to BIM360, then open all models locally with the local links, then close Revit, then parse the data, then repath the links (downloading each model again in the process of the repathing…). A full Forge app (via the methods shown and design collaboration) which just does all of the work is likely the best bet speed wise though.
THe question is - are those values the same, or different based on the need for security? I haven’t tested. Remember you’d have to upload, then open, then parse the cache for all models… at some point your time investment to learn the code calls, build, test, and implement the solution will surpass the time to ‘do it manually for this job’, so be sure the scope of ‘just doing it manually’ is ahead of you as you work.
are you able to link revit files that are on accdocs(Bim360)? i used the morpheus package which works absolutely great on local files. but when one of my colleagues tried on a bim 360 active file & tried to link some revit files as link that are also on same bim360 project folder, the package gave some unexpected error , unable to open file or so. The file were synced before trying the script, but still does not work
is it because of the fact that the files are on bim360 & not on local? any workaround for the same?
Still the same outcome and likely always will be for any future dig-ups of this thread.
The Id’s of the model are needed to use this API in Python, you can find the Python code in the Sparrow package, but it wont take anything but the GUID’s of the model/project. To get these you will need to access the web and likely need C# or just use Forge.
The shift and focus of Autodesk in their API has shifted to APS for cloud based operations, so if your company is heading into this space they should either hire a webdev with Forge experience or give someone the opportunity to become one.