Using COM object in C# - c#

I'm trying to use TrustCommerce in my website. I installed dll files from the website, but I can't use it' I'm supposed to be able to use myObject.PushParam(string) and it's not working. Is there something I'm missing here? I found an article about it in PHP:
public static void TrustCommerce()
{
//TCLinkNET.TClinkClass.
object myObject = Orders.COMCreateObject("TCLINKCOMLib.TClinkClass");
}
public static object COMCreateObject(string sProgID)
{
// We get the type using just the ProgID
Type oType = Type.GetTypeFromProgID(sProgID);
if (oType != null)
{
return Activator.CreateInstance(oType);
}
return null;
}

add COM reference to your project, then an introp assembly will be generated for the COM. the way you are using requires reflection to invoke COM methods. 3.5 or less, do not forget to distribute the interop assembly with your application installer.

Related

Retrieve <Version> tag written in csproj file from dll [duplicate]

I am trying to get the executing assembly version in C# 3.0 using the following code:
var assemblyFullName = Assembly.GetExecutingAssembly().FullName;
var version = assemblyFullName .Split(',')[1].Split('=')[1];
Is there another proper way of doing so?
Two options... regardless of application type you can always invoke:
Assembly.GetExecutingAssembly().GetName().Version
If a Windows Forms application, you can always access via application if looking specifically for product version.
Application.ProductVersion
Using GetExecutingAssembly for an assembly reference is not always an option. As such, I personally find it useful to create a static helper class in projects where I may need to reference the underlying assembly or assembly version:
// A sample assembly reference class that would exist in the `Core` project.
public static class CoreAssembly
{
public static readonly Assembly Reference = typeof(CoreAssembly).Assembly;
public static readonly Version Version = Reference.GetName().Version;
}
Then I can cleanly reference CoreAssembly.Version in my code as required.
In MSDN, Assembly.GetExecutingAssembly Method, is remark about method "getexecutingassembly", that for performance reasons, you should call this method only when you do not know at design time what assembly is currently executing.
The recommended way to retrieve an Assembly object that represents the current assembly is to use the Type.Assembly property of a type found in the assembly.
The following example illustrates:
using System;
using System.Reflection;
public class Example
{
public static void Main()
{
Console.WriteLine("The version of the currently executing assembly is: {0}",
typeof(Example).Assembly.GetName().Version);
}
}
/* This example produces output similar to the following:
The version of the currently executing assembly is: 1.1.0.0
Of course this is very similar to the answer with helper class "public static class CoreAssembly", but, if you know at least one type of executing assembly, it isn't mandatory to create a helper class, and it saves your time.
using System.Reflection;
{
string version = Assembly.GetEntryAssembly().GetName().Version.ToString();
}
Remarks from MSDN http://msdn.microsoft.com/en-us/library/system.reflection.assembly.getentryassembly%28v=vs.110%29.aspx:
The GetEntryAssembly method can return null when a managed assembly has been loaded from an unmanaged application. For example, if an unmanaged application creates an instance of a COM component written in C#, a call to the GetEntryAssembly method from the C# component returns null, because the entry point for the process was unmanaged code rather than a managed assembly.
Product Version may be preferred if you're using versioning via GitVersion or other versioning software.
To get this from within your class library you can call System.Diagnostics.FileVersionInfo.ProductVersion:
using System.Diagnostics;
using System.Reflection;
//...
var assemblyLocation = Assembly.GetExecutingAssembly().Location;
var productVersion = FileVersionInfo.GetVersionInfo(assemblyLocation).ProductVersion
This should do:
Assembly assem = Assembly.GetExecutingAssembly();
AssemblyName aName = assem.GetName();
return aName.Version.ToString();
I finally settled on typeof(MyClass).GetTypeInfo().Assembly.GetName().Version for a netstandard1.6 app. All of the other proposed answers presented a partial solution. This is the only thing that got me exactly what I needed.
Sourced from a combination of places:
https://msdn.microsoft.com/en-us/library/x4cw969y(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/2exyydhb(v=vs.110).aspx

Creating an instance of a COM interop class

I am trying to open CorelDRAW from within my program using C#. So far I have been able to do so by referencing the appropriate com library and calling
CorelDRAW.Application draw = new CorelDRAW.Application();
draw.Visible = true;
However, I would like my program to work with any version of CorelDRAW that supports interop. I am attempting to use reflection to load the interop library at runtime, where the specific dll can be chosen for the correct version. From looking around I have tried the following.
string path = "Interop.CorelDRAW.dll";
Assembly u = Assembly.LoadFile(path);
Type testType = u.GetType("CorelDRAW.Application");
if (testType != null)
{
object draw = u.CreateInstance("CorelDRAW.Application");
FieldInfo fi = testType.GetField("Visible");
fi.SetValue(draw, true);
}
The program fails at u.CreateInstance... fails because CorelDRAW.Application is an interface, not a class. I have also tried replacing CorelDRAW.Application with CorelDRAW.ApplicationClass as that is available when I browse through Interop.CorelDRAW as a resource, but then u.getType... fails.
How can I get this to work? Thank you!
You can create instances of registered ActiveX objects using following construct:
Type type = Type.GetTypeFromProgID("CorelDRAW.Application", true);
object vc = Activator.CreateInstance(type);
Then you have 3 options, on how to work with returned object.
Casting returned object to real CorelDRAW.Application interface, but for this you need to reference some CorelDraw library which contains it, and probably this will produce versioning problems.
Reflection, which you mention in your question.
Use dynamic keyword, so you can call existing methods and properties just like it was a real CorelDraw class/interface.
Type type = Type.GetTypeFromProgID("CorelDRAW.Application", true);
dynamic vc = (dynamic)Activator.CreateInstance(type);
vc.Visible = true;
System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFrom(fullPath);
dynamic app = assembly.CreateInstance("CorelDRAW.ApplicationClass", true);
this is gonna work

Get A GUID by Type Name

So I'm trying to do manually what AxImp does (I'm doing it dynamically).
My product is a wide released, sanctioned "add-on" to a third party product. They have an OCX, which I add to my form with a COM reference...however, if the client has (or installs) an updated version of their product my product can no longer load the OCX.
Therefore I'm trying to load their OCX dynamically. I've got everything working except that I need the GUID of one of the interfaces in one of their OCXs. I know what the type name is, and the OCX >is< registered on the system. How can I get an object's GUID just from the type name?
Note, Assembly.LoadFrom() doesn't work because the OCX isn't .NET it's COM.
Since your comment let us know that the GUID is found in the OCX but not registered under HKEY_CLASSES_ROOT, we'll have to read it from the type library:
Call LoadTypeLib or LoadTypeLibEx, passing the path to the .OCX file
Then use the FindName method of the returned object.
Then GetTypeAttr followed by PtrToStructure to get a TYPEATTR structure with the GUID.
Not sure why you can't simply add a COM reference to the DLL to your project.
Visual Studio will automatically add a .NET wrapper to any COM object that is referenced this way.
I had to write something like that to migrate code from COM to C#
class GetGuid
{
[DllImport("oleaut32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
static extern int LoadTypeLib(string fileName, out ITypeLib typeLib);
public string SearchRegistry(string dllPath /* or ocx */)
{
var result = string.Empty;
ITypeLib tl;
if (LoadTypeLib(dllPath, out tl) == 0)
{
ITypeInfo tf;
tl.GetTypeInfo(0, out tf);
var ip = IntPtr.Zero;
tl.GetLibAttr(out ip);
if (ip != IntPtr.Zero)
{
var ta = (System.Runtime.InteropServices.ComTypes.TYPELIBATTR)Marshal.PtrToStructure(ip, typeof(System.Runtime.InteropServices.ComTypes.TYPELIBATTR));
result = ta.guid.ToString();
}
}
return result;
}
}

