Set the GUID value of VSTO AddIn - c#

I don't understand how i can set the GUID value of a VSTO AddIn. In EventViewer i see Empty GUID: {00000000-0000-0000-0000-000000000000}.
I've tried using the Guid and ProgId attributes on the ThisAddIn class, but that doesn't help. Can you please tell me how to change the GUID.

That GUID is the COM GUID. It does not matter in a VSTO addin since VSTO loads your addin, not Outlook directly.

Guid (Globally unique identifier) is used to identify your component by outside world. When you write a project which is going to be used as COM (Component Object Model) you will have to give a unique name. For this reason you need to apply GUID attribute.
For VSTO add-ins you need to apply the Guid attribute to the assembly, not the add-in class like in case of other COM add-ins you could do that. For example, if you try to create a new VSTO add-in and open the AssemblyInfo.cs file (for C# projects) you may find the following entry there:
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("74776e40-0ee0-412c-b7aa-e39838a741c1")]
That makes sense only if you set the ComVisible to true. By default, VSTO doesn't use ProgID and Guid attributes for loading add-ins. Instead, the VSTOLoader is used for loading managed add-in assemblies without relying on the COM technology, so assemblies are not registered for the COM interop.

Related

How to register a MindJet MindManager AddIn?

I am looking for some technical help with MindJet MindManager. I have been playing with add-ins for a couple of days for MindJet MindManager. I have previously written my own macros which I wish to turn into add-ins. So far, I haven't found much information on authoring the add-ins.
I have been able to author as least one add-in from scratch and successfully register it in a hacking sort of way. Because, I wasn't able to register it normally I registered it under the name of an existing add-in by replacing the DLL(containing .net code) with my own. I built the project naming the ProgramId the same as the one I replaced and it loads perfectly. I can debug it from within visual studio.
System.Diagnostics.Debugger.Launch();
This is probably okay for me to install my menu commands and get what I need done.
Initially, I followed as much instruction as I could find on-line about how to manually install a mindjet add-in but content for this process is severely limited.
Next, I opened up MindManager and went to options under the AddIns menu. I could see the friendly name of the add-in taken from the registry where I set the correct values learned from the limited instructions. However, I noticed that there was no location showing in the bottom of the add-in options window where other add-ins did show a path. I have no idea how this path is created or where it is located from.
It seems pretty clear that since the location is missing my code surely won't load.
Of course, there may be something else I am missing that may further complicate things but this looks like a good place to start. I looked in the code of the managed .net assembly from some of the other add-ins(that were pre-installed) but found no sign of any location information. I also looked through the registry looking for similar location data with no luck.
I am running out of things to try and have spent the better part of two days looking for answer and have so far come up empty handed.
MindJet MindManager uses a COM add-in architecture. If you need to register a unmanaged native COM add-in you need to use RegSrv32 to add a record in the registry that will be used to locate the dll when MindManager tries to load its add-ins.
You can also author add-ins by using a managed .NET project and reference the wrapper library provided by MindJet. This library also needs to be registered but RegSrv32 doesn't know what to do with .NET managed libraries. Therefore, you must follow the following steps using RegAsm from the correct build of the .NET Framework.
Sign the AddIn with a strong name key
In assemblyInfo.cs set COM visible to true
[assembly: ComVisible(true)]
Register the type for interop RegAsm.exe
a)Use the correct version of .NET.
(In my case "C:\Windows\Microsoft.NET\Framework\v4.0.30319\regasm.exe")
b)This allows the application to find the location of the .dll
[Example command line:] C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe "C:\Program Files (x86)\Mindjet\MindManager 10\Automated.Mindjet.dll" /register /codebase

Can I control version number assigned to interop assembly?

I have a C# program that uses a native C++ COM object. Visual Studio generates an interop assembly with wrappers for the types in the COM object. Each time I recompile the C# program interop assembly has version 1.0.0.0.
This is bad for the installer - sometimes we extend the COM object interfaces (add new methods at the end of some interface) so the interop assembly has to be changed. when the installer tries to update an existing installation it thinks that the interop assembly hasn't changed (since it still has version 1.0.0.0) and skips updating it and the program doesn't work.
How can I control the version number assigned to the interop assembly?
It's been a little while so I might be remembering incorrectly how this works but I think that you might be able to do what you want if you use Tlbimp rather than having VS create the wrappers.
Possibly you could do it using the asmversion parameter and otherwise it might be possible if you give it a strong name using the keyfile parameter.

