C# COM Object Issues

G

Guest

Hi all,

At a high level here is what is going on -- I built a C# COM object. I need to call this com object from SQL Server using the sp_OACreate stored procedure in SQL Server. I build the COM object, register it using regasm, but when I try to call it in SQL Server I get the following error message - "0x80070002 Extended Procedure The system cannot find the file specified." I have tried registering the DLL with regsvr32 and that returns the message "fsi.dll was loaded, but the DllRegisterServer entry point was not found. DllRegisterServer may not be exported, or a corrupt version of fsi.dll may be in memory. Consider using PView to detect and remove it." Well I checked PView and there are no fsi.dll in memory. So, what my hopes are that someone has built a COM object in .NET, registered it, and was able to call it using sp_OACreate. Any help or ideas at this point would be greatly appreciated.

Step 1 (C# COM Source Code [compiled with COM Interoptibility set to true]
-----------------------------------------------------
using System;
using System.ComponentModel;
using System.Collections;
using System.Diagnostics;


namespace fsi
{
public class com : System.ComponentModel.Component
{
private System.ComponentModel.Container components = null;


public static void Main()
{

}

public static void Main(string[] args)
{

}

public com(System.ComponentModel.IContainer container)
{
///
/// Required for Windows.Forms Class Composition Designer support
///
container.Add(this);
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
}


public com()
{
///
/// Required for Windows.Forms Class Composition Designer support
///
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
}

public string test()
{
return "Success";
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}


#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}


Step 2 (Register dll on server with regasm)
- Returns success

Step 3 (Call base stored procedure on server)
------------------------------------------------------
DECLARE @object int
DECLARE @hr int
DECLARE @src varchar(255), @desc varchar(255)
EXEC @hr = sp_OACreate 'fsi.com', @object OUT
IF @hr <> 0
BEGIN
EXEC sp_OAGetErrorInfo @object, @src OUT, @desc OUT
SELECT hr=convert(varbinary(4),@hr), Source=@src, Description=@desc
RETURN
END
 
G

Guest

My apologies for the second post. When I did the first one I received a failure message that my message did not make it because an error occurred. However, it appears it still did...
 
P

Phil Wilson

Your C# COM object needs to be a class library - your code below looks like
an exe. Something like this in your class library is what it should look
like. Obviously the guids and progid need to match what the client is
expecting. Then run regasm on it. I've no idea how SQL gets to your COM
method, so what follows is a guess, but if it really is COM it will require
a Guid or a progid, and I expect it might be late binding, so the parameters
need to be automation-compatible (stick to string, int ! ).

[ComVisible(true), GuidAttribute(" get a unique guid here")]
[ProgId("Your.progid")]
public class someclass
{

public string somemethod ()
{
return "hello";
}
}
--
Phil Wilson [MVP Windows Installer]
----
gman997 said:
Hi all,

At a high level here is what is going on -- I built a C# COM object. I
need to call this com object from SQL Server using the sp_OACreate stored
procedure in SQL Server. I build the COM object, register it using regasm,
but when I try to call it in SQL Server I get the following error message -
"0x80070002 Extended Procedure The system cannot find the file specified."
I have tried registering the DLL with regsvr32 and that returns the message
"fsi.dll was loaded, but the DllRegisterServer entry point was not found.
DllRegisterServer may not be exported, or a corrupt version of fsi.dll may
be in memory. Consider using PView to detect and remove it." Well I
checked PView and there are no fsi.dll in memory. So, what my hopes are
that someone has built a COM object in .NET, registered it, and was able to
call it using sp_OACreate. Any help or ideas at this point would be greatly
appreciated.
Step 1 (C# COM Source Code [compiled with COM Interoptibility set to true]
-----------------------------------------------------
using System;
using System.ComponentModel;
using System.Collections;
using System.Diagnostics;


namespace fsi
{
public class com : System.ComponentModel.Component
{
private System.ComponentModel.Container components = null;


public static void Main()
{

}

public static void Main(string[] args)
{

}

public com(System.ComponentModel.IContainer container)
{
///
/// Required for Windows.Forms Class Composition Designer support
///
container.Add(this);
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
}


public com()
{
///
/// Required for Windows.Forms Class Composition Designer support
///
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
}

public string test()
{
return "Success";
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}


#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}


Step 2 (Register dll on server with regasm)
- Returns success

Step 3 (Call base stored procedure on server)
------------------------------------------------------
DECLARE @object int
DECLARE @hr int
DECLARE @src varchar(255), @desc varchar(255)
EXEC @hr = sp_OACreate 'fsi.com', @object OUT
IF @hr <> 0
BEGIN
EXEC sp_OAGetErrorInfo @object, @src OUT, @desc OUT
SELECT hr=convert(varbinary(4),@hr), Source=@src, Description=@desc
RETURN
END
 
G

Guest

The methods/properties of your class object that need to be exposed through COM need only be defined as 'public'.

Once your DLL is generated it will need to be installed in the GAC on the target computer for all other programs to use. See http://support.microsoft.com/default.aspx?scid=kb;en-us;815808.

gman997 said:
Hi all,

At a high level here is what is going on -- I built a C# COM object. I need to call this com object from SQL Server using the sp_OACreate stored procedure in SQL Server. I build the COM object, register it using regasm, but when I try to call it in SQL Server I get the following error message - "0x80070002 Extended Procedure The system cannot find the file specified." I have tried registering the DLL with regsvr32 and that returns the message "fsi.dll was loaded, but the DllRegisterServer entry point was not found. DllRegisterServer may not be exported, or a corrupt version of fsi.dll may be in memory. Consider using PView to detect and remove it." Well I checked PView and there are no fsi.dll in memory. So, what my hopes are that someone has built a COM object in .NET, registered it, and was able to call it using sp_OACreate. Any help or ideas at this point would be greatly appreciated.

Step 1 (C# COM Source Code [compiled with COM Interoptibility set to true]
-----------------------------------------------------
using System;
using System.ComponentModel;
using System.Collections;
using System.Diagnostics;


namespace fsi
{
public class com : System.ComponentModel.Component
{
private System.ComponentModel.Container components = null;


public static void Main()
{

}

public static void Main(string[] args)
{

}

public com(System.ComponentModel.IContainer container)
{
///
/// Required for Windows.Forms Class Composition Designer support
///
container.Add(this);
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
}


public com()
{
///
/// Required for Windows.Forms Class Composition Designer support
///
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
}

public string test()
{
return "Success";
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}


#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}


Step 2 (Register dll on server with regasm)
- Returns success

Step 3 (Call base stored procedure on server)
------------------------------------------------------
DECLARE @object int
DECLARE @hr int
DECLARE @src varchar(255), @desc varchar(255)
EXEC @hr = sp_OACreate 'fsi.com', @object OUT
IF @hr <> 0
BEGIN
EXEC sp_OAGetErrorInfo @object, @src OUT, @desc OUT
SELECT hr=convert(varbinary(4),@hr), Source=@src, Description=@desc
RETURN
END
 
G

Guest

Thanks Guys!! It works, I added the strong name followed by the directions in the knowledge base. I also added the attributes as suggested by Phil. I added the dll to GAC and then ran regasm. Hopped back into SQL Server and bingo it all works. I am listing the updated source code here for reference to others. This is really cool though calling a .NET method from SQL Server with COM.

using System;
using System.ComponentModel;
using System.Collections;
using System.Diagnostics;


namespace fsi
{
using interop = System.Runtime.InteropServices;
[
interop.ComVisible(true),
interop.Guid("78A7E9AD-B31B-3AF0-B931-2E1258CC1BD1")
]

public class com : System.ComponentModel.Component
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;


public static void Main()
{

}

public static void Main(string[] args)
{

}

public com(System.ComponentModel.IContainer container)
{
///
/// Required for Windows.Forms Class Composition Designer support
///
container.Add(this);
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
}


public com()
{
///
/// Required for Windows.Forms Class Composition Designer support
///
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
}

public string test()
{
return "Success";
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}


#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top