2018-12-18 09:51 PM - last edited on 2022-10-04 04:47 PM by Daniel Kassai
GS::Array<API_Guid> gotlinkNodeIDs; if (ACAPI_Database (APIDb_GetHotlinkNodesID, NULL, &gotlinkNodeIDs) != NoError) { DBPrintf("Error getting hot link nodes!"); return; } for (UIndex i = 0; i < gotlinkNodeIDs.GetSize (); i++) { GSErrCode err; // Get hotlink from GUID API_HotlinkNode hotlinkNode; BNZeroMemory (&hotlinkNode, sizeof (API_HotlinkNode)); hotlinkNode.guid = gotlinkNodeIDs; GS::UniString string = APIGuidToString(hotlinkNode.guid); const char *guidString = string.ToCStr(); DBPrintf("Getting Link %s ... \n", guidString); err = ACAPI_Database (APIDb_GetHotlinkNodeID, &hotlinkNode, nullptr); if (err != NoError) { DBPrintf("Error getting link! %d \n", err); } else { // Print current link + get current path GS::UniString displayLinkText = hotlinkNode.sourceLocation->ToDisplayText(); const char *displayLinkTextCString = displayLinkText.ToCStr(); IO::Path currentPath; hotlinkNode.sourceLocation->ToUTF8POSIXPath(¤tPath); GS::UniString currentPathString (currentPath); DBPrintf("\t Old: %s \n", displayLinkTextCString); // Remove old share from path currentPathString.DeleteFirst("/Studio Server"); // Set new server and add current path GS::UniString newLocationURL ("smb://new.server.fqdn/Studio Server/"); newLocationURL.Append(currentPathString); // Set hotlinknode sourceLocation to new location object IO::Location newFileLocation (newLocationURL); hotlinkNode.sourceLocation = &newFileLocation; // new display text link to show new link displayLinkText = newFileLocation.ToDisplayText(); displayLinkTextCString = displayLinkText.ToCStr(); DBPrintf("\t New: %s \n", displayLinkTextCString); // Update the hotlink via API err = ACAPI_Database (APIDb_ModifyHotlinkNodeID, &hotlinkNode); // rename hotlink node if (err != NoError) { DBPrintf("\t ERROR: Hot link not updated: %d.", err); } else { DBPrintf("\t Hot link updated."); } // Update cache if (err == NoError && hotlinkNode.guid != APINULLGuid) { // update cache content DBPrintf(" Updating cache."); ACAPI_Database (APIDb_UpdateHotlinkCacheID, const_cast<API_Guid*> (&hotlinkNode.guid)); } DBPrintf("\n"); } } WriteReport("Updated all links");Result:
Dec 19 09:15:04 Archicad 22.app[4649]: Getting Link 396470F1-4EFC-DEDC-D658-45A971C4367B ... Dec 19 09:15:04 Archicad 22.app[4649]: Old: afp://old.server.fqdn/Studio%20Server//TEMPORARY/Archicad Test file/modules/Level 1-4 - shell.mod Dec 19 09:15:04 Archicad 22.app[4649]: New: smb://new.server.fqdn/Studio%20Server/TEMPORARY/Archicad%20Test%20file/modules/Level%201-4%20-%20shell.mod Dec 19 09:15:04 Archicad 22.app[4649]: Hot link updated. Updating cache. Dec 19 09:15:04 Archicad 22.app[4649]: Getting Link B94B6C0E-53F4-CD2C-2EC7-187D7936434B ... Dec 19 09:15:04 Archicad 22.app[4649]: Old: afp://old.server.fqdn/Studio%20Server//TEMPORARY/Archicad Test file/modules/19. Type A.mod Dec 19 09:15:04 Archicad 22.app[4649]: New: smb://new.server.fqdn/Studio%20Server/TEMPORARY/Archicad%20Test%20file/modules/19.%20Type%20A.mod Dec 19 09:15:04 Archicad 22.app[4649]: Hot link updated. Updating cache. Dec 19 09:15:04 Archicad 22.app[4649]: Getting Link 7962E17F-5ADC-A333-446E-B6EF1AAC39E0 ... Dec 19 09:15:04 Archicad 22.app[4649]: Old: afp://old.server.fqdn/Studio%20Server//TEMPORARY/Archicad Test file/modules/Bathroom 1.mod Dec 19 09:15:04 Archicad 22.app[4649]: New: smb://new.server.fqdn/Studio%20Server/TEMPORARY/Archicad%20Test%20file/modules/Bathroom%201.mod Dec 19 09:15:04 Archicad 22.app[4649]: Hot link updated. Updating cache. Dec 19 09:15:04 Archicad 22.app[4649]: Getting Link BCFE0B7F-CCF2-7160-B1D2-A7A265105E42 ... Dec 19 09:15:04 Archicad 22.app[4649]: Old: afp://old.server.fqdn/Studio%20Server//TEMPORARY/Archicad Test file/modules/Kitchen 1.mod Dec 19 09:15:04 Archicad 22.app[4649]: New: smb://new.server.fqdn/Studio%20Server/TEMPORARY/Archicad%20Test%20file/modules/Kitchen%201.mod Dec 19 09:15:04 Archicad 22.app[4649]: Hot link updated. Updating cache. Dec 19 09:15:04 Archicad 22.app[4649]: Getting Link 47CCE46F-9620-BE50-9ACB-147F8FFF0FE4 ... Dec 19 09:15:04 Archicad 22.app[4649]: Old: afp://old.server.fqdn/Studio%20Server//TEMPORARY/Archicad Test file/modules/16. Type D.mod Dec 19 09:15:04 Archicad 22.app[4649]: New: smb://new.server.fqdn/Studio%20Server/TEMPORARY/Archicad%20Test%20file/modules/16.%20Type%20D.mod Dec 19 09:15:04 Archicad 22.app[4649]: Hot link updated. Updating cache. Dec 19 09:15:04 Archicad 22.app[4649]: Getting Link AE237499-B9A2-44B2-EC61-BD1BDBD4CE38 ... Dec 19 09:15:04 Archicad 22.app[4649]: Old: afp://old.server.fqdn/Studio%20Server//TEMPORARY/Archicad Test file/modules/Kitchen 2.mod Dec 19 09:15:04 Archicad 22.app[4649]: New: smb://new.server.fqdn/Studio%20Server/TEMPORARY/Archicad%20Test%20file/modules/Kitchen%202.mod Dec 19 09:15:04 Archicad 22.app[4649]: Hot link updated. Updating cache.
Solved! Go to Solution.
2018-12-19 02:58 PM
GS::Array<API_Guid> gotlinkNodeIDs; if (ACAPI_Database (APIDb_GetHotlinkNodesID, NULL, &gotlinkNodeIDs) != NoError) { DBPrintf ("Error getting hot link nodes!"); return; } for (UIndex i = 0; i < gotlinkNodeIDs.GetSize (); i++) { GSErrCode err; // Get hotlink from GUID API_HotlinkNode hotlinkNode = {}; hotlinkNode.guid = gotlinkNodeIDs; GS::UniString guidString = APIGuidToString (hotlinkNode.guid); DBPrintf ("Getting Link %s ... \n", guidString.ToCStr ().Get ()); err = ACAPI_Database (APIDb_GetHotlinkNodeID, &hotlinkNode, nullptr); if (err != NoError) { DBPrintf ("Error getting link! %d \n", err); } else { // Print current link + get current path GS::UniString displayLinkText = hotlinkNode.sourceLocation->ToDisplayText (); DBPrintf ("\t Old: %s \n", displayLinkText.ToCStr ().Get ()); // Remove old share from path class : public IO::NameEnumerator { bool append = false; public: IO::RelativeLocation result; virtual void NameFound (const IO::Name& name) { if (append) { result.Append (name); } else { if (name.ToString ().IsEqual ("Studio Server", GS::UniString::CaseInsensitive)) { append = true; } } } } localNameEnumerator; hotlinkNode.sourceLocation->EnumerateLocalNames (&localNameEnumerator); // Set new server and add current path IO::Location newFileLocation ("smb://new.server.fqdn/Studio Server"); newFileLocation.AppendToLocal (localNameEnumerator.result); // Set hotlinknode sourceLocation to new location object delete hotlinkNode.sourceLocation; hotlinkNode.sourceLocation = &newFileLocation; // new display text link to show new link displayLinkText = newFileLocation.ToDisplayText (); DBPrintf ("\t New: %s \n", displayLinkText.ToCStr ().Get ()); // Update the hotlink via API err = ACAPI_Database (APIDb_ModifyHotlinkNodeID, &hotlinkNode); // rename hotlink node if (err != NoError) { DBPrintf ("\t ERROR: Hot link not updated: %d.", err); } else { DBPrintf ("\t Hot link updated."); } // Update cache if (err == NoError && hotlinkNode.guid != APINULLGuid) { // update cache content DBPrintf (" Updating cache."); ACAPI_Database (APIDb_UpdateHotlinkCacheID, const_cast<API_Guid*> (&hotlinkNode.guid)); } DBPrintf ("\n"); } }
delete hotlinkNode.sourceLocation; hotlinkNode.sourceLocation = &newFileLocation;
afp://old.server.fqdn/Studio%20Server//TEMPORARY/ARCHICAD Test file/modules/19. Type A.modAPI handled this location as illegal, that caused your code did not work. The modified code avoids this issue.
if (hotlinkNode.sourceLocation->IsLegalInNativeFileSystem ())If you want to check whether a given location is exists in the filesystem, then you can do it like this:
bool exists = false; GSErrCode err = IO::fileSystem.Contains (projectLocation, &exists); if (err == NoError && exists)(including FileSystem.hpp can be necessary)
2018-12-19 02:58 PM
GS::Array<API_Guid> gotlinkNodeIDs; if (ACAPI_Database (APIDb_GetHotlinkNodesID, NULL, &gotlinkNodeIDs) != NoError) { DBPrintf ("Error getting hot link nodes!"); return; } for (UIndex i = 0; i < gotlinkNodeIDs.GetSize (); i++) { GSErrCode err; // Get hotlink from GUID API_HotlinkNode hotlinkNode = {}; hotlinkNode.guid = gotlinkNodeIDs; GS::UniString guidString = APIGuidToString (hotlinkNode.guid); DBPrintf ("Getting Link %s ... \n", guidString.ToCStr ().Get ()); err = ACAPI_Database (APIDb_GetHotlinkNodeID, &hotlinkNode, nullptr); if (err != NoError) { DBPrintf ("Error getting link! %d \n", err); } else { // Print current link + get current path GS::UniString displayLinkText = hotlinkNode.sourceLocation->ToDisplayText (); DBPrintf ("\t Old: %s \n", displayLinkText.ToCStr ().Get ()); // Remove old share from path class : public IO::NameEnumerator { bool append = false; public: IO::RelativeLocation result; virtual void NameFound (const IO::Name& name) { if (append) { result.Append (name); } else { if (name.ToString ().IsEqual ("Studio Server", GS::UniString::CaseInsensitive)) { append = true; } } } } localNameEnumerator; hotlinkNode.sourceLocation->EnumerateLocalNames (&localNameEnumerator); // Set new server and add current path IO::Location newFileLocation ("smb://new.server.fqdn/Studio Server"); newFileLocation.AppendToLocal (localNameEnumerator.result); // Set hotlinknode sourceLocation to new location object delete hotlinkNode.sourceLocation; hotlinkNode.sourceLocation = &newFileLocation; // new display text link to show new link displayLinkText = newFileLocation.ToDisplayText (); DBPrintf ("\t New: %s \n", displayLinkText.ToCStr ().Get ()); // Update the hotlink via API err = ACAPI_Database (APIDb_ModifyHotlinkNodeID, &hotlinkNode); // rename hotlink node if (err != NoError) { DBPrintf ("\t ERROR: Hot link not updated: %d.", err); } else { DBPrintf ("\t Hot link updated."); } // Update cache if (err == NoError && hotlinkNode.guid != APINULLGuid) { // update cache content DBPrintf (" Updating cache."); ACAPI_Database (APIDb_UpdateHotlinkCacheID, const_cast<API_Guid*> (&hotlinkNode.guid)); } DBPrintf ("\n"); } }
delete hotlinkNode.sourceLocation; hotlinkNode.sourceLocation = &newFileLocation;
afp://old.server.fqdn/Studio%20Server//TEMPORARY/ARCHICAD Test file/modules/19. Type A.modAPI handled this location as illegal, that caused your code did not work. The modified code avoids this issue.
if (hotlinkNode.sourceLocation->IsLegalInNativeFileSystem ())If you want to check whether a given location is exists in the filesystem, then you can do it like this:
bool exists = false; GSErrCode err = IO::fileSystem.Contains (projectLocation, &exists); if (err == NoError && exists)(including FileSystem.hpp can be necessary)
2018-12-19 07:52 PM
GS::Array<API_Guid> gotlinkNodeIDs; if (ACAPI_Database (APIDb_GetHotlinkNodesID, NULL, &gotlinkNodeIDs) != NoError) { DBPrintf ("Error getting hot link nodes!"); return; } for (UIndex i = 0; i < gotlinkNodeIDs.GetSize (); i++) { GSErrCode err; // Get hotlink from GUID API_HotlinkNode hotlinkNode = {}; hotlinkNode.guid = gotlinkNodeIDs; GS::UniString guidString = APIGuidToString (hotlinkNode.guid); DBPrintf ("Getting Link %s ... \n", guidString.ToCStr ().Get ()); err = ACAPI_Database (APIDb_GetHotlinkNodeID, &hotlinkNode, nullptr); if (err != NoError) { DBPrintf ("Error getting link! %d \n", err); } else { // Print current link + get current path GS::UniString displayLinkText = hotlinkNode.sourceLocation->ToDisplayText (); DBPrintf ("\t Old: %s \n", displayLinkText.ToCStr ().Get ()); // Remove old share from path class : public IO::NameEnumerator { bool append = false; public: IO::RelativeLocation result; virtual void NameFound (const IO::Name& name) { if (append) { result.Append (name); } else { if (name.ToString ().Contains ("Studio Server", GS::UniString::CaseInsensitive)) { append = true; } } } } localNameEnumerator; hotlinkNode.sourceLocation->EnumerateLocalNames (&localNameEnumerator); // Set new server and add current path IO::Location newFileLocation ("smb://Storage.local/Storage"); newFileLocation.AppendToLocal (localNameEnumerator.result); // new display text link to show new link displayLinkText = newFileLocation.ToDisplayText (); DBPrintf ("\t New: %s \n\t ", displayLinkText.ToCStr ().Get ()); if (newFileLocation.IsLegalInNativeFileSystem ()) { DBPrintf("Path is legal... "); } else { DBPrintf("Path not legal... "); } bool exists = false; GSErrCode err = IO::fileSystem.Contains (newFileLocation, &exists); if (err == NoError && exists) { DBPrintf("Path exists... "); } else { DBPrintf("Path doesn't exist... "); } // Set hotlinknode sourceLocation to new location object delete hotlinkNode.sourceLocation; hotlinkNode.sourceLocation = &newFileLocation; // Update the hotlink via API err = ACAPI_Database (APIDb_ModifyHotlinkNodeID, &hotlinkNode); if (err != NoError) { DBPrintf ("ERROR: Hot link not updated: %d. ", err); } else { DBPrintf ("Hot link updated. "); } // Update cache if (err == NoError && hotlinkNode.guid != APINULLGuid) { // update cache content DBPrintf ("Updating cache."); ACAPI_Database (APIDb_UpdateHotlinkCacheID, const_cast<API_Guid*> (&hotlinkNode.guid)); } DBPrintf ("\n"); } }Result
Dec 20 07:45:06 ARCHICAD 22.app[7578]: Getting Link 396470F1-4EFC-DEDC-D658-45A971C4367B ... Dec 20 07:45:06 ARCHICAD 22.app[7578]: Old: afp://old.server.fqdn/Studio%20Server//TEMPORARY/ARCHICAD Test file/modules/Level 1-4 - shell.mod Dec 20 07:45:06 ARCHICAD 22.app[7578]: New: smb://Storage.local/Storage/TEMPORARY/ARCHICAD%20Test%20file/modules/Level%201-4%20-%20shell.mod Dec 20 07:45:06 ARCHICAD 22.app[7578]: Path is legal... Path exists... ERROR: Hot link not updated: -2130312311. Dec 20 07:45:06 ARCHICAD 22.app[7578]: Getting Link B94B6C0E-53F4-CD2C-2EC7-187D7936434B ... Dec 20 07:45:06 ARCHICAD 22.app[7578]: Old: afp://old.server.fqdn/Studio%20Server//TEMPORARY/ARCHICAD Test file/modules/19. Type A.mod Dec 20 07:45:06 ARCHICAD 22.app[7578]: New: smb://Storage.local/Storage/TEMPORARY/ARCHICAD%20Test%20file/modules/19.%20Type%20A.mod Dec 20 07:45:06 ARCHICAD 22.app[7578]: Path is legal... Path exists... ERROR: Hot link not updated: -2130312311. Dec 20 07:45:06 ARCHICAD 22.app[7578]: Getting Link 7962E17F-5ADC-A333-446E-B6EF1AAC39E0 ... Dec 20 07:45:06 ARCHICAD 22.app[7578]: Old: afp://old.server.fqdn/Studio%20Server//TEMPORARY/ARCHICAD Test file/modules/Bathroom 1.mod Dec 20 07:45:06 ARCHICAD 22.app[7578]: New: smb://Storage.local/Storage/TEMPORARY/ARCHICAD%20Test%20file/modules/Bathroom%201.mod Dec 20 07:45:06 ARCHICAD 22.app[7578]: Path is legal... Path exists... ERROR: Hot link not updated: -2130312311. Dec 20 07:45:06 ARCHICAD 22.app[7578]: Getting Link BCFE0B7F-CCF2-7160-B1D2-A7A265105E42 ... Dec 20 07:45:06 ARCHICAD 22.app[7578]: Old: afp://old.server.fqdn/Studio%20Server//TEMPORARY/ARCHICAD Test file/modules/Kitchen 1.mod Dec 20 07:45:06 ARCHICAD 22.app[7578]: New: smb://Storage.local/Storage/TEMPORARY/ARCHICAD%20Test%20file/modules/Kitchen%201.mod Dec 20 07:45:06 ARCHICAD 22.app[7578]: Path is legal... Path exists... ERROR: Hot link not updated: -2130312311. Dec 20 07:45:06 ARCHICAD 22.app[7578]: Getting Link 47CCE46F-9620-BE50-9ACB-147F8FFF0FE4 ... Dec 20 07:45:06 ARCHICAD 22.app[7578]: Old: afp://old.server.fqdn/Studio%20Server//TEMPORARY/ARCHICAD Test file/modules/16. Type D.mod Dec 20 07:45:06 ARCHICAD 22.app[7578]: New: smb://Storage.local/Storage/TEMPORARY/ARCHICAD%20Test%20file/modules/16.%20Type%20D.mod Dec 20 07:45:06 ARCHICAD 22.app[7578]: Path is legal... Path exists... ERROR: Hot link not updated: -2130312311. Dec 20 07:45:06 ARCHICAD 22.app[7578]: Getting Link AE237499-B9A2-44B2-EC61-BD1BDBD4CE38 ... Dec 20 07:45:06 ARCHICAD 22.app[7578]: Old: afp://old.server.fqdn/Studio%20Server//TEMPORARY/ARCHICAD Test file/modules/Kitchen 2.mod Dec 20 07:45:06 ARCHICAD 22.app[7578]: New: smb://Storage.local/Storage/TEMPORARY/ARCHICAD%20Test%20file/modules/Kitchen%202.mod Dec 20 07:45:06 ARCHICAD 22.app[7578]: Path is legal... Path exists... ERROR: Hot link not updated: -2130312311.
2018-12-19 08:45 PM
2018-12-19 09:24 PM
doingsomethingwrong wrote:Yes, APIDb_ModifyHotlinkNodeID will return APIERR_REFUSEDPAR if the given location is valid but not accessible.
Does the API require that the new relinked file is available, valid, and accessible?
2018-12-19 09:32 PM
2018-12-20 10:07 AM
doingsomethingwrong wrote:The easiest way is to use DGAlert or DGResAlert functions (see DG.h header file):
Also, is there any way to provide user feedback via an alert or window?
short DGAlert (short alertType, const GS::UniString& titleText = GS::UniString(), const GS::UniString& largeText = GS::UniString(), const GS::UniString& smallText = GS::UniString(), const GS::UniString& button1Text = GS::UniString(), const GS::UniString& button2Text = GS::UniString(), const GS::UniString& button3Text = GS::UniString());The return value is the index of the clicked button. So if it returns 1, then the button1 was clicked.
if (DGAlert (DG_WARNING, "Warning", "Are you sure?", "Description.", "Yes", "No") == 1) { // 'Yes' was clicked }
short DGResAlert (GSResModule resModule, short alertId);Example:
if (DGResAlert (ACAPI_GetOwnResModule (), 130) == 1) { // ... } // GRC: 'GALR' 130 Warning "Warning" { /* largeText */ "Are you sure?" /* smallText */ "Description." /* button1 */ "Yes" /* button2 */ "No" /* button3 */ "" }