Page 1 of 1
[Solved] Paste into current document .uno:Paste
Posted: Mon Dec 01, 2014 11:25 pm
by sAccord
We are trying to do what we thought was a simple thing from a 3rd party app written in FreePascal using automation. Steps:
- 1. We verify that OpenOffice SWriter is open.
2. We load a bit of text into the Windows clipboard.
3. Now we simply wish to execute a paste command into the current document.
The core of the current 'paste command' code looks like this:
Code: Select all
Server := CreateOleObject('com.sun.star.ServiceManager');
desktop := Server.createInstance('com.sun.star.frame.Desktop');
dispatcher := Server.createInstance('com.sun.star.frame.DispatchHelper');
dispatcher.executeDispatch(desktop.CurrentFrame, '.uno:Paste', '', 0, variantArray());
but our app crashes most of the time after the text is successfully pasted.
I have searched about and seen a thread that seems to warn against using dispatcher from a 3rd party app. Is this the problem?
What are the possible solutions?
Thanks in advance.
Re: Paste into current document .uno:Paste
Posted: Tue Dec 02, 2014 1:17 am
by kingfisher
If I understand you correctly, you can use paste in Writer to paste whatever is on the clipboard.
Re: Paste into current document .uno:Paste
Posted: Tue Dec 02, 2014 2:02 am
by sAccord
Yes, but we want to automate that paste from outside Writer.
Re: Paste into current document .uno:Paste
Posted: Tue Dec 02, 2014 8:48 am
by B Marcelly
From what you show it is impossible to find a possible error.
It is not clear that the crash is related to the paste or to something else in your code after the paste action.
We don't know if the same data can be pasted manually without error.
The document must be displayed (do not load it Hidden), and its window at front.
Re: Paste into current document .uno:Paste
Posted: Tue Dec 02, 2014 5:35 pm
by sAccord
The major question seems to revolve around using dispatcher from an outside application. See this post:
viewtopic.php?f=20&t=72229&p=324928&hil ... 27#p324928
that has the quote:
What you experience with .uno:PasteSpecial is normal. Dispatcher commands are intended for user interface, not for programming.
We are also running the same surrounding code and paste content with MS-Word with zero crashing problems. The data can be pasted without error. So it is unique to this small code section, and probably has to do with using (or how we are trying to use) dispatcher. If you want a larger section of code, here is the code in the procedure that also includes (in the first section) the code that is working just fine now with MS-Word.
Code: Select all
BEGIN
IF GetWordProcessorRunning(aName) THEN
BEGIN
IF (0 <> POS(aName, kWordDisplayName)) THEN
BEGIN
TRY
Server := GetActiveOleObject('Word.Application');
IF pasteMatchStyle THEN
Server.ActiveDocument.Application.Selection.PasteSpecial(FALSE, FALSE, 0, FALSE, 2)
ELSE
Server.ActiveDocument.Application.Selection.Paste;
EXCEPT
return;
END;
END
ELSE
BEGIN
IF (0 <> POS(aName, kSWriter)) THEN
BEGIN
TRY
Server := CreateOleObject('com.sun.star.ServiceManager');
desktop := Server.createInstance('com.sun.star.frame.Desktop');
dispatcher := Server.createInstance('com.sun.star.frame.DispatchHelper');
dispatcher.executeDispatch(desktop.CurrentFrame, '.uno:Paste', '', 0, variantArray());
EXCEPT
return;
END;
END
ELSE
BEGIN
aWnd:= GetWordProcessorHandle;
IF aWnd <> 0 THEN
Send_CtrlV_ToAppHwnd(aWnd);
END;
END;
END;
END;
We are not loading the document. We are setting a Windows keyboard hook, so that the user can press a key combination in side Writer (or MS-Word, or Wordpad, or Notepad, or anything else) and our dialog pops up for the specialized text content we can serve up. We put their selection into the clipboard, and offer an option to press a button on the dialog that dismisses the dialog and automatically paste the content from the clipboard into the application.
This is very simple and has been working with MS-Word for some time now. We want to add support for Writer. Thus the question.
I should note that I also tried .uno:PageDialog as an alternative to paste and had problems. We also do not crash if I do not execute the dispatcher related calls. So I am given to think it is related to our use of dispatcher. Either in its use altogether, or in a blunder in how we used it. Which is why in the OP I asked:
I have searched about and seen a thread that seems to warn against using dispatcher from a 3rd party app. Is this the problem?
What are the possible solutions?
Is there another way to send a paste command into Writer?
Re: Paste into current document .uno:Paste
Posted: Tue Dec 02, 2014 7:10 pm
by B Marcelly
In the thread you cite, my remark on the Dispatcher is not about its reliability.
The problem was .uno:PasteSpecial, not .uno:Paste.
.uno:PasteSpecial always opens a dialog window that is supposed to be answered by the user. And the programmer did not want this.
The thread author said that .uno:Paste is not reliable. This is his opinion, not mine.
As a precaution, you may explicitly release your variables after paste, especially desktop and Server.
Code: Select all
dispatcher:= unassigned; desktop:= unassigned; Server:= unassigned;
I have done a VBScript code equivalent to your pasting code, and tested it on an opened Writer document.
I have copied a formatted text and even an image from elsewhere, then run the script. Absolutely no problem, paste works.
Re: Paste into current document .uno:Paste
Posted: Tue Dec 02, 2014 7:34 pm
by sAccord
Thank you for the reply and clarifications. I've implemented those releases:
Code: Select all
IF (0 <> POS(aName, kSWriter)) THEN
BEGIN
TRY
Server := CreateOleObject('com.sun.star.ServiceManager');
desktop := Server.createInstance('com.sun.star.frame.Desktop');
dispatcher := Server.createInstance('com.sun.star.frame.DispatchHelper');
// dispatcher.executeDispatch(desktop.CurrentFrame, '.uno:Paste', '', 0, variantArray());
dispatcher:= unassigned;
desktop:= unassigned;
Server:= unassigned;
EXCEPT
return;
END;
END
and with the commented out line above, it runs and does not crash. A manual paste in Writer pastes the material fine with no crash.
But if I uncomment the executeDispatch line, I get:
Project XYZ raised exception class 'External: SIGSEGV'.
At address 40DFC3
The call stack:
Code: Select all
fpc_reraise
0040DF80 83ec04 sub $0x4,%esp
0040DF83 891c24 mov %ebx,(%esp)
0040DF86 8b1570a0b100 mov 0xb1a070,%edx
0040DF8C 85d2 test %edx,%edx
0040DF8E 7409 je 0x40df99 <fpc_reraise+25>
0040DF90 a180aeb100 mov 0xb1ae80,%eax
0040DF95 ffd2 call *%edx
0040DF97 eb05 jmp 0x40df9e <fpc_reraise+30>
0040DF99 b884aeb100 mov $0xb1ae84,%eax
0040DF9E 8b18 mov (%eax),%ebx
0040DFA0 85db test %ebx,%ebx
0040DFA2 7505 jne 0x40dfa9 <fpc_reraise+41>
0040DFA4 e847fdffff call 0x40dcf0 <SYSTEM_DOUNHANDLEDEXCEPTION>
0040DFA9 8b1570a0b100 mov 0xb1a070,%edx
0040DFAF 85d2 test %edx,%edx
0040DFB1 7409 je 0x40dfbc <fpc_reraise+60>
0040DFB3 a190aeb100 mov 0xb1ae90,%eax
0040DFB8 ffd2 call *%edx
0040DFBA eb05 jmp 0x40dfc1 <fpc_reraise+65>
0040DFBC b894aeb100 mov $0xb1ae94,%eax
0040DFC1 8b00 mov (%eax),%eax
******0040DFC3 c7400c00000000 movl $0x0,0xc(%eax)******
0040DFCA 8b03 mov (%ebx),%eax
0040DFCC ba01000000 mov $0x1,%edx
0040DFD1 e86a1c0000 call 0x40fc40 <fpc_longjmp>
0040DFD6 8b1c24 mov (%esp),%ebx
0040DFD9 83c404 add $0x4,%esp
0040DFDC c3 ret
0040DFDD 0000 add %al,(%eax)
0040DFDF 00 add %al,0x1c8908ec(%ebx)
With the line in question decorated with asterisks, which sure does look a bit like a NULL pointer problem that happens somehow when FreePascal tries to reraise an exception.
I suppose I can try another Win32 development environment to keep as close to our FreePascal base. I'm open to other suggestions to get this to behave in FreePascal. Is the dispatcher + .uno:Paste the only way to initiate a paste outside of Writer?
Re: Paste into current document .uno:Paste
Posted: Tue Dec 02, 2014 10:14 pm
by B Marcelly
Are you sure that your variables are not used elsewhere ?
Otherwise, it looks like release of the variables happens before the dispatch action has finished. Wait some 200ms after the dispatch command ?
Is the dispatcher + .uno:Paste the only way to initiate a paste outside of Writer?
I don't know other solution.
Re: Paste into current document .uno:Paste
Posted: Tue Dec 02, 2014 10:29 pm
by sAccord
B Marcelly wrote:Are you sure that your variables are not used elsewhere ?
Yes, that is the whole function. The very top is that I clipped out is:
Code: Select all
PROCEDURE PasteIntoWordProcessor (pasteMatchStyle: BOOLEAN);
VAR
Server, desktop, dispatcher: variant;
aName: Str;
aWnd: HWND;
FUNCTION variantArray(): Variant;
BEGIN
variantArray:= VarArrayCreate([0, -1], varVariant);
END;
B Marcelly wrote:Otherwise, it looks like release of the variables happens before the dispatch action has finished. Wait some 200ms after the dispatch command ?
Interesting. I tried this:
Code: Select all
IF (0 <> POS(aName, kSWriter)) THEN
BEGIN
TRY
Server := CreateOleObject('com.sun.star.ServiceManager');
desktop := Server.createInstance('com.sun.star.frame.Desktop');
dispatcher := Server.createInstance('com.sun.star.frame.DispatchHelper');
Sleep(300);
dispatcher.executeDispatch(desktop.CurrentFrame, '.uno:Paste', '', 0, variantArray());
Sleep(300);
dispatcher:= unassigned;
desktop:= unassigned;
Server:= unassigned;
EXCEPT
return;
END;
END
and it still crashed in the same place. Unless I put them in the wrong places.
B Marcelly wrote:Is the dispatcher + .uno:Paste the only way to initiate a paste outside of Writer?
I don't know other solution.
Re: Paste into current document .uno:Paste
Posted: Wed Dec 03, 2014 9:09 am
by B Marcelly
Works for me without a hitch.
Code: Select all
uses Variants;
procedure TForm1.Button2Click(Sender: TObject);
var
Server, desktop, dispatcher: variant;
FUNCTION variantArray(): Variant;
BEGIN
variantArray:= VarArrayCreate([0, -1], varVariant);
END;
begin
Server := CreateOleObject('com.sun.star.ServiceManager');
desktop := Server.createInstance('com.sun.star.frame.Desktop');
dispatcher := Server.createInstance('com.sun.star.frame.DispatchHelper');
dispatcher.executeDispatch(desktop.CurrentFrame, '.uno:Paste', '', 0, variantArray());
dispatcher:= unassigned;
desktop:= unassigned;
Server:= unassigned;
end;
Tested on Lazarus 32bits, version 1.2.6 containing FPC 2.6.4
MS-Windows 7 64bits Home SP1
Re: Paste into current document .uno:Paste
Posted: Wed Dec 03, 2014 6:35 pm
by sAccord
B Marcelly wrote:Works for me without a hitch.
Tested on Lazarus 32bits, version 1.2.6 containing FPC 2.6.4
MS-Windows 7 64bits Home SP1
Fascinating. We just built one outside our app doing this and it still fails every time.
We thought compiling with MacPas might matter, but we crash with or without that compile option. I don't suppose you used any special compile options there?
We'll fiddle some more. I appreciate your help on this and after some more poking around, I'll post back.
Re: Paste into current document .uno:Paste
Posted: Mon Dec 08, 2014 10:31 pm
by sAccord
Update. Turns out there was a problem with the macpas compiler option in Laz/FPC that has already been fixed in a future release and there is a work-around. Thank you for the help trying to sort this out, and we'll be happily supporting OpenOffice with our app now.