Can you override a Publicnoncreatable program to apply its TLB? - vb.net

I have referenced the SketchUp.exe into a project or at times an extracted TLB from the SketchUp.exe and can see the object model but cannot create an instance of any object in it.
I found out it may be a non-shared object or set to PublicNoncreatable and thus unlike AutoCAD or Excel I cannot create object instances.
When working with Adobe Acrobat I found it had the same problem but had a non-viewable object name which allowed instancing its objects.
Maybe SketchUp also has a completely hidden object or method that allows this. In the mean time is there a way to apply and instance of the object by overriding its non-share status as shared?

SketchUp's COM API is no longer supported. You may want to take a look at the new C API.

Related

Adding new members and extending methods in an external API interface

I am building an VB.NET application in Visual Studio using SOLIDWORKS API - my application connects to SOLIDWORKS application via COM, and performs some actions in it using various API calls. The API is accessed by adding project references to SOLIDWORKS .dll files. These files must be embedded to the executable of my application for legal reasons.
This question is not specific to that API, but I will try to explain what I want to do. There is a SOLIDWORKS API interface called Body2 that governs manipulation of model objects (bodies) in 3D space. For example, Body2 interface provides a method ApplyTransform that allows moving or rotating a certain body by applying a MathTransform (a transform matrix) to it:
ModelBody.ApplyTransform(rotationMatrix) 'rotates the body
Now, the Body2 objects do not store these transformation matrices - they are applied and forgotten. However, in my application, I need to persistently store that information, so that at some point, I can reverse all transformations, and return the body to it's original position.
Therefore, I want to extend the Body2 interface by adding a new property to it, called "CombinedTransformMatrix", so that every time I call ApplyTransform, I could also update the value of this property, for example:
ModelBody.ApplyTransform(rotationMatrix)
ModelBody.CombinedTransformMatrix.Multiply(rotationMatrix)
ModelBody.ApplyTransform(translationMatrix)
ModelBody.CombinedTransformMatrix.Multiply(translationMatrix)
And when I finally want to return the body to it's original position, I could call:
ModelBody.ApplyTransform(ModelBody.CombinedTransformMatrix.Inverse)
ModelBody.CombinedTransformMatrix = New MathTransform 'reset matrix
Ideally, it would be really nice to also extend the ApplyTransform method, so that it would update the CombinedTransformMatrix automatically, for example:
Overrides Function ApplyTransform(Xform As MathTransform) As Boolean
'Do whatever SOLIDWORKS does in this function
'My additional code:
Me.CombinedTransformMatrix.Multiply(Xform)
End function
(I know I should do an extension rather than an override, but I don't know how)
If this is possible, then I could simplify the code for the body transformations, as the CombinedTransformMatrix would update automatically:
'Rotate and move
ModelBody.ApplyTransform(rotationMatrix)
ModelBody.ApplyTransform(translationMatrix)
'Return to original position
ModelBody.ApplyTransform(ModelBody.CombinedTransformMatrix.Inverse)
ModelBody.CombinedTransformMatrix = New MathTransform 'reset matrix
I would very much prefer this kind of a solution instead of creating some derived class from Body2, or making some kind of a wrapper class that stores CombinedTransformMatrix outside the Body2 object. I want to store that bit inside the object itself. As for derived class, Visual Studio doesn't even allow me to inherit from Body2 - says "'Body2Class' is not allowed when its assembly is configured to embed interop types.". And I must embed these .dll files because otherwise I would have to ship them along the .exe of my application, which is legally prohibited by SOLIDWORKS.
Is what I want possible? Can I add that CombinedTransformMatrix to the Body2 interface without creating a derived class? And is it possible to extend that ApplyTransform method with my additional code without knowing how that method is implemented?
If not, what is the next best solution to achieve what I want? Like I said, I would very much like to avoid wrappers or additional variables outside of Body2, because there will be lots of these Body2 objects, they will persist throughout the application's lifetime, each will have a different transformation, so having to store their transformation information outside themselves would seriously complicate my code.
There is no universal way of doing this. You can maintain the separate dictionary with your COM object (e.g. IBody2 in this case) to be a key and the additional parameters (tags) to be a value. You will need to manually update the dictionary to remove the data when the pointer is destroyed. There are however some specific SW interfaces that do have some ways to associate custom data (similar to tags). For instance, IBody2 has the IBody2::AddPropertyExtension2 which allows associating custom data with the body itself, IEntity has the IEntity::CreateStringAttributeDefinition (note, this is not documented method) etc.
But there is no something like universal System::Windows::Forms::Tag property for Windows Controls or Dependency Property for DependencyObjects exists for COM classes.

Providing my own objects for "make new" in my scriptable application

This is a question about implementing a scriptable application using Cocoa Scripting.
My app's scriptable application object contains elements of a custom class, let call it flower.
In the .sdef file, the Cocoa class for flower is specified as ScriptableFlower.
In Applescript, one can now write:
tell app "myapp"
get flowers
end tell
My code provides an accessor function for retrieving flowers: -(NSArray*)flowers.
Now, I like to implement a way to add new flowers, so that one can write:
tell app "myapp"
make new flower
end tell
The default behavior for this, with the default Core suite handler for "make" using NSCreateCommand, is as follows:
The scripting engine will fetch the current array of flowers by calling my flowers function, then instantiate a new Cocoa object of class ScriptableFlower, and then call setFlowers:(NSArray*) with an array that contains my original objects plus the newly created one.
However, this is not good for my application: I cannot allow the scripting engine to create objects of my scriptable classes at will.
Instead, I need to be the one instantiating them.
A half-way solution would be to implement the default -(id)init method and then detect if it's called by me - if not, I can take the extra steps. But that's not clean. I rather do not let the scripting engine create new objects at all but rather provide them myself as I may have the object "somewhere" already prepared.
Is there some provision in Cocoa Scripting that leads to it calling me whenever it wants me to create a new scriptable object?
Update
To clarify: The Cocoa Scripting docs explains that one can implement special insertion handlers (insertObject:in<Key>AtIndex:)so that one doesn't have to take the entire NSArray, but that still leads to the scripting engine to create the object. I need to be asked to create the object instead, though.
The file NSObjectScripting.h provides a function for this:
- (id)newScriptingObjectOfClass:(Class)objectClass forValueForKey:(NSString *)key withContentsValue:(id)contentsValue properties:(NSDictionary *)properties;
It's available since OS X 10.5 and documented as follow:
Create a new instance of a scriptable class to be inserted into the relationship identified by the key, set the contentsValue and properties of it, and return it. Or return nil for failure. The contentsValue and properties are derived from the "with contents" and "with properties" parameters of a Make command. The contentsValue may be nil. When this method is invoked by Cocoa neither the contentsValue nor the properties will have yet been coerced using scripting key-value coding's -coerceValue:forKey: method. In .sdef-declared scriptability the types of the passed-in objects reliably match the relevant .sdef declarations however.
One option is to subclass NSCreateCommand and implement your own logic.

Where can I find the descriptin of LibreOffice API for BASIC

I wanted to create a few macros for LibreOffice using BASIC. However I cannot find the API description. It is absent in help as well as in interet. When I try to google it I get masses of examples in C++, Java, Python, but not a single www with BASIC.
For example where from can I get the hierarchy of objects and their methods?
LibreOffice Basic uses essentially the same API as PyUNO and Java. That is, they all use the UNO API. To get started, the OpenOffice development guide helpfully describes the two main ways to step into the object hierarchy, the Global variables ThisComponent and, less commonly, StarDesktop. There also is a specialty variant in LO Base, ThisDatabaseDocument. To get the properties and methods of these objects, execute MsgBox oObject.DBG_properties or .DBG_methods. It often is easier to copy the longer lists that are returned by this method into a text editor for searching. You will find that all, or nearly all, of the methods and properties you reveal will be described in the LibreOffice UNO IDL API. The documentation for the API is not that descriptive, but you will be able to fill in some essential details using that resource Every Object has properties that can be reviewed by .DBG_properties.
The key properties for navigating the object hierarchy are .Parent, .Model, .CurrentController and occasionally .Source. The key methods are getByName() and getByIndex(). It also is helpful that events which trigger macros typically return an event object whose source or parent is the object that initiated the macro, for example, a command button. This object can be accessed by referring to it along with the Sub, i.e., Sub SubName (oEventObject As Variant)....

VB connect to COM object

Either I don't understand COM objects, either it's all that confusing.
I frequently 'create' , 'dispatch' COM objects - either in Python, either in VB ( Obj = win32com.client.Dispatch('Visum.Visum') or Obj = CreateObject("Excel.Application") respectively).
That's easy, obvious and everything's fine.
But how can I:
a) connect to COM object which is already running
b) get list of running processes which are COM objects
in VB what is the reference, and additional info on: CreateObject command. In Python it's part of well defined, comprehensive library of win32com whereas in VB it's just single method without reference: http://msdn.microsoft.com/en-us/library/7t9k08y5(v=vs.80).aspx
Highly confusing (COM object,server? connection, dispatching, registering??)
Thanks for claryfying
Rafal
i2
First of all, I would suggest reading a good introduction to COM. Personally, i think that 'Essential COM' by Don Box is the best book about COM. Spending a few hours with it will save you many hours later.
That being said, let's move to your questions.
a) In order to retrieve an existing COM object from VB, you need to call GetObject function. This will only work for COM objects which are registered with Running Object Table. Excel does this, so there shouldn't be any problems with that.
b) as Hans Passant correctly noted, this question doesn't make sense. Processes and COM objects are completely unrelated things, except for the fact that processes host the COM objects. It is similar to asking 'which processes are instances of class X'. However, a process can host a COM object (or many of them). These object can be alive only temporarily, so what would you expect there? Besides, many COM classes are implemented within dlls, but created instances obviously are hosted within a process - so what would you expect there?
COM technology is something I didn't not use for a while, so sorry if some info might be wrong (anyway, I've got my book "Inside COM+ base services" with me!)
Briefly speaking, let's give a simplified definition of a COM object: it nothing else than a standard DLL with classes exposing a standard interface IUnkown with the following methods:
AddRef: to register a client consuming the COM object
Release: to unregister a client (usually unused objects stop running, but other might remain resident)
QueryInterface: to get the address of a function
QueryInterface is used to dynamically retrieve the address of a function (late-binding) which is powerful (you don't have to know the DLL at compile time) but time consuming. On the other hand, you can directly reference the addresses of the functions at compile-time because those DLL are registered in the system (all the informations are stored in the registry)
Creating a new object or getting the address of a running object is done through RPC (remote procedure call) which will load and/or play the role of a proxy
So to create a new instance of a COM object, you will call CreateObject (in VB) (Co)CreateInstance in VC++ (or even c#?), while to get an executing instance, you might want to call GetObject().
Getting the list of COM objects is not that easy (I guess not possible at all) because, as told earlier, a COM object is nothing else but a DLL: this means that the library will mainly load in the address space of each process which access is private. Even for out-process COM objects (opposite to in-process) which are object shared between many processes (i.e.: Excel is an out-of-process COM object: you don't load the DLL in your application's address space), they are loaded by a host (rpc.exe or a proprietary host)
Hope this helps
Serge

How do I know whether an application support OLE2 and which methods & attributes are exposed?

I want to call an ActiveX DLL or OLE2 object from ABAP.
I already know the syntax of how to instantiate the object & execute the methods:
data: my_object type ole2_object.
create object my_object <ole2object>.
call method of my_object <objectmethod>.
But given a particular application, how do I know if this is supported, what the values/names of ole2object and objectmethod is?
Transaction SOLE supplies a table of OLE Applications, among this is Excel.Application which I know can be instantiated as an OLE object, so it looks like you have to add the OLE2 app to this table first, but once again where can I read the data like CLSID & LibType from - is it published as part of the application?
Objects are coming from the table TOLE. Their methods and propeties are stored into table OLELOAD.
I found some time ago somes documents (this one and this one) that contained indications of how you can find the properties and methods.
Indication on the CLSID are succint, but it seems to be the value in the register with HKEY_CLASS_ROOt/CLSID that goes with the application indicated (ie VISIO.APPLICATION for exemple). If you search this application value with regedit, you'll find the corresponding CLSID.
Hope it's helping
Guillaume
In this case, you're simply using OLE2 to access a COM interface. If you're into accessing Office applications, you might want to take a look at KB222101. For other applications and libraries, you'll need the API documentation, some suitable examples (not necessarily in ABAP, VB will do just fine). a pointed stick to poke the developer with or all three of them...
Oh, and there's a tool called OLE/COM Object Explorer by MiTeC that can be downloaded for free from their website. Haven't used it myself, but it looks like it might be helpful.