actxserver​('ADODB.Co​nnection') doesn´t work on Matlab Production Server

12 ビュー (過去 30 日間)
leonardo scolaro
leonardo scolaro 2023 年 11 月 6 日
回答済み: Divyanshu 2023 年 11 月 15 日
I have the following code running on Matlab Production Server :
function tblResultados = AnalisisCorrelacion(flag)
% numInput is assumed/expected to be numeric
if iscell(flag) % Convert to a vector/matrix if needed
flag = cell2mat(flag);
end
if isrow(flag) % Transpose the input if needed
flag = flag';
end
if flag == 1
cn = actxserver('ADODB.Connection');
set(cn,'CursorLocation',3);
%Open connection
invoke(cn,'Open', 'provider="myprovider";mode=Read;USER ID="myuser";Password="mypassword";Data Source="serverIPaddr";');
sql = ['SET starttime= now-1h,endtime=now,samplingmode=calculated, CalculationMode= Average,intervalmilliseconds=1m ,select ,value,' ...
'from "mytable WHERE" tagname LIKE "mytag"'];
%Run query and return results
tblResultados=adodbquery(cn,sql);
end
end
This code works well on local PC but on Matlab Production Server issue the following error :
Server Creation Failed: CoInitialize has not been called
Error in AnalisisCorrelacion (line 13)
While processing request 70682411008)
Error in actxserver (line 89)
{Error using feval

回答 (1 件)

Divyanshu
Divyanshu 2023 年 11 月 15 日
Hi Leonardo,
I understand that your code executes properly on local PC but when executed on MATLAB Production Server (MPS) you are facing the issue. Refer the following points to get better understanding of the problem:
  • When a MPS worker is called first time, this starts a thread and 'CoInitialize' is called on this thread.
  • Call to 'CoInitialize' initializes COM interface on this thread.
  • If you make a call to different CTF on this same worker, then a new thread is started.
  • However, CoInitialize is not called for this new thread and hence COM interface is not initialized. Now using 'actxserver' on this thread would fail.
A workaround for this issue is to call 'CoInitializeEx' from this thread. Implement the following .cpp file:
#include "mex.h"
#include <Objbase.h>
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
HRESULT r;
/* Print the ID of the current thread */
DWORD th = GetCurrentThreadId();
mexPrintf("Calling CoInitializeEx(NULL,COINIT_APARTMENTTHREADED) on thread %0.8x\n",th);
/* Simply call CoInitializeEx */
r = CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);
/* This can return S_OK if CoInitialize had not been called before and
* it was now called successfully. In that case, just continue, do not
* call CoUninitialize; we actually need the thing to be initialized
* for the COM work we are doing in MATLAB.
* It may also return S_FALSE which is an indication CoInitialize had
* been called successfully before and the new call didn't really do
* anything. As documented on https://docs.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-coinitializeex
* we should still CoUninitialize this call then; do it once, to
* counteract what we just did but leave the original instance intact.
*/
if (r == S_FALSE) {
mexPrintf("CoInitializeEx returned S_FALSE, calling CoUninitialize.\n");
CoUninitialize();
}
/* Return the return code to MATLAB */
plhs[0] = mxCreateDoubleScalar(r);
}
Compile the above .cpp file using C++ compiler and then simply always call this before the first call to "actxserver" in your code.

カテゴリ

Help Center および File ExchangeMATLAB Production Server についてさらに検索

製品


リリース

R2023a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by