Presently I am developing a small security application in Delphi. It is intended to be installed in Windows XP and higher OS-s and almost finished, but I'd like to implement the feature to scan MS Office files while opening. To that end, I'm planning to use IOfficeAntiVirus interface. I am trying to realize using the scan method of the interface based on the article by Serge Perevoznyk (http://www.delphi-central.com/MS_Office_AV_API.aspx).
The original example supposed to display a message box when a file is opened, however it does not, although I tried it on different versions of Windows and Office. I compared this solution with the information on MSDN. It seemed to be correct. I suppose there should be some additional settings in the Windows Registry which I missed to make. Can anyone give me some hint where shall I look for the solution?
You do not use IOfficeAntiVirus, you implement it.
You need to create a new ActiveX Library that contains a new ActiveX Control whose implementation class implements the Scan() method. In the Control's registration code, you have to use ICatRegister to register your Control as using the CATID_MSOfficeAntiVirus category. That way, Office/IE can find your ActiveX Control so it can instantiate it and call its Scan() implementation. The second half of Serge's article shows you how to do that (Serge's example shows Scan() taking a PChar as input, but it actually takes a TMsoavinfo^ instead. Don't pass TMsoavinfo using a PChar).
You then have to register the resulting DLL using Windows' command-line regsvr32.exe app.
If Office/IE is not calling your Scan() implementation, then you are likely not registering your ActiveX control correctly, such as if you are not taking 32bit/64bit and/or UAC issues into account.
Just for information's sake if anyone is interested. Remy's answer is correct, however there is a small bug in the initialization section of the above mentioned example project.
Instead of
TComObjectFactory.Create(ComServer, TMsoTest, Class_MsoTest,
'MsoTest', '', ciMultiInstance, tmApartment);
The correct command is:
TMSOAVFactory.Create(ComServer, TMsoTest, Class_MsoTest,
'MsoTest', '', ciMultiInstance, tmApartment);
Related
The problem: I need to obtain the selected text from a window in a Windows application (not my program). I am doing my work in Delphi XE and the software I am attempting to access is a kluge built over the past 15 years with C, C++, VB and who knows what else. I do not have the source code. The edit box (an RTF memo) I am attempting to read is of the class "Ter32Class". When I use wm_copy, nothing goes to the clipboard. when I use wm_gettext, nothing. When I use wm_keydown commands (to simulate Ctrl-Ins or Ctrl-C) nothing happens. Note that I can get all of these alternatives to work in wordpad, notepad, and FireFox but not this application (or OpenOffice, incidentally, but that's not the issue). The only way I have been able to programmatically obtain text from this box is to use autohotkey with the simple "send ^c" command. While it works, it is inelegant. HELP?!?
More information: Window hierarchy: Ter32Class is a child of OI_Mdi which is a child of MDIClient, which is a child of OI_Window . I am drilling down to obtain the appropriate handle as it will respond to a paste command.
I am using Delphi XE but I'd love any solution in C++ or VB if no Delphi XE gurus have the answer.
From Quick Macros Forum
One of the windows I need to talk to is of class Ter32Class which
apparently is a TE Edit Control, an editor that doesn't inherit from
the standard RichText Control
and
The published method of talking to this control is via it's DLL
so unless something has changed (post is 2006), it appears you'll need to use it's dll to get the text.
From Sub Systems (TE Edit control website)
Application Interface functions
GetTerBuffer: Retrieve Window Text
HANDLE GetTerBuffer(hWnd, size)
I'm trying to assign a ParentWindow, to a control created in a dll. The control is an editor, I need to process a text file, but this control requires a ParentWindow.
How can I solve this problem, if I create this control in a dll?
I'm using Delphi 5.
also create the TForm (maybe not Visible) inside the dll then the control and add it to the form
This is a common question, and the correct answer is "Don't do that".
The first question I have is "why do you feel the need to create a control in a DLL?" Why not just create it in code or include the control itself in your EXE?
Second, if you want to add a control to a separate binary, but it in a Package. Packages are designed specifically to make exporting controls simple and easy.
You need to get the parent window from somewhere! Typically the host application that loads and calls the DLL would supply a window handle. It looks like your DLL provides a custom control for an application, so of course the application needs to supply a parent window handle.
Also, you typically need a window handle to the entire application as well, which you set as Application.Handle before you do anything else in your DLL.
ok, thaks for your answers, i already solved (a few minutes before first answer).
first, i need explain why i don't embed, and that is because costumer ask me that way.
the solution is send my form handle to my dll as an argument, after testing that way, i got no errors...
only modificate the prototype of my procedure, to recieve a HWND as an argument, to ParentWindow prop of my control (created in memory).
that's all.
We have a need to interoperate between one of our web apps and a Win32 app created in Delphi.
A colleague suggested using a custom protocol handler like ourcompany://something to pass information to the app.
Is this possible with Delphi (5 Enterprise), or not? If it's available in later versions, we'll look to sourcing a license for that.
Cheers!
MSDN has an article explaining the whole thing. It describes the registry entries you need to set up, and it describes the command line that Internet Explorer will use to invoke your program.
There's nothing to prevent you from writing a protocol handler in any Delphi version you want.
A custom protocol handler is a registered COM object that implements the IInternetProtocol interface.
Here http://www.doogal.co.uk/plugprot.php is some information on how to implement it in Delphi.
Yes, as a matter of fact that is exactly how the IDE Welcome page works. We register a custom protocol handler for bds://.
I'm using Turbo Delphi 2006.
The DLL will be called from within Excel as part of a VBA/DLL combination.
The first part of the problem is trying to find out how to pass to the DLL a reference to the current Excel session. Most other code I've seen was that it launched a separate instance of Excel apart from the one you're in.
I've seen some C++ code that creates an instance of IDispatch and then passes something in to a method of the IDispatch object, but not knowing much C++.
Any ideas?
What you describe is called writing a COM addin. You need to create an automation DLL and implement the IDTExtensibility2 interface. You will then receive the Excel Application interface as a parameter to the OnConnection method.
You will also need to register your DLL as an addin so Excel will automatically load it.
EDIT: Forgot to mention: You might want to take a look at Add-in Express. Their framework and components make getting started with the creation of Office addins ridiculuously easy. You definitely won't have to bother with the details of IDTExtensibility2. All that comes with a (well-justified) price tag, though.
Delphi comes with a set of ActiveX controls to give complete access to Excel and the other Office applications. They should be on the "Servers" tab of the Tool Palette.
If the aren't there, then select Components|Install Packages, and scroll down the list there until the very end, and select the right package.
In a default installation, they should be called:
Microsoft Office Sample Automation Server Wrapper Components
and there should be one for XP and Win2k. The XP ones will work for Vista.
Now that if if you want to automate Excel.
If you merely want to add functionality to Excel by using Delphi, I'd suggest using a COM object, as I suspect that Excel is very accepting of COM objects. Otherwise, you can create a straight DLL, and use that the same way that Excel uses any other DLL.
I do not know much about Office, but I guess you should use COM/ActiveX. Then you also get your IDispatch. See http://delphi.about.com/od/comoleactivex/OLE_COM_DCOM_Automation_ActiveX_Delphi_knowledge_base.htm
I read this article and find the concept of Virtual Library Interfaces nice for runtime loading of DLLs. However it seems that they aren't available for Win32. Is this true? And if so: Why? I don't see what would tie the idea to .NET.
EDIT: I'm mostly rephrasing here what Rob already wrote. :-)
I'm not after plugins or similar - it's about plain old Win32 DLLs. What appeals to me is the idea to let the compiler deal with all the details of loading a DLL at runtime - no need to call GetProcAddress for every function in the DLL etc.
It seems to me like the three answers so far have completely missed the point of your question. That, or I have. You're asking why Win32 Delphi doesn't have something like the magical Supports function that Hallvard's article talks about, aren't you? Namely, a function that, given the name of a DLL and the type information of an interface, returns an object that implements that interface using the standalone functions exported from the DLL.
Hydra seems to be all about calling .Net code from a Win32 program, not about importing functions from a DLL. TJvPluginManager requires that the plug-in DLLs export a special self-registration function that the manager will call when it loads the DLL, and the function must return an instance of the TJvPlugin class, so the plug-in DLL must be written in Delphi or C++ Builder. The Supports function, on the other hand, works with any DLL written in any language. You could use it on kernel32, if you wanted.
I don't know why Win32 Delphi doesn't have such a thing. Maybe CodeGear didn't see much demand for it since Delphi and Turbo Pascal had already gone for so long without it.
It's certainly possible to write a function that works like that, and I don't expect it would be any harder to write than the .Net version must have been, unless Microsoft's .Net libraries already provide most of the pieces and Delphi just wraps them up into a convenient-to-call function that looks like the several other overloaded versions of Supports that Delphi has had for years.
There would be a few steps to implementing that function in Win32. (I'm providing only a sketch of what's necessary because I don't have a running copy of Delphi handy right now. Ask nicely, and maybe I'll find more details.) First, you'd need to make sure that type information for an interface held, at a minimum, the undecorated names of its methods. Then, Supports would need to generate a function stub for each method in the interface (besides _AddRef, _Release, and QueryInterface). The stub would go something like this, assuming the calling convention is stdcall:
asm
// Pop the return address,
// discard the "this" pointer,
// and restore the return address
pop eax
pop ecx
push eax
jmp AddressOfFunction
end;
As Supports generated each stub, it would fill in the actual function address, gotten from calling GetProcAddress with the name of the corresponding interface method. The stdcall calling convention is easy to wrap like that; cdecl is a little cumbersome; register is a pain in the neck.
Once it has all the stubs generated, it would need to generate an "object" that looks like it implements the given interface. It doesn't have to be an actual class. At compile time, Supports doesn't know the layout of the interface it's going to be asked to implement, so having a class wouldn't accomplish much.
The final step is to provide implementations of the _AddRef, _Release, and QueryInterface. _AddRef would be unremarkable; _Release is where you'd call FreeLibrary when the reference count reached zero; QueryInterface wouldn't do much at all, except claim that it supports IUnknown and the interface given to Supports.
Delphi used to come with a sample program that demonstrated implementing an interface without any classes at all. It was all done with records and function pointers (which is all an interface ultimately is, after all). Delphi also came with the corresponding code to do it with classes, in part to show how much easier Delphi can make things. I can't find the name of the demo program now, but I'm sure it's still around somewhere.
There are a number of Win32 options for this type of functionality. Project JEDI has an open source plugin system as part of the JVCL that loads either DLLs or packages, and can include forms and whatnot as additional functionality.
There are also a number of commercial products available, including the TMS Plugin Framework and RemObjects Hydra.
This is nothing new or special. The article's just talking about plugins. Native code's been able to do plugins for years. The only special thing about P/Invoke is that it allows native code and .NET to talk to each other in a plugin system, and the little trick where "the DLL can be seen as a singleton object that implements the interface [so that] you can use the Supports function from the Borland.Delphi.Win32 unit to check if the DLL and all the methods are available."
If you want to do what the article's talking about in Delphi for Win32, look at the LoadLibrary, GetProcAddress and FreeLibrary Windows API functions. If you absolutely must have an interface like the article describes, you have to write it yourself, either in the DLL (if you wrote the DLL yourself) by writing an exported function that returns an interface, or in the calling app, by writing a function that uses GetProcAddress to create an interface dynamically. (Caution: this requires mucking around with pointers, and is usually more trouble than it's worth.)
Your best bet is probably just to do what Tim Sullivan mentioned: use TJvPluginManager from the JEDI VCL if you only need native code, or Hydra if you have to talk to .NET assemblies.
I've used Hydra myself for a Delphi only solution (i.e., didn't interface to .NET) and it works great for that too. It's easier to use and adds some niceties, but I think that it's basically implemented the same way as the "roll-your-own" plugin framework that is well-described in this article:
http://www.saxon.co.uk/SinglePkg/
I would look for a plugin framework that's interface-based (like Hydra and the "roll-your-own" system in above paragraph), rather than one that simply sends messages between apps.
There is a Delphi plugin framework on sourceforge, don't know whether it's the same one as in JEDI project or not: http://sourceforge.net/projects/rd-dpf
There are also a couple of other commercial solutions, one of which is Dragonsoft's:
http://www.dragonsoft.us/products_dsps.php
What is wrong with doing this with simple com objects? Declare a simple interface that all of your plugins implement, and require that each com object include an exported function that returns its class guid. Then using the "plugins" is as simple as walking thru the plugins directory looking for DLL's which expose the special registration function, invoking it and then using the class guid to then invoke the com object.
I used something like this in a WIN32 commercial application with great success. The advantage was I could switch plugins in and out at will (provided of course the application wasn't running to remove existing ones), the magic was all in the interface that each one implemented.