Monday, August 20, 2018

Calling .NET From COM
Originally posted by Mikec276 on C Sharp Friends

It might be hard to convince your IT manager to let you build your entire system from scratch in C#, just because you think it is cool. A better trick is to start building new bits with .NET, and slowly integrate them into the old system before anyone has a chance to discover what you are up to ;-). But for that you have to be able to call them from your existing COM systems.

It turns out that this is very easy. Here is a simple example of calling a C# object from a COM technology platform (vbscript).

General Steps

1. Build a simple C# class, inside say a Library assembly (DLL).

2. Use the Framework-provided REGASM tool to add the registry entries necessary for it to be called via COM.

3. Call your object from the 'legacy' code.

The C# Class

A simple class to demonstrate this functionality, with a couple of simple string and int properties, is as follows:
using System;

namespace SampledotNETDLL
{
    public class Customer
    {
        private string msName;
        private int miHatSize;

        public Customer()
        //default constructor needed to access from COM.
        {
            this.CustomerName = "John Doe";
            miHatSize = 12;

        }

        public void Init(string Name)
        {
            this.CustomerName = Name;
            Random rand = new Random();
            miHatSize = rand.Next(8)+7;
        }

        public string CustomerName
        {
            get    { return msName; }
            set     { msName = value; }
        }

        public int HatSize
        {
            get    { return miHatSize; }
        }
    }
}
Note the use of a public no-args constructor. For this to be called from COM it has to have a public no-args constructor. Any member-specific initialisation is done in a separate method 'Init'. Build this class, then we will register it so that COM can call it.

Registering the .NET Assembly

The .net framework provides a tool called REGASM.EXE, that you can use to create the necessary registry entries for your new assembly. It is simple to use, from the command prompt simply type:
REGASM [path to assembly]
The assembly will then be registered in the HKEY_LOCAL_MACHINE hive of the registry, just like a COM DLL. Note if you see this error:

RegAsm warning: No types were registered

Then it may be because your potential COM-accessible classes do not have no-args constructors required to make them COM-able (yes I discovered this the hard way ;-) ).

Call the Object with COM

For this example we will call the Customer object(s) from Vbscript. For this to work, we need to copy the DLL into the path of the wscript/cscript applications, which are found in C:\WINNT\System32. I will explain later how we can avoid this step. Then create a VBScript file, something like the following:
dim oCustomer
set oCustomer = CreateObject("SampledotNETDLL.Customer")
if err.number <> 0 then
    msgbox "Error " & Err.number & " Creating Customer: " 
   & Err.description
else
    msgbox "Customer exists: " & Cstr(not(oCustomer is nothing))
    oCustomer.Init "Frank Smith"
    msgbox "Customer Name: " & oCustomer.CustomerName &
             " Hat Size: " & oCustomer.Hatsize
end if
Note that the CreateObject uses [namespace].[classname] as the ProgID. We can change this, more on this later. If we run this you should get two message boxes, one saying

Customer exists: True

The other saying

Customer Name: Frank Smith Hat Size: [some number]

You can of course alter the code to suit your requirements, calling the C# code from VB, C++, Jscript or any other COM-enabled 'client'.

Changing the ProgID

You can give your class any ProgID you like, if you don't like the default of [namespace].[classname]. To do this, simply add
using System.Runtime.InteropServices;
to your class, and give the class itself the following attribute:
[ProgID("MySample.Customer")]
...which would change the ProgID to "MySample.Customer", for example. You can of course change this to whatever you desire. If you add this in remember to use REGASM on your new DLL once it is rebuilt ;-).

Making the Assembly Globally Accessible

In the above example we had to copy the assembly into the path of the 'client', which was the scripting host (wscript or cscript). To avoid this step, and make the assembly globally accessible, we simply give the assembly a strong name, and register it with the .net Global Assembly Cache (GAC) in the usual manner. I'm going to assume you know how to do that, as it is a general .NET detail and not specific to COM interoperability.

Using the GAC works because the .NET CLR is, at runtime, creating what is know as a COM Callable Wrapper (CCW) for your assembly. If your assembly is not in the GAC, and not in the path of the client, the CCW simply won't find your assembly, just as for standard multi-assembly .NET programming. Incidently the error message you get back is not overly helpful (yes I found this out the hard way too ;-) ), the VB Error object has the following data in it:

Error Number 0x80131522 (-2146233054)

Source: (null)

If you ever see this, then what it means is that the CCW can't find your assembly for some reason - it is not in the path of the client, nor was it found in the GAC. or any other COM-enabled 'client'.

Take it to the Streets

So now you have the knowledge you need to infiltrate your existing legacy systems with shiny new C# objects (which is what we REALLY want to write things in, right? ;-) ). 

Thursday, January 19, 2012

Banks... Ugh!

How much longer must I visit banks who only attempt to obtain private financing before some bank will submit the GD! SBA paperwork I've already filled out for them?  A banker told me the other day. "Let's be frank, my job is to get you the least amount of money with the highest interest rate possible; your job is to get the highest amount of money with the least amount of interest possible", as if it were really a negotiation!  My job is to get up and walk out the door telling you where you can put your high interest rates.  As a small business owner and veteran who has four employees and a business that's growing at a steady rate of speed. How about you just look at the paperwork I gave you and do your job and stop trying to rip off the successful small businesses! Geez!

Friday, December 2, 2011

Wells Fargo v. PayPal

I've recently had three clients who have all had Wells Fargo accounts.  They are small businesses and can't, nor want, to pay a lot of money for certificates, merchant accounts, bank fees, etc., so I recommended PayPal to them and Savvyon programmed some simple solution to their unique needs.

I received a call shortly after each client setup their PayPal account telling me that they had been contacted by Wells Fargo stating that they had noticed the 'test transactions' posted by PayPal and wanted them to switch to using their merchant account with CyberSource. Interesting to hear that Wells Fargo has clearly programmed some sort of alerts into their system that notifies sales people of someone's intent to use PayPal for something.  So if you setup a business account with PayPal and you have a Wells Fargo bank account, be prepared to receive a phone call!!

I would really like someone to convince me how having a monthly merchant account fee + bank transaction fees + annual SSL certificate costs + programming costs, etc., really is less expensive than a free PayPal account with a very nominal fee structure and a small wait time to withdraw monies is going to benefit small businesses that are trying to make ends meat and survive in this economy.

Monday, July 26, 2010

Looping through Content Controls in a Word Document

Code Snippet
  1. For Each contControl As Word.ContentControl In ThisAddin.MyAddIn.Application.ActiveDocument.ContentControls
  2.     'Do something with contcontrol
  3. Next

He will probably be bored with this job!

Lately I had an opportunity to interview with a great company.  The Vice President of IT was tremendously impressed with my credentials and seemed eager to have me join their team.  During the interview he stated that I would probably be bored with the job at hand.  I told him that for several years now I have been working jobs which were ‘heads down’ and required no critical thinking, problem solving or creative thought of any kind and that the job they were offering would be a pleasant change from the jobs I have been working in for years. Needless to say, I have only heard back from the recruiter once claiming again the company thought I would be bored with the position and the recruiter told me the company was wavering on the contract to perm price.  That’s the last I heard of it.  I sure wish more people would have the balls to pick up the phone and call someone to let them know they’ve been rejected rather than just not calling.  It would have been nice to work for them but oh well, I digress.

Calling .NET From COM Originally posted by Mikec276 on C Sharp Friends It might be hard to convince your IT manager to let you build y...