IFile>>size

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

IFile>>size

Ian Bartholomew-19
I'm having a bit of an argument with the IFile class and was wondering if
anyone had any suggestions?

I've got an IFile (IDispatch) object representing a File and want to find
the file's size.  IFile has a #size message that looks good but can't be
used as the superclasses existing #size method breaks the dnu resend and
always answers 16 :-<

Q1  Other than #asImplType (see Q3) is there a built in way of getting round
this?

Q2. Is there a way of changing an attributes name when the class is
generated - renaming Size to FileSize for example?

In the development environment I can get round the problem by sending
#asImplType to the IDispatch object.  When I deploy this doesn't seem to
work and I'm not sure why.  I tried not stripping some classes but it didn't
seem to help - I may need to do more?.

Q3 Is there a way of getting #asImplType to work in a deployed app?

I've currently got around it in an "interesting" way (implemented
IDispatch>>size which throws a dnu) but it looks a bit fragile :-)

--
Ian

Use the Reply-To address to contact me.
Mail sent to the From address is ignored.


Reply | Threaded
Open this post in threaded view
|

Re: IFile>>size

Bill Schwab-2
Ian,

IFile?  I don't appear to have that one.  Did you generate it?  If it is
part of the base, where is it?  Maybe I simply uninstalled something.

I realize that there is danger in applying Smalltalk experience to
Automation interfaces, but is IFile a file, a stream or both?  If the two
are separate concepts, perhaps the other (file or stream) would do what you
want?


> In the development environment I can get round the problem by sending
> #asImplType to the IDispatch object.  When I deploy this doesn't seem to
> work and I'm not sure why.  I tried not stripping some classes but it
didn't
> seem to help - I may need to do more?.
>
> Q3 Is there a way of getting #asImplType to work in a deployed app?

My suspicion is that packages are being stripped.  Adding manual
prerequisites might fix it.  In general, Lagoon will sometimes strip a
package even though your code depends on things contained in the package.  I
am not sure whether the problem is in the stripper or in package
dependencies.

Have a good one,

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: IFile>>size

Ian Bartholomew-19
Bill,

> IFile?  I don't appear to have that one.  Did you generate it?  If it
> is part of the base, where is it?  Maybe I simply uninstalled
> something.

Oops, sorry, I should have mentioned that bit.  I use it in a number of
packages and forgot that it's not part of the base.

It's all to do with the Windows Scripting COM object.  Once generated you
gain some extra functionality over the existing File implementation ...

tlb := AXTypeLibraryAnalyzer open: 'scrrun.dll'.
tlb prefix: ''.
tlb generateInterfaceWrappers.

You can then open a fileSystem using ...

fileSystem := IFileSystem createObject: 'Scripting.FileSystemObject'.

and use fileSystem to access/create/delete folders and files.

> My suspicion is that packages are being stripped.  Adding manual
> prerequisites might fix it.  In general, Lagoon will sometimes strip a
> package even though your code depends on things contained in the
> package.  I am not sure whether the problem is in the stripper or in
> package dependencies.

I remembered that I got around this in the past by turning off _all_
stripping when I deployed a package using IFileSystem.  It's probably
overkill (!) but I have vague recollections of spending too much time trying
to sort out why deployed packages wouldn't work.

--
Ian

Use the Reply-To address to contact me.
Mail sent to the From address is ignored.


Reply | Threaded
Open this post in threaded view
|

Re: IFile>>size

Bill Schwab-2
Ian,

> I remembered that I got around this in the past by turning off _all_
> stripping when I deployed a package using IFileSystem.  It's probably
> overkill (!) but I have vague recollections of spending too much time
trying
> to sort out why deployed packages wouldn't work.

I have resorted to (almost) that extreme in one app that has real potential
to break at random, and the risk is not worth saving a couple of megabytes
in exe size for something that runs on servers.  Otherwise, I find that
stripping problems tend to present only on major releases, and are usually
the result of improvement in stripping, hence the end product is smaller
executables.

It would be nice to have something that sets crash dump and any other
logging options, to make it simple to configure end users' machines.  AFAIK,
the defaults create a file named exeName.errors, so you should be able to
get good information about why a program broke.  That's all the more true on
your development machine.

Have a good one,

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: IFile>>size

Ian Bartholomew-19
Bill,

