I'm developing word automation application and I'm facing serious issue with unexpected RPC/COM cast exception
[System.InvalidCastException: Nie
można rzutować obiektu modelu COM typu
'System.__ComObject' na typ interfejsu
'Microsoft.Office.Interop.Word._Application'.
Ta operacja nie powiodła się, ponieważ
wywołanie metody QueryInterface dla
składnika modelu COM w celu uzyskania
interfejsu o identyfikatorze IID
'{00020970-0000-0000-C000-000000000046}'
nie powiodło się z powodu
następującego błędu: Serwer RPC jest
niedostępny. (Wyjątek od HRESULT:
0x800706BA).]
translation from polish to english:
Unable to cast System.__ComObject to
Microsoft.Office.Interop.Word._Application.
The reason is that QueryInterface for
IID
'{00020970-0000-0000-C000-000000000046}'
failed - RPC server is unavailable -
error code HRESULT: 0x800706BA
Here the brief of wordapp module:
Initialization - after user is logged in.
using Microsoft.Office.Interop.Word;
public class WordApp
{
Application app = null;
object m = System.Reflection.Missing.Value;
object oFalse = false;
object oTrue = true;
....
app = Activator.CreateInstance(Type.GetTypeFromProgID("Word.Application.12")) as Application;
app.Visible = false;
app.DisplayAlerts = WdAlertLevel.wdAlertsNone;
app.PrintPreview = false;
I'm using Activator.CreateInstance instead of app = new Application() - here the explanation.
Then user can execute 2 actions in wordapp module
a) print prepared docx document
System.Windows.Forms.PrintDialog pd = new System.Windows.Forms.PrintDialog();
...
this.app.ActivePrinter = pd.PrinterSettings.PrinterName;
object oNumcopies = pd.PrinterSettings.Copies;
object oRange = WdPrintOutRange.wdPrintAllDocument;
object inputname = fullPath;
Document doc = app.Documents.Add(
ref inputname,
ref m,
ref m,
ref m);
try
{
// Print the document
doc.PrintOut(ref oFalse, ref oFalse, ref oRange,
ref m, ref m, ref m,
ref m, ref oNumcopies, ref m, ref m,
ref oFalse, ref m, ref m,
ref m, ref m, ref m, ref m,
ref m);
}
finally
{
doc.Close(ref oFalse, ref m, ref m);
doc = null;
}
b) convert docx to mht
object inputname = docxname;
object outputname = htmlname;
object fileType = WdSaveFormat.wdFormatWebArchive;
Document doc = app.Documents.Add(
ref inputname,
ref m,
ref m,
ref m);
try
{
doc.SaveAs(ref outputname, ref fileType,
ref m, ref m, ref m, ref m, ref m, ref m, ref m,
ref m, ref m, ref m, ref m, ref m, ref m, ref m);
}
finally
{
doc.Close(ref oFalse, ref m, ref m);
doc = null;
}
When user logout, then I release word instance:
object oSaveChanges = WdSaveOptions.wdDoNotSaveChanges;
app.Quit(
ref oSaveChanges,
ref m,
ref m);
The exception is thrown out in random places - but the most common place is near app.Documents.Add. After that exception it's not possible to app.Quit. It seems that word instance is dead.
I found that thing in eventlog (application scope):
EventType offdiag12, P1
585d8a02-f370-4c04-85b6-fccad7e80459255ec053-6dbd-4a22-9e59-112a79de8c6a,
P2 NIL, P3 NIL, P4 NIL, P5 NIL, P6
NIL, P7 NIL, P8 NIL, P9 NIL, P10 NIL.
I run office diagnostic and it didn't find any error.
Is there possible to enable / find more error informations from system?
This code runs perfectly well on my dev machine (vista). The issue occurs at customers machines (usually winxp sp2/sp3).
Is there an error in my code or what?
The only one thing I need to add.
WordModule init/close/print functions are called from main thread and savetomht from backgroundworkders' thread.
What you describe often refers to the following situation. You use a COM out-proc server (a COM object instantiated in a separate process rather then in the same process as your program) and for some reason that COM server encounters a fatal error and terminates unexpectedly. The COM object you were using no longer exists. Since RPC is used for interacting with out-proc COM servers and the server side no longer exists after termination you receive the error message saying that the RPC server is unavailable which is true but looks confusing.
You have to research and eliminate the reason of COM server termination. The most likely reasons are the following:
some unreasonable input values you pass to the calls and
an unhandled exception in an event handler. If you have any handling for events fired from a COM component you should catch all the exceptions that may be thrown inside your handler and not let them propagate outside the handler.
I don't know, but here are some suggestions based on general experience. You might try using distinct m s rather than sharing one between all parameters (the idea being that if the value is being messed with inside it could be having unpredictable results). You also may want to try providing reasonable values (rather than the m s) wherever you can. Some versions of the API may be more forgiving than others.
Related
x = fopen('pm10_data.txt');
fseek(x, 8,0);
dat = fscanf (x,'%f',[2,1000]);
dat = transpose(dat);
a = dat(:,1);
b = dat(:,2);
[r,p] = cor_test (a,b)
fclose(x);
r
p
this is what i got,
r =
scalar structure containing the fields:
method = Pearson's product moment correlation
params = 76
stat = 6.2156
dist = t
pval = 2.5292e-08
alternative = !=
Run error
error: element number 2 undefined in return list
error: called from
tester.octave at line 7 column 6
Presumably you're referring to the cor_test function from the statistics package, even though you don't show loading this in your workspace.
According to the documentation of cor_test:
The output is a structure with the following elements:
PVAL The p-value of the test.
STAT The value of the test statistic.
DIST The distribution of the test statistic.
PARAMS The parameters of the null distribution of the test statistic.
ALTERNATIVE The alternative hypothesis.
METHOD The method used for testing.
If no output argument is given, the p-value is displayed.
This seems to be what you're getting too.
If you want the p value explicitly from that structure, you can access that as r.pval
The syntax [a, b, ...] = functionname( args, ... ) expects the function to return more than one argument, and capture all the returned arguments into the named variables (i.e. a, b, etc).
In this case, cor_test only returns a single argument, even though that argument is a struct (which means it has fields you can access).
The error you're getting effectively means you requested a second output argument p, but the function you're using does not return a second output argument. It only returns that struct you already captured in r.
I've been reading the documentation about cjson and know about the conversion of null values to cjson.null values (because of no possible way to store nil in Lua tables. This works well if I use cjson.decode and cjson.encode.
However, when I try to pack and unpack the contents of the table with cmsgpack, the keys with null values are not present. I use code similar to this one.
How do you solve this problem? Do you replace null values with a especial value ({isnull: true} before calling cmspack.pack and later, replace back {isnull: true} to null) or use any other technique?
I did a quick research and didn't find any msgpack library that handles null values in hash tables. I'm not saying that such a library doesn't exist, though.
I've chosen another approach. Since lua-cmsgpack doesn't do anything special for handling null values when decoding MessagePack binary data and nil values are problem in tables only, we can add some special case code for hash → table decoder.
Actually, the patch is pretty trivial:
--- a/lua_cmsgpack.c
+++ b/lua_cmsgpack.c
## -565,6 +565,10 ## void mp_decode_to_lua_hash(lua_State *L, mp_cur *c, size_t len) {
mp_decode_to_lua_type(L,c); /* key */
if (c->err) return;
mp_decode_to_lua_type(L,c); /* value */
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 1);
+ lua_pushlightuserdata(L, NULL);
+ }
if (c->err) return;
lua_settable(L,-3);
}
Here the second call of mp_decode_to_lua_type converts a hash entry value to a corresponding Lua type value, and when the value is nil (that is, null in MessagePack), we replace it with a light userdata (NULL pointer). The same userdata (NULL pointer) is used as the cjson.null value.
We don't need to patch the encoder because it encodes any unsupported value including any userdata to null, that is, you can use cjson.null userdata to represent null values (and cjson.decode does just that). When the hash is decoded, you'll get the same userdata.
The same trick can be applied to array-like tables but it is not necessary if you know a size of a table — you can iterate the table from the first to the last index.
local cjson = require('cjson')
local cmsgpack = require('cmsgpack')
local encoded_hash = cmsgpack.pack({k1 = nil, k2 = cjson.null, k3 = 'baz'})
local decoded_hash = cmsgpack.unpack(encoded_hash)
print('decoded_hash.k2 == cjson.null?', decoded_hash.k2 == cjson.null)
for k, v in pairs(decoded_hash) do
print(k, '->', v)
end
local encoded_array = cmsgpack.pack({'foo', nil, cjson.null, 'bar'})
local decoded_array = cmsgpack.unpack(encoded_array)
print('#decoded_array =', #decoded_array)
for i = 1, 4 do
print(i, '->', decoded_array[i])
end
Output:
decoded_hash.k2 == cjson.null? true
k3 -> baz
k2 -> userdata: (nil)
#decoded_array = 4
1 -> foo
2 -> nil
3 -> userdata: (nil)
4 -> bar
Thanks to LuaRocks we don't even need to support the fork of the library for such a trivial patch. Patches can be included directly in rockspec file. I've created a gist with modified rockspec: https://gist.github.com/un-def/d6b97f5ef6b47edda7f65e0c6144663c
You can install a patched version of the library with the following command:
luarocks install https://gist.github.com/un-def/d6b97f5ef6b47edda7f65e0c6144663c/raw/8fe2f1ad70c75bfe2532a1f4cf9213f4e28423d3/lua-cmsgpack-0.4.0-0.rockspec
This code:
#[macro_use]
extern crate lazy_static;
extern crate mysql;
use mysql::*;
fn some_fn() {
lazy_static! {
static ref CONNECTION: Conn = Conn::new("mysql://root:password#127.0.0.1:3306/mydb?prefer_socket=false").unwrap();
}
}
generates a very long error message:
error[E0277]: the trait bound `*mut std::os::raw::c_void: std::marker::Sync` is not satisfied in `winapi::minwinbase::OVERLAPPED`
--> src\main.rs:8:5
|
8 | / lazy_static! {
9 | | static ref CONNECTION: Conn = Conn::new("mysql://root:password#127.0.0.1:3306/mydb?prefer_socket=false").unwrap();
10 | | }
| |_____^ `*mut std::os::raw::c_void` cannot be shared between threads safely
|
= help: within `winapi::minwinbase::OVERLAPPED`, the trait `std::marker::Sync` is not implemented for `*mut std::os::raw::c_void`
= note: required because it appears within the type `winapi::minwinbase::OVERLAPPED`
= note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<winapi::minwinbase::OVERLAPPED>`
= note: required because it appears within the type `std::boxed::Box<winapi::minwinbase::OVERLAPPED>`
= note: required because it appears within the type `named_pipe::Overlapped`
= note: required because it appears within the type `named_pipe::PipeClient`
= note: required because it appears within the type `std::option::Option<named_pipe::PipeClient>`
= note: required because it appears within the type `std::io::BufWriter<named_pipe::PipeClient>`
= note: required because it appears within the type `std::option::Option<std::io::BufWriter<named_pipe::PipeClient>>`
= note: required because it appears within the type `bufstream::InternalBufWriter<named_pipe::PipeClient>`
= note: required because it appears within the type `std::io::BufReader<bufstream::InternalBufWriter<named_pipe::PipeClient>>`
= note: required because it appears within the type `bufstream::BufStream<named_pipe::PipeClient>`
= note: required because it appears within the type `mysql::io::Stream`
= note: required because it appears within the type `std::option::Option<mysql::io::Stream>`
= note: required because it appears within the type `mysql::Conn`
= note: required by `lazy_static::lazy::Lazy`
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
Is it because mysql::Conn is not intended to use in multithreaded apps?
How I can use lazy_static if my program is not multithreaded and I use non-thread-safe types?
Your code works just fine... on macOS. I believe this to be a bug with the
implementation of the MySQL crate, and the author agreed, fixing the bug in less than a day. You should be able to just upgrade the crate and use your original code.
As a temporary workaround, you can wrap the Conn in a Mutex:
use mysql::*;
use std::sync::Mutex;
fn some_fn() {
lazy_static! {
static ref CONNECTION: Mutex<Conn> = Mutex::new(Conn::new("mysql://root:password#127.0.0.1:3306/mydb?prefer_socket=false").unwrap());
}
}
if my program is not multithreaded and I use non-thread-safe types?
I always recommend against using global variables, threads or not. Instead, create your Conn at the top of your program and pass references to it into all of your functions.
I have several custom exception classes that were created "With Message Class". Since I can't directly get a message from them, I want to create a utility method that returns a BAPIRET2 from a given exception based on the values in IF_T100_MESSAGE~T100KEY. However, I can't provide that method with a generic CX_ROOT importing parameter as this class is not message-enabled. I also can't create a generic message-enabled exception class as new classes have to inherit from one of CX_STATIC_CHECK, CX_DYNAMIC_CHECK, or CX_NOCHECK.
How can I then retrieve the message details from an unspecified exception? Should I create a method that receives a CX_ROOT and then does up to three calls to methods with an import typed to each of the three possible subclasses? Or are there better alternatives?
You could prepare a type descriptor of the interface (once):
DATA: lr_t100_descr TYPE REF TO cl_abap_intfdescr.
lr_t100_descr ?= cl_abap_typedescr=>describe_by_name( 'IF_T100_MESSAGE' ).
and then examine each exception as it comes your way:
DATA: lr_t100_exception TYPE REF TO if_t100_message.
IF lr_t100_descr->applies_to( ir_any_exception ) = abap_true.
lr_t100_exception ?= ir_any_exception.
" ...
ENDIF.
You could use the message collector object, so for example
DATA:
excp type ref to CX_ROOT,
bapi_messages type BAPIRETTAB,
message_collector type ref to IF_RECA_MESSAGE_LIST.
FIELD_SYMBOLS:
<bapi_message> TYPE BAPIRET2.
message_collector = cf_reca_message_list=>create( ).
TRY.
" some code which may cause and exception
CATCH cx_root into excp.
message_collector->add_from_exxeption( io_exception = excp).
ENDTRY.
bapi_messages = message_collector->get_list_as_bapiret( ).
LOOP AT bapi_messages ASSIGNING <bapi_message>.
" write out message
ENDLOOP.
It is well worth checking out the message collector object.
For example
http://wiki.scn.sap.com/wiki/display/profile/2007/07/09/Message+Handling+-+Finding+the+Needle+in+the+Haystack
For a logging class I use something like this:
METHOD add_message_exception.
DATA:
lr_type TYPE REF TO cl_abap_typedescr,
lr_class TYPE REF TO cl_abap_classdescr,
lr_intf TYPE REF TO cl_abap_intfdescr,
l_bapiret2 TYPE bapiret2,
lr_msg TYPE REF TO if_t100_message.
CHECK ir_exception IS NOT INITIAL.
l_bapiret2-type = i_type.
"Test for T100KEY interface
cl_abap_classdescr=>describe_by_object_ref(
EXPORTING
p_object_ref = ir_exception
RECEIVING
p_descr_ref = lr_type
EXCEPTIONS
reference_is_initial = 1
OTHERS = 2 ).
TRY.
lr_class ?= lr_type.
IF sy-subrc = 0.
lr_class->get_interface_type(
EXPORTING
p_name = 'IF_T100_MESSAGE'
RECEIVING
p_descr_ref = lr_intf
EXCEPTIONS
interface_not_found = 1
OTHERS = 2 ).
IF sy-subrc = 0.
lr_msg ?= ir_exception. "Cast to interface
l_bapiret2-id = lr_msg->t100key-msgid.
l_bapiret2-number = lr_msg->t100key-msgno.
cl_message_helper=>set_msg_vars_for_if_t100_msg( text = lr_msg ).
l_bapiret2-message_v1 = sy-msgv1.
l_bapiret2-message_v2 = sy-msgv2.
l_bapiret2-message_v3 = sy-msgv3.
l_bapiret2-message_v4 = sy-msgv4.
l_bapiret2-message = me->get_msg(
i_msgid = l_bapiret2-id
i_msgno = l_bapiret2-number ).
ENDIF.
ENDIF.
CATCH cx_root.
"Pokémon exception handling
ENDTRY.
"No T100KEY Interface available
IF lr_msg IS INITIAL.
l_bapiret2-message = ir_exception->if_message~get_text( ).
l_bapiret2-message_v1 = sy-msgv1.
l_bapiret2-message_v2 = sy-msgv2.
l_bapiret2-message_v3 = sy-msgv3.
l_bapiret2-message_v4 = sy-msgv4.
ENDIF.
ENDMETHOD.
Hope this helps as I struggled with the same problem. Maybe there is some adjustment needed, but I think you get the basic idea. This method can handle
I might be missing something, but can't you just use IF_MESSAGE~GET_TEXT which is present on CX_ROOT ?
Otherwise, I would make it the responsibility of the custom exception class to have a method that can return a proper message ( it might rely on the utility method you are planning on ).
Given the following code :
exception E of int;
fun g(y) = raise E(y);
fun f(x) =
let
exception E of real;
fun z(y)= raise E(y);
in
x(3.0);
z(3)
end;
f(g);
When executing the code in SML I get :
stdIn:216.8-216.12 Error: operator and operand don't agree [literal]
operator domain: real
operand: int
in expression:
z 3
That's fine - I understand that the line z(3); causes an error , since z throws int instead of real .
But my problem is with the line x(3.0); , why doesn't it cause an error ?
From my understanding , x is g(y) , then when we execute x(3.0) we actually execute g(3.0) , but g throws only exceptions of type int , but we passed to g the value 3.0 ,hence g would throw a real value , so it's supposed to be a violation , doesn't it ?
I'd appreciate if someone can explain why no error is happening when executing x(3.0) .
Thanks
EDIT:
When I remove z(3); , meaning :
- fun f(x) =
= let
= exception E of real;
= fun z(y)= raise E(y);
= in
= x(3.0)
=
= end;
val f = fn : (real -> 'a) -> 'a
- f(g);
The output is :
stdIn:11.1-11.5 Error: operator and operand don't agree [tycon mismatch]
operator domain: real -> 'Z
operand: int -> 'Y
in expression:
f g
-
So , as U can see , in both cases we'll get error .
Hence , I'm back at square one : why when both x(3.0) and z(3) appear (see code 1 , the first code posted at the beginning of the post) one after the other , why does SML only refers to the error that the second line (z(3);) caused , and not to the error that
the first line caused (x(3.0);) .
10x again
To complement Jesper's excellent answer: In other words, there is nothing wrong with the call to x inside f. If you remove the erroneous call to z, and then type f into an SML prompt, then you should see that the type system has inferred the type
(real -> 'a) -> 'a
for it. That type is perfectly fine, it is merely the call to f later on in your program that is ill-typed. because g does not match the parameter type real -> 'a as required.
Your problem lies in the fact that x is a function that is passed along to f, thus when typing the function f, it will always give the correct type to the argument x, as it is not bound by anything. The fact that you are have a function application f(g) right after plays no role when inferring the types of the function f.
If we move the local function z outside the definition of f, we end up with something a lot simpler, which will type
exception R of real;
fun z(y)= raise R (y);
exception I of int;
fun g(y) = raise I (y);
fun f(i, r) = (i(3.0); r(3))
However when we then call f(g,z) we end up with the following error, as the two functions aren't of the correct type
- f(g, z);
stdIn:78.1-78.8 Error: operator and operand don't agree [tycon mismatch]
operator domain: (real -> 'Z) * (int -> 'Y)
operand: (int -> 'X) * (real -> 'W)
in expression:
f (g,z)
The initial misunderstanding stemmed from not understanding when the type error was detected. Standard ML is a strongly STATICALLY typed language. This means that the type checking is all done at compile time, when the function is first read by the interpreter, not at run-time. This means that the type error is generated before the code is ever executed, which Jesper correctly pointed out. The two type errors are exactly where Jesper indicated, in the f(g) expression and the z(3) expression. There is nothing wrong with the expression x(3.0) when the expression is compiled. There would only be a problem there if static type checking did not prevent the program from running at all. A dynamically typed language like Python would allow this program to run and raise an exception where Ron suggests when the x(3.0) expression was evaluated.