what's wrong in my code related to COM?

2020-07-29 08:05发布

问题:

  *****BLOCK_1****

    if( strcmpi(appName.c_str(),MSSQL)==0 ||strcmpi(appName.c_str(),MSSQL2005)==0 )
{


      if (FAILED(CoCreateInstance (CLSID_SQLDMOServer, NULL, CLSCTX_INPROC_SERVER,
    IID_ISQLDMOServer, (LPVOID*)&m_pSQLServer))) {


    DMOAvailable=false;
    IDiscoverPtr pICalc;
    HRESULT hRes=CoCreateInstance(Test::CLSID_SqlClass, NULL,  CLSCTX_INPROC_SERVER,Test::IID_IDiscover, reinterpret_cast<void**> (&pICalc));

    if(FAILED(hRes))

         {
           cout << "CoCreateInstance Failed on CLSID_SQLDMOServer\n";

       return FALSE;
     }

***BLOCK_2***

if((strcmpi(appName.c_str(),MSSQL2008)==0 || strcmpi(appName.c_str(),MSSQL2005)==0 )    && DMOAvailable==false )
{

    HRESULT hr=CoInitialize(NULL);
    IDiscoverPtr pICalc(__uuidof(SqlClass));
    if(FAILED(CoCreateInstance(Test::CLSID_SqlClass, NULL, CLSCTX_INPROC_SERVER, 
        Test::IID_IDiscover, reinterpret_cast<void**> (&pICalc))))
    {
        cout<<" Loading SQLSMO failed This is because of SMO not Available "<<endl;
        return FALSE;
    }

}

*****BLOCK_3 ****

if((strcmpi(appName.c_str(),MSSQL2008)==0 && DMOAvailable==true))
{

    HRESULT hr= CoInitialize(NULL);

    cout<<"\nIn Init SqlServer DMO-true and SQL2008"<<endl;



    HRESULT hRes=CoCreateInstance(Test::CLSID_SqlClass, NULL, CLSCTX_INPROC_SERVER, 
    Test::IID_IDiscover, reinterpret_cast<void**> (&pICalc));
    if(FAILED(hRes))
    {
       printf(" Loading SQLSMO failed This is because of SMO not Available 0x%X\n",hRes)
       return FALSE;
    }
    else
        cout<<success;


}

return TRUE;
}


 I have prepared the Test.dll in c# and in that i have a an interface IDiscover and a     class SqlClass implementing that interface.I have Manually assigned the Guid like this

[System.Runtime.InteropServices.Guid("D4660088-308E-49fb-AB1A-77224F3FF851")]

public interface IDiscover
{
  string getSqlInstances(string HostName);

  string getDB(string SQLInstanceName);

  string getDatabaseInfo(string SQLInstanceName, string DBName);
};

namespace Test

  {

    [System.Runtime.InteropServices.Guid("46A951AC-C2D9-48e0-97BE-91F3C9E7B065")]

    public class SqlClass:IDiscover

  {

  }
}

I also make COMVisible=true;

and register the class using RegAsm.exe Test.dll/tlb:Test.tlb /codebase

and imported the tlb in one cpp file as #import c:...\Test.tlb named_guids

This is working fine in my Machine And also in My virtual Machine for any case.if i gave sql2005 it works and i gave sql2008 it working. and in some other machine it shows that errror code as 0x80004002 only when entering into 3rd block.if it enters 1st block and 2nd block its working fine in other machine also.what happening in 3rd block i am not understanding plzzzzzzzz help me in this regard...

Sharptooth u can plzz go through this one .....

回答1:

When working with COM, your assemblies should be "Release Builds". Make sure that's the case before digging around any further.



回答2:

These two statements:

IDiscoverPtr pICalc(__uuidof(SqlClass));

HRESULT hRes=CoCreateInstance(Test::CLSID_SqlClass, NULL, CLSCTX_INPROC_SERVER, Test::IID_IDiscover, reinterpret_cast<void**> (&pICalc));

do exactly the same thing, so you don't need to run them in sequence.

The first one translates the HRESULT into an exception of type _com_error. I'd try something like:

  IDiscoverPtr pDiscover;
  HRESULT hr = pDiscover.CreateInstance(__uuidof(SqlClass));
  if (FAILED(hr))
  {
    printf("SQL DMO is not avilable. Error code: 0x%X\n", hr);
  }

Could you post back what the error code is?



回答3:

The IDiscoverPtr constructor will throw an exception if it can't instantiate the COM object. The most likely reason is that the COM object is not registered in the registry of that machine (regasm was not run for the .NET assembly that implements the IDiscover).



回答4:

I have seen the error 0x80004002 E_NOINTERFACE if you expose a property of type DateTime on the com visible type you are trying to call CreateInstance() on. I've also noticed that you have to Rebuild the project that imports the tlb file instead of a Build if the tlb file changes for example.