Having trouble registering assembly for COM

I have created a simple class library project in visual studio 2008 that has one class as shown below. I am trying to get this class to register for COM interop so that I can use in via unmanaged scripts like vbscript or jscript.
In my project build properties I have checked the box that says "Register for COM Interop".
In the Assembly Settings I have checked "Make this assembly COM Visible" and I have confirmed that the [assembly: ComVisible(true)] attribute is present in the assembly.cs file.
Every time I build this project I get an error that reads "projectname.dll does not contain any types that can be registered for COM Interop. Also, I have not been able to successfully create an instance of class 1 using a vbscript. Does anyone know that this is not registering properly?
My vbscript fails to create activex object at this line... Set F = CreateObject("64BitCLTest.Class1").
Finally, how do I get VS to register this in the 64bit area of the registry instead of the 32 bit area so that 64bit processes can use it?
-- The Test Class--
namespace _64BitCLTest
{
[Guid("BBAA06EF-CA4C-4fe2-97CD-9B1D85ADA656")]
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
[ProgId("64BitCLTest.Class1")]
public class Class1
{
Class1()
{
// do nothing
}
public string Method1()
{
return "This is a return string from method 1";
}
public int Property1
{
get {return 777;}
}
}
}
you need to mark the constructor public:
-- The Test Class--
namespace _64BitCLTest
{
[Guid("BBAA06EF-CA4C-4fe2-97CD-9B1D85ADA656")]
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
[ProgId("64BitCLTest.Class1")]
public class Class1
{
public Class1()
{
// do nothing
}
public string Method1()
{
return "This is a return string from method 1";
}
public int Property1
{
get {return 777;}
}
}
}
There are two parts to this answer. The first, problem as consultutah said was that I did not have the constructor marked as public.
The second answer is that there is a bug (I believe) in VS2008 that causes assemblies to never be registered in the 64-bit section of the registry, even if the setup project is configured for a target platform of x64.
I installed VS2010, rebuilt the exact same project and ran the Install. The assembly registered perfectly and I was able to successfully access it through COM using a 64bit process. I still have not found a solution for this in VS2008.