Find COM DLL path from Com Interop Assembly

I am trying to write a wrapper around a legacy COM object and install the wrapper into the GAC. The goal would be to automate the setup of specific configuration information the component requires, and make a common strongly typed interface for all of my applications to use.
My solution thus far is to keep an XML configuration file in the same directory as the original COM DLL, and load the configuration in the class constructor. Unfortunately, I have been unable to find the location of the registered COM dll...
How do I get the full file path of the COM dll referenced by a COM object interop dll?
Presumably you could get the GuidAttribute or CoClassAttribute values from the interop DLL that map to the CLSID and IID values of your COM DLL. Then you can look up the appropriate DLL path in the registry.
Once you've created an object from the respective COM server, its DLL must have been loaded. Assuming that the underlying COM server is implemented in "mycomserver.dll", you could use P/Invoke and call GetModuleHandle( "mycomserver.dll" ) -- that gives you the path of the DLL.
If you know the CLSID of the COM dll, you can check if there's a key with that CLSID on HKEY_CLASSES_ROOT\CLSID\{CLSID-of-your-COM-component} or HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{CLSID-of-your-COM-component} (Wow6432Node => 32-bit COM registered on a 64-bit machine)
If the key is there, it means that the COM component is registered. Then look at the default value inside the sub-key InprocServer32
e.g.
HKEY_CLASSES_ROOT\CLSID\{12345678-9012-3456-7890-123456789012}\InprocServer32
HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{12345678-9012-3456-7890-123456789012}\InprocServer32
If helps, here is a reference example of how to open these keys using C# (you'd just have to check for the value in InprocServer32): How to check COM dll is registered or not with C#?
Just reflect the AddIn class.
var t = typeof(ThisAddIn);
var path = t.Assembly.CodeBase;

Programmatically determine if a COM library (.DLL) is installed

Is there a programmatic way in C# to determine whether a particular COM DLL has been installed? Or is this a matter of scanning the registry for the classId?
What I usually did (and would do, if I needed this again) is try to create an object instance of a class you know is in the COM library - either by ProgID or GUID - and checking for failure.
Try and create it, and handle the error if not.
Under Win32 CoCreateInstance will return REGDB_E_CLASSNOTREG if not installed (including, IIRC, if registered but the dll/exe implementing it is then deleted).
Under .NET the generated COM interop assembly will throw some error (need to check this, don't have convenient code to test for which exception type). Note. if the interop assembly is missing then that will be treated as missing assembly possibly leading to an application load error.

Why does regasm.exe register my c# assembly with the wrong GUID?

I've got a c# assembly which I'm invoking via COM from a Delphi (win32 native) application.
This works on all the machines I've tested it on, except one.
The problem is that the Delphi application gets "Class not registered" when trying to create the COM object.
Now, when I look in the registry under HKEY_CLASSES_ROOT\DelphiToCSharp\CLSID, the GUID listed there is not the same as the assembly Guid in AssemblyInfo.cs. It should be the same - it IS the same on all the other computers where it's installed.
I have tried regasm /unregister delphitocsharp.dll, and that removes the registry key. Then if I do regasm delphitocsharp.dll, the registry key returns, but the GUID is the same as before (ie. wrong), and Delphi still gets "Class not registered".
DelphiToCSharp.dll on the working machine is identical (verified with md5) to the version on the non-working machine.
All I can think of is that an old version of the dll was registered before, and there still exists some remnant of that file which is making regasm confused.
How can I fix or at least further diagnose this issue?
The GUID in AssemblyInfo becomes the "Type-Library" GUID and usually is not what you'd be looking for. I'm going to assume you're trying to access a class, and you need to define a Guid attribute and ComVisible for the class. For example:
[Guid("00001111-2222-3333-4444-555566667777"), ComVisible(true)]
public class MyCOMRegisteredClass
If you don't, then the class either a) won't be registered, or b) if you've defined COMVisible(true) at the assembly level, will be assigned a guid that .NET bakes up for you.
Maybe you have an old version of the assembly somewhere? Maybe in the GAC? Regasm is probably picking that up and using it.
Most probably you have a copy of the same (old version) dll somewhere on your system, search disk for copies of the same file and remove (backup) them manually before registering the new copy.

Categories

Resources