Developer forum
cancel
Showing results for 
Search instead for 
Did you mean: 

IO Error question

TomWaltz
Newcomer
In the API documentation, there is a section on Input and Output. I have been looking at the sections on copying and deleting files, namely FileSystem::Copy.

It says there that most of the errors are "declared in FileSystem class scope."

(OK, this may be a C++ question, not an API question, I'm not sure).

As a result, all of my error checking statements, i.e.: if (err == SourceNotFound) return an error that "SourceNotFound" is an invalid identifier".

It seems that all the global scope error messages work. (no surprise).

I have file.hpp and filesystem.hpp included already, which I thought might be the problem.

I've tried fileSystem.SourceNotFound and fileSystem::SourceNotFound, with no luck.

How do I get a pre-defined error value from the FileSystem class scope to work in mine?
Tom Waltz
12 REPLIES 12

Oleg
Advocate
TomWaltz wrote:
How do I get a pre-defined error value from the FileSystem class scope to work in mine?
I think it is a documentation mistake. I dont see the SourceNotFound error code in the FileSystem.
I think:

if (err == IO::FileSystem::FileNotFound)

or if you have "using namespace IO", than just

if (err == FileSystem::FileNotFound)

Ralph Wessel
Mentor
TomWaltz wrote:
As a result, all of my error checking statements, i.e.: if (err == SourceNotFound) return an error that "SourceNotFound" is an invalid identifier".
I've tried fileSystem.SourceNotFound and fileSystem::SourceNotFound, with no luck.
Are you looking for IO::Folder::SourceNotFound?

In C++, this statement identifies the scope of 'SourceNotFound' as the class 'Folder', and the scope of 'Folder' is the namespace 'IO'. This means the API can be combined with other sources which define a class called 'Folder' or an enumerator called 'SourceNotFound' without ambiguity.
Ralph Wessel BArch

TomWaltz
Newcomer
"IO::Folder::SourceNotFound" was it.

I've not dealt with namespaces enough to catch that one.

Thanks, guys!
Tom Waltz

Oleg
Advocate
Just tried it. Ralph is right, the error code is defined in Folder class.

Hmm.., It is "interesting" class design, to return an error code defined in the Folder class from a FileSystem member function. A puzzle.

Karl Ottenstein
Moderator
Thanks, Ralph and Oleg! Good question, Tom - thanks for asking ... keep 'em coming. As with AC-talk, questions here provide an opportunity for all of us to look more deeply at something, or to get a quick fix. This was useful for me since I hadnt really looked at the IO module much.

I agree with Oleg - this is a strange puzzle of programming and documentation! Any additional comments here and as we go along can only help GS to refine the API and the documentation, so keep it coming. 😉

Each class in the IO namespace defines error codes presumably for that class, but as we saw here, SourceNotFound is in the Folder class but returned by a function in the FileSystem class. I just looked at another one - FileSystem::Copy can return TargetExists, but that name is also in the Folder class.

Whether the documentation should be edited or the code fixed for these kinds of things is up to GS of course. Personally, I would rather see the return type be something like FileSystemErrCode (an enumerated type of allowable errors for FileSystem objects) rather than the universal GSErrCode (long).

Ideas for better documentation in this area?

I'd like to see the namespace prefix on each page: rather than seeing "FileSystem::Copy" at the top of the page with nothing on the page to remind me that it is inside IO, I'd prefer "IO:FileSystem::Copy", with a hyperlink on IO as well as the one we now see for FileSystem.

I'd like to see different symbols, perhaps *, ** and *** for the footnotes of the return value (and of course have the footnotes on all pages corrected to show the proper classes...or fix the classes themselves). With the current color-coded footnotes - see screenshot - you can't distinguish things when printed in black/white.

Finally, since I was looking at the Folder class docs as well as hpp files ... it would be nice if the prototypes of all overloaded variants of a function were listed at the top of a page, hyperlinked to the descriptions below. For example, take a look at the page for Folder::Copy. By scrolling, one sees that there are three variants. I'd like to see:
virtual GSErrCode  Copy (const Name& from,  const Name& to);

virtual GSErrCode  Copy (const Name& from,  Folder& target, const Name& to);

virtual GSErrCode  Copy (const Name& from,  Folder& target, const Name& to) const;
right at the top, maybe with a one line summary, hyperlinked. (I'm not sure what I think about the subtle difference between the last two variants, or the fact that the last one does a runtime check that 'from' and 'target' are different - yet there is no unique/defined error return value documented for that event.)

My 2 cents for Saturday. 😉

Karl
One of the forum moderators   •   AC 25 USA and earlier   •   MacOS 11.6.1, iMac Pro

Ralph Wessel
Mentor
Oleg wrote:
Hmm.., It is "interesting" class design, to return an error code defined in the Folder class from a FileSystem member function. A puzzle.
I think the difficulty exists primarily for us because GS is too stretched to fill in the blanks in the documentation - not a criticism, just a fact of life for a development team.
It helps if you think of this part of the API in terms of objects. The 'FileSystem' class represents an upper tier of functionality for handling other objects which notionally represent files as 'Location' objects. Without commenting on the merits of the design, the class is essentially a wrapper for the old File Manager. The FileSystem class doesn't necessarily know anything specific about the Locations you provide, and therefore it makes sense that error conditions are defined by and returned from the objects which can encounter specific error conditions.

For example, if you give a 'FileSystem' object a Location 'object' that refers to a 'Folder' object, and the folder object 'knows' that it isn't physically represented anywhere, it returns the message 'SourceNotFound'. Or if you are overwriting an existing physical folder, it would return 'TargetExists'. The error conditions have more meaning because they are defined in a narrower context. IMHO this is better than a single huge list of error codes.
Ralph Wessel BArch

TomWaltz
Newcomer
OK.... I'm having many other frustrations with this whole concept, since the Folder::Copy and fileSystem.Copy seem to work totally differently, and the Folder::Errors are not compatible with the fileSystem.Copy error messages, the the filesystem::Errors and filersystem.Errors aren't working right....

Maybe the question I SHOULD have asked is this:
Can Archicad call an outside shell script? (on a Mac)

Thanks!!
Tom Waltz

Ralph Wessel
Mentor
TomWaltz wrote:
Maybe the question I SHOULD have asked is this:
Can Archicad call an outside shell script? (on a Mac)
You can call anything you like, but the support isn't in the ArchiCAD API. You need to use the Mac OS itself.
Could we step back a bit - what are you trying to do? This may help other readers to propose the solution you're really looking for?

This suggestion comes up regularly in other Dev lists, and it's a good one to consider here. If you have a question, some background information can mean your question is answered much faster, e.g. what you are trying to accomplish, a snippet of your code, what you tried already...
Ralph Wessel BArch

Oleg
Advocate
Ralph wrote:
For example, if you give a 'FileSystem' object a Location 'object' that refers to a 'Folder' object, and the folder object 'knows' that it isn't physically represented anywhere, it returns the message 'SourceNotFound'. Or if you are overwriting an existing physical folder, it would return 'TargetExists'. The error conditions have more meaning because they are defined in a narrower context. IMHO this is better than a single huge list of error codes.
I am not against more meaning error codes of course.
Graphisoft developers have chosen to define local error codes for a class inside this class. ОК. Why not.
But IMHO, in this case it is more logical, when error codes returned by members functions of the class would be or general ( like NoError, Error) or defined in this class only. Otherwise the interface of FileSystem class actually depends on its implementation. What happens, if later the implementation of FileSysten::Copy function will change and will not use the Folder class anymore.
I think what in this case enough to define it as:

class FileSystem {
...
  enum
 {
  ...
  SourceNotFound=Folder::SourceNotFound
  ...
  };
...
};
PS:
Actually, I think, that it was supposed to make as described in the documentation and it was just a bug in the FileSistem class.
All of us do plenty of bugs.

TomWaltz
Newcomer
This goes back to my desire to make my Archicad add-on self updating.

My idea was that when our next Archicad disk image is deployed, it would contain a copy of our in-house add-on.

Obviously, the add-on runs while Archicad is running. The idea is that whenever Archicad is quit, the Notification Manager tells the Add-on to look in a specified folder on the network. If there is an update there, it will copy the update, over-writing the Add-on currently on the local hard drive.

I have all the logic working inside the add-on. My problem is with the file operations, namely copying the file from the network location to the local folder.

Since IO::fileSystem.Copy cannot overwrite files, I had to add a routine to delete the file, then try again:
const char* networkFileLocation = "Public:CAD_Standards:KA-Update:KA-Add-On"; 
const char* localFileLocation = "Local_Disk:Applications:ArchiCAD 8.1 folder:Add-Ons:KA:KA-Add-On";
		
// define Location objects
IO::Location 	networkFile (networkFileLocation);
IO::Location 	localFile (localFileLocation);

GSErrCode 	err;    
GSErrCode	err2;	// temporary to help track down delete failure
err = IO::fileSystem.Copy (networkFile, localFile);
if (err == IO::Folder::SourceNotFound)
	{
		char    msgStr[256];
		CHCopyC ("Error, Source not found", msgStr);   
		ACAPI_WriteReport (msgStr, false); 
	}
else if (err == IO::Folder::TargetExists)
	{
		err2 = IO::fileSystem.Delete(localFile);
		if (err2) 
			{
				char    msgStr[256];
				CHCopyC ("Delete Failed", msgStr);   
				ACAPI_WriteReport (msgStr, false); 
				return;
			}
		IO::fileSystem.Copy(networkFile, localFile);

		char    msgStr[256];
		CHCopyC ("Updated from source", msgStr);   
		ACAPI_WriteReport (msgStr, false); 
	}
return;
I cannot figure out while I keep getting the "Delete failed" message, and the Delete function fails. I suspect that is may have to do with the mixture of fileSystem and Folder namespaces/object behavior.

At that point, I began to think about using an external shell script, called when Archicad is quit.

As I've said before, since updates of our inhouse add-on is a sporadic but unpredictable event, and a CAD issue, not really an IT one, we wanted to make it as self contained as possible, namely by making the add-on copy itself whenever needed.

Thanks!!
Tom Waltz

Andras Babos
Graphisoft Alumni
Graphisoft Alumni
"TomWaltz" wrote:

I cannot figure out while I keep getting the "Delete failed" message, and the Delete function fails. I suspect that is may have to do with the mixture of fileSystem and Folder namespaces/object behavior.


I'm afraid your problem is system- not ArchiCAD-related. You get a Delete Failed message because you are trying to delete a DLL (your Add-On) which is actually running. Your program is basically trying to delete itself!

What you can do is use a separate Add-On, which does nothing else just updates your original Add-On. Just make sure first that the original Add-On is already unloaded.

HTH:
Andras.

TomWaltz
Newcomer
What you can do is use a separate Add-On, which does nothing else just updates your original Add-On. Just make sure first that the original Add-On is already unloaded.
Wow, you read my mind.

That's exactly what I just now ended up doing. It makes sense that an executable cannot delete itself, but it sure was entertaining to try!!
Tom Waltz

Still looking?

Browse more topics

Back to forum

See latest solutions

Accepted solutions

Start a new discussion!