|
Yes, if you follow the instructions in the article I linked to, you can create your own .NET library to call the API, and then call that as a COM component from Excel.
Or you could use VSTO to create an Excel add-in or workbook with .NET code running behind it. But it sounds like you might be locked out from doing that as well.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
 Hello, in the article you linked in your post, there are two different GUIDs. What are the differences in the 2, and which ones should I be using?
Also, in the article to call the COM object he was able to reference the COM wrapper class built to expose the .NET calls to VBA in Visual Studio. I am trying to do this in Excel, where I can't simply reference the dll. Can somebody tell me how I can call COM objects in Excel? Here is my code for the COM Wrapper Class:
Imports System
Imports System.Collections.Generic
Imports System.Runtime.InteropServices
Imports NXOpen
Imports NXOpen.UF
Imports NXOpen.Assemblies
Namespace ExcelNXInterface
<Guid("bbe0089d-a732-4743-922b-180b30006fa4"), _
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> _
Public Interface _ExcelNXInterface
<DispId(1)> Sub HighlightCompTag(ByRef tag As Long)
<DispId(2)> Sub Echo(ByVal output As String)
End Interface
<ComVisible(True)>
<Guid("975DC7E0-4596-4C42-9D0C-0601F86E3A1B"), _
ClassInterface(ClassInterfaceType.None), _
ProgId("ExcelNXInterface.Open")> Public Class ExcelNXInterface
Implements _ExcelNXInterface
Public _ExcelNXInterface
Dim theSession As Session = Session.GetSession()
Dim ufs As UFSession = UFSession.GetUFSession()
Public Sub HighlightCompTag(ByRef tag As Long) Implements _ExcelNXInterface.HighlightCompTag
Try
ufs.Disp.SetHighlight(tag, 1)
Echo("Component(s) Highlighted...")
Catch e As NXException
Echo("NX Exception is: {0} " + e.Message)
Catch e As Exception
Echo("Exception is: {0} " & e.Message)
Echo("DONE!" & vbLf)
End Try
End Sub
Sub Echo(ByVal output As String) Implements _ExcelNXInterface.Echo
theSession.ListingWindow.Open()
theSession.ListingWindow.WriteLine(output)
theSession.LogFile.WriteLine(output)
End Sub
End Class
End Namespace
Here is the manifest I built to reference in Excel:
="1.0"="utf-8"
<asmv1:assembly
manifestVersion="1.0"
xmlns="urn:schemas-microsoft-com:asm.v1"
xmlns:asmv1="urn:schemas-microsoft-com:asm.v1"
xmlns:asmv2="urn:schemas-microsoft-com:asm.v2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<assemblyIdentity
type="win32"
version="1.0.0.0"
name="ExcelNXInterface"/>
<clrClass
clsid="{975DC7E0-4596-4C42-9D0C-0601F86E3A1B}"
progid="ExcelNXInterface.Open"
threadingModel="Both"
name="ExcelNXInterface.Open">
</clrClass>
<file name = "ExcelNXInterface.dll"></file>
</asmv1:assembly>
Here is the VBA code I am using to try and call the COM objects in Excel's IDE:
Sub ExcelNX()
Dim actCtx As Object
Set actCtx = CreateObject("Microsoft.Windows.ActCtx")
actCtx.Manifest = ThisWorkbook.Path & "\ExcelNXInterface.dll.manifest"
Dim myNX As Object
Set myNX = actCtx.CreateObject("ExcelNXInterface.Open")
End Sub
So far I am getting an error stating "Method 'CreateObject' of object IActCtx' failed" when it attemps to run this line of code:
<br />
Set myNX = actCtx.CreateObject("ExcelNXInterface.Open")<br />
The DLL I built to expose .NET calls to VBA, the Excel Workbook making the VBA calls and the Manifest are all in the same directory.
Any help or guidance is appreciated. Thank you.
modified 19-Oct-16 12:05pm.
|
|
|
|
|
Obviously, you need to create your own Guids.
I believe you'd use the Guid from the IDispatch interface, but it's a long time since I've had to touch COM at that level.
Member 12336929 wrote:
progid="ExcelNXInterface.Open"
Set myNX = actCtx.CreateObject("ExcelNXInterface.Open")
That doesn't seem to match the name of the class you created. Did you mean to use ExcelNXInterface.ExcelNXInterface instead?
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Okay, based on some other examples I found online I saw that some people used the progid in the manifest. I wasn't sure why, but I just followed the examples. So I went ahead and tried using your suggestion. This time around I got another error, but it seems much friendlier (maybe).
It says "ActiveX component can't create Object". So maybe using ExcelNXInterface.ExcelNXInterface was the way to go, even though it still isn't working. It seems better than the error saying the Create Object Method Failed.
Anyway, I am pretty much lost from here out. Not sure what else can be done. I have seen in other forums online that some people claim in order to pull this off you need to alter the Excel.exe.manifest file to point to your dll, and store the dll in the same folder as Excel's executable file. I'm hoping that isn't true.
|
|
|
|
|
I suspect you'd need to update the progId in the manifest to ExcelNXInterface.ExcelNXInterface as well.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Okay so I changed the manifest to reflect the new progid: ExcelInterface.ExcelInterface .
I assumed that also meant that I should change the progid in the DLL to match the manifest. I changed the following line:
ProgId("ExcelNXInterface.ExcelNXInterface")> Public Class ExcelNXInterface .
As a result I am getting the following error: Method 'CreateObject' of object IActCtx failed.
Thank you for your help by the way.
|
|
|
|
|
Member 12336929 wrote: ExcelInterface.ExcelInterface
Member 12336929 wrote: ProgId("ExcelNXInterface.ExcelNXInterface")
Which is it? These should both match.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I am trying to do some stuff with the CommonItemDialog, which means COM. I have compiled shobjidl.idl with midl, and created an interop with tlbimp. However, when I reference that interop in VS2015, some of the definitions are just not there - in particular, I cannot see the IFileDialog2 interface. I looked at the idl, and the generated .c and .h files, and I cannot see anything that might exclude this interface.
Does anyone have any ideas what is going on here? Its been years since I touched the C++/COM stuff, so its more than likely there's something I have forgotten.
PS: I was going to post this in Quick Answers, but I thought I'd put it here instead just to give Rob Philpott[^] a reason to start screaming again (ref Discussions/General Programming/COM[^])
Cheers,
Mick
------------------------------------------------
It doesn't matter how often or hard you fall on your arse, eventually you'll roll over and land on your feet.
|
|
|
|
|
Hi,
I want to debug COM dll solution through another ASP.Net solution (IIS).
Solution A - COM dll which outputs 4 com dll's.
Solution B - ASP.Net which access, solution A COM dll's. This solution was hosted in IIS
Solution B I able to debug through Visualstudio->Debug->attachtoprocess->w3wp.exe
But when solution B calls COM dll which is from solution A , I cannot debug Solution A(COM Dll).
Please suggest solution for debugging.
(Usually I debug the dll solution through
VS->Project->properties->Debugging->command->setting target exe path. But here it is asp.net solution, so I don't know what to give in Target exe path)
|
|
|
|
|
You'll probably need a debugger that is suitable for the language the COM object was built on. Remember COM is just an interface, it is a way of making code language-agnostic, so if the COM dll is VB6 use VB6 IDE, if it's a C++ object then again use a C++ debugger.
|
|
|
|
|
I want to replace the Window's stock (gregorian) calendar with an English version of the Hebrew(Israel) calendar. I know that I will have to code this (or at least hack the resources in a dll), but I don't know where to begin.
On the "Date" tab, of "Customize Format" window, there is a "Calendar type" option available for some "Region Formats"... ie. Hebrew(Israel)...
I would like to implement an English variant of the "Hebrew(Israel)" sacred calendar. Because there is currently no way to have that calendar format in the english language (from the system tray calendar, for example).
I know that this will require coding, and most likely with COM. If there is a working solution that just involves resource hacking, that is fine instead.
I don't know where to begin this adventure so I thought that I'd ask here. This is where I've started:
Retrieving Time and Date Information (Windows)[^] , but I can find nothing about the system's calendar themselves (the objects). I will not use .NET for anything; If I am going to do this, I am going to do it right (with real native code).
If anyone has any tips... even some debugging strategy that might shed some light into this tunnel -- it would be much appreciated. Thank you.
|
|
|
|
|
|
That actually helps a little (got a couple more results than my search @ DuckDuckGo.com).
It looks like I can recreate the whole calendar experience to whatever degree that I'd like to. So the problem becomes integrating the "new" calendar into the Windows taskbar tray (replacing or complimenting the existing system calendar).
|
|
|
|
|
I am not sure if that is possible. Have you tried adjusting your regional settings?
|
|
|
|
|
Of course I have... HAVE YOU? Don't waste your life "answering" a question if you have done zero research... thanks.
|
|
|
|
|
No need to be abusive, it was a perfectly reasonable question. You would be amazed (or maybe not) at the number of people who do none.
|
|
|
|
|
getting heated 
|
|
|
|
|
I want to get the context menu items on the mail item(outbox of outlook) programmatically from my outlook add-in. I ideally want to programmatically in C# get the context menu item on a mail item and perform invoke operation on the custom context menu item say "MyContextMenuItem". Everything getting context menu on mail item, iterating to find my item and performing the click, should happen programmatically. I googled around and found to add context item but not able to retrieve programmatically. Your reply would be of great help.Please Find the attachment for more details.
Thank you..
|
|
|
|
|
Why is it that this native code works to create an IShellLink object:
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
But this managed code throws "COM Error: Class not registered"
var Link = new Shell32.ShellLinkObject();
In the C# project I have a reference to Shell32. I'm on Windows 10 x64 and I have the C# project set to build for "Any CPU".
So what's the problem here?
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
I'm writing a COM server exe using CLSCTX_LOCAL_SERVER as below.
1. COM Server
. Use IDL language to define a interfaceID, classID.
. Call CoRegisterClassObject to register a factory object
. I designed COM Server source code as below
class CMyFactory : public IClassFactory
{
};
class CMyObj : public IUnknown
{
-----class XSubClass : public IMyInterface
-----{
-----}m_subClass;
-----friend class CMyObj;
}
Before starting COM Server, I call CoRegisterClassObject to register factoryObject to system.
2. COM Client
. IMyInterface* pObj;
. CoGetClassObject(CLSID_CoMyObj, CLSCTX_LOCAL_SERVER, NULL, IID_IClassFactory, (void **) &pFac);
. pFac->CreateInstance(NULL,IID_interfaceID,(void**)&pObj);
However, the result of CreateInstance calling is "E_NOINTERFACE No such interface supported".
Could you please tell me the way to solve it?
|
|
|
|
|
|
But it doesn't mention about COM Local sever
|
|
|
|
|
|
Dear All,
I am doing some development with a Logitech C920. I tried to maximize the resolution of C920 to 1920X1080, which it can support. The setting is successful as hr is S_OK. Then I use a samplegrabber to get the image, which is always 640X480. Something is wrong. I am brand new to DirectShow. All my code is based on other's sample code. So, could anyone give me a help?
Best,
Gary
/////////////////////////////////////////////////////////////
void videoCapture::SetResolution(IBaseFilter* pSrcFilter, int Width, int Height)
{
IAMStreamConfig *pConfig = NULL;
pCapture->FindInterface(&PIN_CATEGORY_STILL,
&MEDIATYPE_Video, pSrcFilter, IID_IAMStreamConfig, (void**)&pConfig);
int resolutions, size;
VIDEO_STREAM_CONFIG_CAPS caps;
pConfig->GetNumberOfCapabilities(&resolutions, &size);
for (int i = 0; i < resolutions; i++)
{
AM_MEDIA_TYPE *mediaType;
if (pConfig->GetStreamCaps(i, &mediaType,
reinterpret_cast<byte*>(&caps)) == S_OK)
{
int maxWidth = caps.MaxOutputSize.cx;
int maxHeigth = caps.MaxOutputSize.cy;
if (maxWidth == Width && maxHeigth == Height)
{
VIDEOINFOHEADER *info = reinterpret_cast<videoinfoheader*>(mediaType->pbFormat);
info->bmiHeader.biWidth = maxWidth;
info->bmiHeader.biHeight = maxHeigth;
info->bmiHeader.biSizeImage = DIBSIZE(info->bmiHeader);
HRESULT hr = pConfig->SetFormat(mediaType);
DeleteMediaType(mediaType);
break;
}
DeleteMediaType(mediaType);
}
}
SAFE_RELEASE(pConfig);
}
/////////////////////////////////////////////////////////////
HRESULT videoCapture::CaptureVideo(unsigned int devIndex)
{
if (devIndex == 0)
devIndex = 1;
HRESULT hr;
IBaseFilter *pSrcFilter = NULL;
// Attach the filter graph to the capture graph
hr = pCapture->SetFiltergraph(pGraph);
if (FAILED(hr)) {
Msg(TEXT("Failed to set capture filter graph! hr=0x%x"), hr);
return hr;
}
// Use the system device enumerator and class enumerator to find
// a video capture/preview device, such as a desktop USB video camera.
hr = FindCameraDevice(&pSrcFilter);
if (FAILED(hr)) {
// Don't display a message because FindCaptureDevice will handle it
return hr;
}
// Add Capture filter to our graph.
hr = pGraph->AddFilter(pSrcFilter, L"Video Capture");
if (FAILED(hr)) {
Msg(TEXT("Couldn't add the capture filter to the graph! hr=0x%x\r\n\r\n")
TEXT("If you have a working video capture device, please make sure\r\n")
TEXT("that it is connected and is not being used by another application.\r\n\r\n")
TEXT("The sample will now close."), hr);
SAFE_RELEASE(pSrcFilter);
return hr;
}
hr = SetCameraExposure(pSrcFilter, 100);
hr = pImageGrabber->InitSampleGrabber(pGraph);
if (FAILED(hr)) {
Msg(TEXT("Couldn't add the SampleGrabber filter to the graph! hr=0x%x"), hr);
return hr;
}
hr = pImageGrabber->SetSampleGrabberMediaType();
if (FAILED(hr)) {
Msg(TEXT("Couldn't set the SampleGrabber media type! hr=0x%x"), hr);
return hr;
}
SetResolution(pSrcFilter, 1920, 1080);
IBaseFilter* pGrabber = pImageGrabber->GetSampleGrabber();
hr = pCapture->RenderStream(NULL, &MEDIATYPE_Video,
pSrcFilter, pGrabber, NULL);
hr = pImageGrabber->GetSampleGrabberMediaType();
if (FAILED(hr)) {
Msg(TEXT("Couldn't get the SampleGrabber media type! hr=0x%x"), hr);
return hr;
}
// Now that the filter has been added to the graph and we have
// rendered its stream, we can release this reference to the filter.
SAFE_RELEASE(pSrcFilter);
#ifdef REGISTER_FILTERGRAPH
// Add our graph to the running object table, which will allow
// the GraphEdit application to "spy" on our graph
hr = AddGraphToRot(g_pGraph, &g_dwGraphRegister);
if (FAILED(hr)) {
Msg(TEXT("Failed to register filter graph with ROT! hr=0x%x"), hr);
g_dwGraphRegister = 0;
}
#endif
// Start previewing video data
hr = pMC->Run();
if (FAILED(hr)) {
Msg(TEXT("Couldn't run the graph! hr=0x%x"), hr);
return hr;
}
return S_OK;
}
|
|
|
|
|
I have built a COM DLL with a number of functions in version 1:
- OnlineAvailCheck_V2 --> first public function
- DownloadProductInfo_V2 --> second public function
- DownloadPriceInfo_V2 --> third public function
The COM DLL is called from an external application; the functions appear in the same order as shown above.
In version 2, the DownloadProductInfo function has become obsolete, and needs to be replaced by V31
- OnlineAvailCheck_V2 --> first public function
- DownloadProductInfo_V2 --> becomes private
- DownloadPriceInfo_V2 --> second public function
- DownloadProductInfo_V31 --> third public function
If I make the V2 function private (because it must no longer be used), the external application makes a shift in the code: all references to DownloadProductInfo_V2 are now replaced by references to the third public function, i.e. DownloadPriceInfo_V2 function.
Is there any way I can give a fixed sequence number to the functions, so that I can avoid the shift? Or is there any other way to deal with this? Thank you.
Dox Girl, where are you?
|
|
|
|
|