|
Excel enables the creation of user-defined functions that can be used in Excel formulas. So I use these code to create a COM introp.
-------------------------------------------------
using System;
using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace AutomationAddin {
[ClassInterface(ClassInterfaceType.AutoDual)]
public class MyFunctions {
public MyFunctions() {
}
public double MultiplyNTimes(double number1,
double number2, double timesToMultiply) {
double result = number1;
for (double i = 0; i < timesToMultiply; i++) {
result = result * number2;
}
return result;
}
[ComRegisterFunctionAttribute]
public static void RegisterFunction(Type type) {
Registry.ClassesRoot.CreateSubKey(
GetSubKeyName(type));
}
[ComUnregisterFunctionAttribute]
public static void UnregisterFunction(Type type) {
Registry.ClassesRoot.DeleteSubKey(
GetSubKeyName(type), false);
}
private static string GetSubKeyName(Type type) {
System.Text.StringBuilder s =
new System.Text.StringBuilder();
s.Append(@"CLSID\{");
s.Append(type.GUID.ToString().ToUpper());
s.Append(@"}\Programmable");
return s.ToString();
}
}
}
-----------------------------------------------------
And set project build property,checked output item,register COM interop.
Building the project,that's success.
Launch Excel and choose Add-Ins from the Tools menu to display the Add-Ins dialog. In the Add-Ins dialog, click the Automation button. But I can't find the class I created by looking for AutomationAddin.MyFunctions in the list of automation servers.
What's wrong? Please help me !Thanks,by the way,My development tool is VS2005 ,Office 2003 (sp2)simply chinese.
|
|
|
|
|
We have a product that does the following:
* starts up as service
* spawns of n threads that actually do work. All of these threads do the same thing, which is to automate a COM server to produce a result.
After about 1000 transactions have run through the process, it starts to get the hexadecimal value above as a return code. This is not always the case, and the error is in fact quite intermittent.
The call that fails is a very simple call on a smart pointer to a home-grown DCOM object.
Anyone run into this before? Any thoughts?
My first instinct is that it's one of those bizarre interplays between threads and memory and that at some point some thing just loses it's mind (very technical, I know
Thanks.
Also, please forgive me if this should be in the threading forum. I thought I'd start here since I KNOW that COM is involved, and only suspect threading.
Joe Hayes
|
|
|
|
|
Well, if the return code could be interpreted as an error code it would be CO_E_OBJNOTREG meaning that the object is not registered.
I suspect that the smart pointer call creates an object, or in this case tries to create an object.
Hope this helps
--
Roger
|
|
|
|
|
I've had a similar problem before, if I remember right it was an issue with following the rules about who (which thread) is making the calls. I'd make sure that your following the interface marshalling rules. If I remember right in my case it was somebody creating the object in one thread then making calls in another without having marshalled the interface. Hope that helps.
|
|
|
|
|
Hi All,
Info: this is a single class object
why this fails?
IF I USE THIS:
hr = CoGetClassObject(CLSID_CoCar, CLSCTX_INPROC_SERVER, NULL,
IID_IClassFactory, (void**)&pCarFact);
hr = pCarFact->CreateInstance(NULL, IID_ICreateCar, (void**)&pICreateCar);
IT COMPILES BUT IT CRASHES if I insist to use IClassFactory::CreateInstance...
.................................
Then I replace it with
hr = CoCreateInstance(CLSID_CoCar, NULL, CLSCTX_INPROC_SERVER, IID_ICreateCar,
(void**)&pICreateCar);
IT COMPILES AND IT RUNS...
Still researching why but no answer so far...
TIA for any help
|
|
|
|
|
Did your CoGetClassObject API Succeeded ? what is the HR value after CoGetClassObject API call ?
AFAIK, CoCreateInstance internally uses CoGetClassObject API and queries for class Factory.
If possible post your code snippet.
Have a great day ahead!
Regards,
Sohail Kadiwala
(My Blog - http://blogs.wdevs.com/sohail/[^])
modified 21-Apr-21 21:01pm.
|
|
|
|
|
odiesback wrote:
IT COMPILES BUT IT CRASHES if I insist to use IClassFactory::CreateInstance...
Too complicated to go into. You need a good book on COM etc...
A better question is why do you not want to just use the first syntax???
odiesback wrote:
Then I replace it with
hr = CoCreateInstance(CLSID_CoCar, NULL, CLSCTX_INPROC_SERVER, IID_ICreateCar,
(void**)&pICreateCar);
This works because CoCreateInstance gets the factory for you behind the scenes, i.e.
CoCreateInstance first calls hr = CoGetClassObject(...factory parameters...)
Then it calls hr = pFactory->CreateInstance(...class parameters ...)
and returns the class pointer as hr.
The only real difference between the two approaches is convenience and performance.
When you call CoCreateInstance, COM gets the factory, and gets the class for you - it does all the work behind the scenes, and is convenient. But if you make multiple calls to get multiple instances of class from the same factory, COM may (or may not be, depending on a lot of things) recreating the same factory multiple times.
If you know in advance that you will be creating numerous instances of the same class objects from a specific factory, or if you know in advance that you will be creating different classes that are all supplied by a specific factory, then you can get the pointer to the factory yourself, hang on to it, and call pFactory->CreateInstance(...) directly.
|
|
|
|
|
Thanks for your repplies:
I am studying COM from "Developer's Workshop to COM and ATL 3.0"
and the code in question is presented by the author for VC6.0 and I am
using VC7.0.
The book uses the call to the IClassFactory and then calls CreateInstance(), which
refuses to run. After trying go get it to work I replace for a call
to CoCreateInstance(). Not even the code supplied by the CD aruns.
this is the code:
----------------------------------------------------
#include <iostream.h>
#include "interfaces.h"
#include "iid.h"
int main()
{
// Initialize COM sub system
CoInitialize(NULL);
// Declare all interfaces you are going to use
IClassFactory* pCarFact = NULL;
ICreateCar* pICreateCar = NULL;
IStats* pIStats = NULL;
IEngine* pIEngine = NULL;
// Declare the return type HRESULT
HRESULT hr;
// Screen page Header
cout << "\n*****************************************************";
cout << "\n** T H E A M A Z I N G C O C A R C L I E N T **";
cout << "\n*****************************************************\n\n";;
// Grab the IClassFactory pointer from CoCarFactory
hr = CoGetClassObject(CLSID_CoCar, CLSCTX_INPROC_SERVER, NULL,
IID_IClassFactory, (void**)&pCarFact);
hr = CoCreateInstance(CLSID_CoCar, NULL, CLSCTX_INPROC_SERVER, IID_ICreateCar,
(void**)&pICreateCar);
//-------> hr is 0 coming out of the expression above
/*
// THE PROGRAM COMPILES BUT IT CRASHES IF USING the IClassFactory pointer
// Call CreateInstance() from the Class Fatory pointer, and ask for IID_ICreate from the
// CoCar
hr = pCarFact->CreateInstance(NULL, IID_ICreateCar, (void**)&pICreateCar);
// Once you used the CoClassFactory pointer, release it.
pCarFact->Release();
*/
// Exercise ICreateCar
if(SUCCEEDED(hr))
{
BSTR name = SysAllocString(L"Odie Silva");
pICreateCar->SetPetName(name);
SysFreeString(name);
pICreateCar->SetMaxSpeed(100);
// Find IStats
hr = pICreateCar->QueryInterface(IID_IStats, (void**)&pIStats);
// Now can release ICreateCar
pICreateCar->Release();
}
if(SUCCEEDED(hr))
{
// Display properties
pIStats->DisplayStats();
// Switch hr to IEngine interface using IStats* (can also use IUnknown*)
hr = pIStats->QueryInterface(IID_IEngine, (void**)&pIEngine);
}
// If successful run the IEngine
if(SUCCEEDED(hr))
{
int curSpd = 0;
int maxSp = 0;
pIEngine->GetMaxSpeed(&maxSp);
do
{
pIEngine->SpeedUp();
pIEngine->GetCurSpeed(&curSpd);
cout << "\n\n Speed is: " << curSpd << endl;
}while(curSpd < maxSp);
// Convert BSTR to char array
char buff[80];
BSTR bstr;
pIStats->GetPetName(&bstr);
WideCharToMultiByte(CP_ACP, NULL, bstr, -1, buff, 80, NULL, NULL);
cout << "\n" << buff << " has blown up! Lead foot!" << endl;
// Final clean up
SysFreeString(bstr);
if(pIEngine)
pIEngine->Release();
if(pIStats)
pIStats->Release();
}
// Unload COM system
CoUninitialize();
return 0;
}
|
|
|
|
|
I just cant find out why my program is crashing.
I simplified it to track down the erro rand the only thing I can say
for sure is that it fails to create my object instance.
hr = S_OK coming out of CoGetClassObject
it crashes when debugging at CreateInstance() using the class factory pointer
"unhandled exception..."
I will check my imp of CreateInstance in my class factory but why it works
great if I use CoCreateInstance(), if that function is just a wrapper and
uses the same data I am using through the class factory?
Thanks for your help
|
|
|
|
|
I am devlopping a control (a simple container (simple frame)using MFC, not ATL) and i need to receive all mouse events, client area and non-client area ones, when the control is selected on a form in the IDE of VB.
Does somebody can help me ?
|
|
|
|
|
Hi lgaudouen,
SetCapture(HWND hWnd) and ReleaseCapture() API's would do the trick for you.
For more information on these API's, refer to the MSDN...
Hope this helps !
Cheers,
Vishal
|
|
|
|
|
Hello, I'm very new to COM and just had a simple question.
Does CoCreateInstance() check to see if there is another instance already in existance?
I am currently using CoCreateInstance() to create my class object, but I only want to do it once.
I want to do this:
If (there is no instance)
then (CoCreateInstance())
else (run code)
Is this automatically done within CoCreateInstance or is there another way to check to see if an instance already exists? I want to avoid running CoCreateInstance() multiple times.
Thank you.
|
|
|
|
|
How to write a com application in c# and deploy.
Any source please!
pkarunadheera
|
|
|
|
|
you can reference to the book 'C# COM+ programming':->
|
|
|
|
|
Hello.
I need to retrive a all Interfaces (methods) and propertyes from a certain COM object i dont know realy where to start...
I'm there aren't many sources exept for some Object Browsers but no sources
|
|
|
|
|
Hi benjamin23,
OLE/COM Object Viewer gives all inofrmation about the COM object. Go to "Type
Library" and double click the COM object you want, it would show you the
information about the interfaces/structures that COM object has...
Hope this would help you...
All the best !
Cheers,
Vishal
|
|
|
|
|
|
The link has been verry userful, still leavme some cuestions:
supose i have an instance of "Word.Application"
I dont know if ".Visible" exists as a property or even a method, the same could happen to ".WebPagePreview" it's a method but my program doesnt know that i need to retrive the collection of methods and propertyes right before i create the object, this whay i can parse for example a .txt wich contains the methods to call or the variables to set.
|
|
|
|
|
Hmmm.. I think you are looking for invoking/calling a method or property dynamically. With this assumption, I think the following interface will help solve your problem -
IDispatch
IDispatch has a method called as GetIDsOfName to which you pass the name of method and it will return you an ID. Using this ID you call another method of IDispatch, namely, Invoke. For more details please check MSDN documentation for IDispatch and its methods.
I hope this helps.
Let me know if you are looking for anything other than what I assumed.
Have a great day ahead!
Regards,
Sohail Kadiwala
(My Blog - http://blogs.wdevs.com/sohail/[^])
modified 21-Apr-21 21:01pm.
|
|
|
|
|
Is somebody developing OPC compliance components? Can you recommend me any good tutorial or demo to know more about this subject? Is still OPC the standard used to develop software components for industrial communications or there are other trend that might I take care?
Thanks in advance,
Marc Soleda.
... she said you are the perfect stranger she said baby let's keep it like this... Tunnel of Love, Dire Straits.
-- modified at 10:31 Monday 10th October, 2005
|
|
|
|
|
insert a object to the activex container,we must open the insert dialog box usually. now i want to insert a object when the activex container Initializing,who can tell me how to do it?thanks.
|
|
|
|
|
How I can get and modify AmbientProperty in WebbowserControl?
P.S. I'm writing plugin for IE.
|
|
|
|
|
Hi Folks
I finished burning my brain with system-level configuration of my com, and now I get the first "normal" errors.
I have a Variant that contains an array of a structure (4 int), and 2 other int, that are rows and columns (of the image I must import)
In this piece of code
HRESULT Image2Variant (IVA_Image Source, VARIANT *Dest)
{
SAFEARRAYBOUND sabRGB[6]
sabRGB[0].lLBound = 0;
sabRGB[0].cElements = Source.columns * Source.rows;
sabRGB[1].lLBound = 0;
sabRGB[1].cElements = Source.columns * Source.rows;
sabRGB[2].lLBound = 0;
sabRGB[2].cElements = Source.columns * Source.rows;
sabRGB[3].lLBound = 0;
sabRGB[3].cElements = Source.columns * Source.rows;
sabRGB[4].lLBound = 0;
sabRGB[4].cElements = 1 // the only columns value
sabRGB[5].lLBound = 0;
sabRGB[5].cElements = 1 // the only rows value
VariantInit(Dest);
Dest->vt = VT_VARIANT | VT_ARRAY;
Dest->parray = SafeArrayCreate(Dest->vt, 1, saRGB);
....
Dest->parray is NULL, so I think that function fails, but I don't know why...
Suggestions?
Thanx
Morenz
|
|
|
|
|
A suggestion for you on your SafeArray init.
I believe that you need to init the vt (first param) with a data type, that is, VT_R4 or something such as that. I am not certain if you are putting in Array addresses in the safearray itself. It looks like you want data values such as floats or integers. I have used several safearrays and my inits always work with a VT_R4 for float instead of your Dest->vt.
The documentation states:
>>
vt
The base type of the array (the VARTYPE of each element of the array). The VARTYPE is restricted to a subset of the variant types. Neither the VT_ARRAY nor the VT_BYREF flag can be set. VT_EMPTY and VT_NULL are not valid base types for the array. All other types are legal.
>>
The other suggestion is that this array is for two dimensions ((Source.columns * Source.rows) by 6), is it not? Therefore the second parameter of the SafeArrayCreate should be 2.
|
|
|
|
|
First of all, thanx a lot for your reply.
I did it work, it was none of the precedent thoughts or ideas we had. It was simply that the cElements record of SAFEARAYBOUND structure had a too big value. I tried with 1000, and it's too big again. It likes 10 .
Now, if that's the problem, I'm back again at the starting point. I need to pass an array that could be max 1024 rows x 1024 cols, x 4 bytes (almost 4 megabytes). How can I do? Putting it into a file, sending the file and reading it back again serially is not a good trick, because if it's true that time is not a prerequisite, it's true, too, that I cannot make it last a minute to analyze a 1024 x 1024 raster image!
Should I serialize it into strings and send 'em in some chunks?
How can I do?
When will these annoying problems stop, so I can start making a decent debug?
Thanks again
Morenz
|
|
|
|
|