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");
}
}
ResultDec 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 */ ""
}