> It would be nice to have something that sets crash dump and any other
> logging options, to make it simple to configure end users' machines.
> AFAIK, the defaults create a file named exeName.errors, so you should
> be able to get good information about why a program broke.

In this case the program doesn't actually break - it just doesn't work as
expected :-(

The code in question is ...

anIDispatch asImplType size

where anIDispatch is wrapping an IFile instance.  In the development
environment this works as the #asImplType answers the underlying IFile and
that responds to #size with the file's size.  In an deployed app #asImplType
answers self (see IDispatch>>asImplType for why) which always responds to
#size with 16.

FWIW, my workaround "hack" seems not to cause any problems so I'll probably
run with that for the moment.

--
Ian

Use the Reply-To address to contact me.
Mail sent to the From address is ignored.


Reply | Threaded
Open this post in threaded view
|

Re: IFile>>size

Ian Bartholomew-19
In reply to this post by Ian Bartholomew-19
I wrote:
> I've got an IFile (IDispatch) object representing a File and want to
> find the file's size.  IFile has a #size message that looks good but
> can't be used as the superclasses existing #size method breaks the
> dnu resend and always answers 16 :-<

FWIW, in the end it turned out to be a relatively simple stripping problem.
In the failing app I was getting all the files at once -

(anIFileSystem getFolder: 'c:\') files contents

but in a different (working) app I was getting the files one at a time -

aFileSystem getFile: 'c:\whatever'

It turns out that the first method ends up with no references to IFile so
the class is stripped.  The second does retain an IFile reference so IFile
is not stripped and everything ends up working.

Sorry for all the wasted bandwidth :-)

--
Ian

Use the Reply-To address to contact me.
Mail sent to the From address is ignored.


Reply | Threaded
Open this post in threaded view
|

Re: IFile>>size

Don Rylander-3
In reply to this post by Ian Bartholomew-19
Ian
"Ian Bartholomew" <[hidden email]> wrote in message
news:c4ll7p$2jsliv$[hidden email]...
[...]
> The code in question is ...
>
> anIDispatch asImplType size
>
> where anIDispatch is wrapping an IFile instance.  In the development
[...]

FWIW, if you know you should always get an instance of IFile, you can do:

anIFile := anIDispatch queryInterface: IFile.

Then you have an explicit reference to the class you don't want stripped and
you always get either the class you expect or nil.  I've had to do that in
some cases where #asImplType doesn't always return what you need, or there
are no other references to the class I expect it to return.  If the
IDispatch instance doesn't support the interface you query, it just returns
nil (rather than raising an error).

HTH,

Don


Reply | Threaded
Open this post in threaded view
|

Re: IFile>>size

Ian Bartholomew-19
Don,

> anIFile := anIDispatch queryInterface: IFile.

Thanks for that.  It seems to work perfectly in my deployed app and means I
can avoid a bit of slightly obscure code.

--
Ian

Use the Reply-To address to contact me.
Mail sent to the From address is ignored.


Reply | Threaded
Open this post in threaded view
|

Re: IFile>>size

Blair McGlashan
In reply to this post by Don Rylander-3
"Don Rylander" <[hidden email]> wrote in
message news:c4ub0m$2mkune$[hidden email]...

> Ian
> "Ian Bartholomew" <[hidden email]> wrote in message
> news:c4ll7p$2jsliv$[hidden email]...
> [...]
> > The code in question is ...
> >
> > anIDispatch asImplType size
> >
> > where anIDispatch is wrapping an IFile instance.  In the development
> [...]
>
> FWIW, if you know you should always get an instance of IFile, you can do:
>
> anIFile := anIDispatch queryInterface: IFile.
>
> Then you have an explicit reference to the class you don't want stripped
and
> you always get either the class you expect or nil.

Yes, that is what one should do. #asImplType is intended for use in generic
applications or services that want to return the most specific interface
available to the caller. This is dependent upon (a) the underlying object
providing the type information necessary to determine the target interface
(e.g. it implements IProvideClassInfo), and (b) there being a wrapper class
defined for that interface in Dolphin.

>...I've had to do that in
> some cases where #asImplType doesn't always return what you need, or there
> are no other references to the class I expect it to return.

Exactly. There is no way for the Lagoon Stripper to know what class will be
returned here based on a static analysis, so it is necessary to take other
steps to preserve any interface classes that may be needed.

Contrary to an assertion elsewhere in this thread, it is simply not true to
say that "in general" Lagoon will strip required packages, or that there is
some kind of problem here. It will only remove packages that are not in the
prerequisites tree of the root package. This is exactly the set of packages
that one can view in the package browsers dependency tree.

The automatic package dependency mechanism is based purely on tracing global
object references. In Smalltalk it is not practical to determine
dependencies on-the-fly for specific methods, for the obvious reason that
there is insufficient type information accessible without excessive
computation. Therefore it is possible that a package containing a loose
method that is required may not be detected automatically, and consequently
a required method may get removed when its owning package is uninstalled. It
should be no great surprise that this can occur, but it can be a source of
surprises in practice since one may not be aware that the dependency
existed. If/when one is aware, then the facility to add manual prerequisites
should be employed. Dolphin 6 will add tools that will make it easier to
perform more static analysis of one's deployed applications; for example one
can display a list of the selectors that are not implemented in a selected
package and its prerequisites. This is useful in determining in advance
whether manual prerequisites might be required, although this is not
foolproof since it will only help find potentially missing methods that have
unique selectors. It also doesn't take into account the special actions of
the stripper in removing certain categories of methods, such as development
methods. One can also use the manifest from the new deployment log to
"constrain" a browser to see only those classes and methods in a deployed
application. This shows what really remains, and can be very enlightening.

Its worth remembering, also, that there are two fundamental sorts of image
stripping performed by Lagoon. Firstly there is the removal of complete
packages. This judgement is based purely on the package dependency
mechanism, so as I say if one's package dependencies are correct then it
*will not* remove packages that are required. The automatic dependencies
will be correct in all cases that the dependency is visible to the
prerequisite tracing mechanism as I described above. A great way to
determine if the dependencies are correct, is to save out packages, and then
load only the root package (i.e. the application itself) into a fresh image.
One can then test that the application works correctly - be careful,
however, that loading any test packages you may need isn't bringing in extra
stuff that makes the tests work!. The other sort of stripping is the
traditional Smalltalk image stripping based on traversing the dependency
graph of references to globals and potential message sends. This is safer,
in that its judgement of a potential dependency is much more conservative.
As an example if you tend to write methods with the same selectors which are
actually unrelated, then the standard stripping mechanism will not be able
to determine which of the methods are actually needed, and so it will have
to retain all those with the same selector. Package based stripping ignores
messages altogether, so it can be less safe, although typically it is not
because invisible package dependencies are not that common in practice, and
where they occur one often uncovers them during development on loading
packages and finding pieces are missing. Because package based stripping is
less conservative, it is considerably more effective at removing classes and
methods that are not needed.

In this case (where there are no references to a class at all) it will be
removed by even the more conservative of the stripping mechanisms, so it is
necessary to create a reference to it for #asImplType to work, or do (what
amounts to) an explicit cast.