Calling C# dll in vbscript

I am trying to call a C# dll from QTP (uses vbscript). I have tried a number of things with no success:
Visual Studio 2010
Create C# class libary (st.dll)
code:
using System;
using System.Collections.Generic;
using System.Text;
namespace st
{
public class Class1
{
public static int GetValue()
{
return 34;
}
}
}
regasm /codebase st.dll
fails 'because it is not a valid .NET assembly'
In QTP/vbscript, I have tried
extern.Declare micInteger, "GetValue", "e:\st.dll", "GetValue"
Returns message: 'Invalid procedure call or argument'
Regardless of QTP, I would greatly appreciate any insight on how to call the c# dll from a .vbs file.
I was able to get this working by doing the following:
Create a new C# dll in VS 2010.
namespace st4
{
public class st4_functions
{
public int GetValue()
{
return 34;
}
}
}
In QTP I added the following lines:
Set obj = DotNetFactory.CreateInstance("st4.st4_functions", "c:\\st4.dll")
MsgBox obj.GetValue()
Thanks to all that responded to my problem. Though I did not do the COM solution, it got me thinking that I could stay with .NET and led to this solution. Good job all!
EDIT:
I created a blog post to detail the steps and provide additional information:
http://www.solutionmaniacs.com/blog/2012/5/29/qtp-calling-c-dll-in-vbscript.html
As Marc said, but I think it merits an answer. If you ensure that your dll will be available though the COM mechanics, your script should be able to call into it with things like CreateObject.
How to register .NET assembly for COM interop
Your function is static. Static class members can't be matched up to interface members, and if it can't implement a .NET interface then it certainly won't implement a COM interface.

Categories

Resources