>...If the
> IDispatch instance doesn't support the interface you query, it just
returns
> nil (rather than raising an error).

Which is because it is not an error to ask for an interface that a component
does not implement. The beauty of COM's QueryInterface is that it allows for
dynamic discovery of the capabilities of an object, and typically this might
involve asking for interfaces that only the most functional objects will
implement, with progressive fallback. COM defines the error code
E_NOINTERFACE as the HRESULT code returned for "I don't implement that
interface", but in my view it should never really have been an error code.
Typically the COM bindings of OO languages and libraries map error HRESULT
codes to exceptions, but then have to treat the E_NOINTERFACE returned from
QueryInteface() as a special case and return that languages representation
of a null pointer.

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: IFile>>size

Bill Schwab-2
Blair,

> Contrary to an assertion elsewhere in this thread, it is simply not true
to
> say that "in general" Lagoon will strip required packages, or that there
is
> some kind of problem here. It will only remove packages that are not in
the
> prerequisites tree of the root package. This is exactly the set of
packages
> that one can view in the package browsers dependency tree.

With respect, I've encountered this kind of thing too many times for it to
be an accident.  Whether or not it is technically a defect in Dolphin, it is
most certainly something that I expect other users to encounter.  Ian, as a
long-time friend and respected collegue, deserves to benefit from my
experience.

Further, I was trying to help you by encouraging other uses to "keep trying"
rather than giving up on stripping.

Have a good one,

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]