Why I have WMI Class but no instance? - wmi

I am following Microsoft guide
on how to setup my own WMI provider.
After registering my provider with Register-CimProvider.exe I can see the class:
Get-CimClass -Namespace root/StandardCimv2/sample -ClassName MSFT_WindowsProcess
NameSpace: ROOT/StandardCimv2/sample
CimClassName CimClassMethods CimClassProperties
------------ --------------- ------------------
MSFT_WindowsProcess {RequestStateChan... {Caption, Description, ElementName, InstanceID...}
However, there is no instance of this class as the next command fails:
Get-CimInstance -ClassName MSFT_WindowsProcess -Namespace root/StandardCimv2/sample
Get-CimInstance : Provider load failure
At line:1 char:1
+ Get-CimInstance -ClassName MSFT_WindowsProcess -Namespace root/Standa ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (root/StandardCi..._WindowsProcess:String) [Get-CimInstance], CimException
+ FullyQualifiedErrorId : HRESULT 0x80041013,Microsoft.Management.Infrastructure.CimCmdlets.GetCimInstanceCommand
This is my mof:
#pragma include ("cim_schema_2.26.0.mof")
#pragma include ("MSFT_Qualifiers.mof")
// MSFT_WindowsProcess class derives from CIM_Process class,
// which defines the schema for the processes running on windows OS.
[ClassVersion("1.0.0")]
class MSFT_WindowsProcess : CIM_Process
{
string CommandLine;
[Description("This instance method demonstrates modifying the "
"priority of a given process."
"The method returns an integer value of 0 if the "
"operation was successfully completed,"
"and any other number to indicate an win32 error code.")]
uint32 SetPriority([In] uint32 Priority);
[static,
Description("This static method demonstrates creating a process "
"by supplying commandline to start a new process."
"It will output the reference to the newly created process."
"The method returns an integer value of 0 if the process "
"was successfully created, and any other number to "
"indicate an win32 error code.")]
uint32 Create([In] string CommandLine, [Out] CIM_Process ref Process);
};
I followed every other step in the guide.
What I need to do to create an instance of the class?

Related

Attaching debugger give me the credentials, removing it and the credentials are empty

I have a problem with the AWS sdk on a Qt app.
I'm getting the STS tokens from Cognito after a click on a QML button.
The function is working perfectly fine and is printing me the token... as long as the debugger is attached [F5]. If I start the project without debugger (green arrow without bug on it) the returned object is empty.
Without the debugger attached I have the following in the aws logs that I don't have otherwise:
[INFO] 2020-09-18 12:33:02.569 CognitoCachingCredentialsProvider [140678610167936] A parent identity was from cognito which is different from the anonymous identity. Swapping that out now.
[INFO] 2020-09-18 12:33:02.569 CognitoCachingCredentialsProvider [140678610167936] Credentials will expire next at 0
Other logs around looks the same, I even have the STS token shown a couples of lines above this one on both cases:
[DEBUG] 2020-09-18 12:33:02.569 CURL [140678610167936] (DataIn) {"Credentials":{"AccessKeyId":"###","Expiration":1.600435982E9,"SecretKey":"###","SessionToken":"##########"},"IdentityId":"<MY_IDENTITY_ID>"}
I have even edited the SDK and added the following logs which resulted in this (with the debugger attached the first line is also getting <MY_IDENTITY_ID> shown).
AWS_LOGSTREAM_INFO("TOTO", "parentIdentityId" << parentIdentityId);
AWS_LOGSTREAM_INFO("TOTO", "m_identityRepository->GetIdentityId() " << m_identityRepository->GetIdentityId()) ;
[INFO] 2020-09-18 12:33:02.569 TOTO [140678610167936] parentIdentityId
[INFO] 2020-09-18 12:33:02.569 TOTO [140678610167936] m_identityRepository->GetIdentityId() <MY_IDENTITY_ID>
Added here https://github.com/aws/aws-sdk-cpp/blob/6d6dcdbfa377393306bf79585f61baea524ac124/aws-cpp-sdk-identity-management/source/auth/CognitoCachingCredentialsProvider.cpp#L52
No commenting the line 56 does not fix my problem.
Attached is my minimal project to reproduce the behavior if you want (You will need to have an AWS setup and an openID provider).
I tried on pure C++ and I get everything even without debugger.
The problem arises when instantiating the QtCoreApplication.
On the base app I tried setting a QTimer::singleShot(100, /*...*/) and I still got the problem.
You can install the aws SDK from here https://github.com/aws/aws-sdk-cpp and if you don't want to install the whole SDK, the project only need a little part of the sdk so add -DBUILD_ONLY="identity-management" to cmake to only build the needed part.
Qt 5.12.5
aws-sdk-cpp on tag: 1.8.42 (Had the same problem from previous patch version and the latest change very often)
Question
What magic attaching the debugger do to allow an application that instanciated a QCoreApplication getting tokens from the aws sdk ?
I am saying it again here: I do not have a DEBUG and a RELEASE build, I just use the arrow vs arrow with a bug on it in qtcreator. As far as I know the environment is the same, just qtcreator attach or not the debugger.
Indeed in release I have the same problem (STS shown when the debugger is attached, empty when not).
Minimal working example
main.cpp (The commented code should do the same as credentials = cognitoAuth.GetAWSCredentials();, and so I have the same behaviour.)
#include <QCoreApplication>
#include <QDebug>
#include <QFile>
#include <aws/cognito-identity/model/GetCredentialsForIdentityRequest.h>
#include <aws/cognito-identity/model/GetIdRequest.h>
#include <aws/core/Aws.h>
#include <aws/identity-management/auth/CognitoCachingCredentialsProvider.h>
#include <aws/identity-management/auth/PersistentCognitoIdentityProvider.h>
Aws::String m_region = Aws::Region::<PICK_YOUR_REGION>;
Aws::String m_providerUrl = "<PROVIDER_URL>";
Aws::String m_accountId = "<ACCOUNT_ID>";
Aws::String m_identityPoolId = "<IDENTITY_POOL_ID>";
Aws::Auth::AWSCredentials getSTS(const std::string idToken) {
const char *persistentFile = "/tmp/aws.identities";
QFile::remove(persistentFile);
Aws::Auth::AWSCredentials credentials;
// Aws::CognitoIdentity::Model::Credentials credentials;
std::shared_ptr<Aws::CognitoIdentity::CognitoIdentityClient> cognitoClient;
Aws::SDKOptions options;
options.loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Trace;
Aws::InitAPI(options);
{
Aws::Client::ClientConfiguration config;
config.region = m_region;
cognitoClient =
std::make_shared<Aws::CognitoIdentity::CognitoIdentityClient>(config);
std::shared_ptr<Aws::Auth::PersistentCognitoIdentityProvider_JsonFileImpl>
identityProvider = std::make_shared<
Aws::Auth::PersistentCognitoIdentityProvider_JsonFileImpl>(
m_identityPoolId, m_accountId, persistentFile);
Aws::Map<Aws::String, Aws::Auth::LoginAccessTokens> logins;
Aws::Auth::LoginAccessTokens loginAccessTokens;
loginAccessTokens.accessToken = idToken;
logins[m_providerUrl] = loginAccessTokens;
identityProvider->PersistLogins(logins);
// QThread::sleep(5);
Aws::Auth::CognitoCachingAuthenticatedCredentialsProvider cognitoAuth{
identityProvider, cognitoClient};
///////////////////////////////////////////////////////////////////////////
// Aws::CognitoIdentity::Model::GetIdRequest idRequest;
// idRequest.SetIdentityPoolId(m_identityPoolId.c_str());
// idRequest.AddLogins(m_providerUrl, idToken.c_str());
////idRequest.SetIdentityPoolId((region + ":" + identityPoolId).c_str());
//
// auto idResult = cognitoClient->GetId(idRequest);
// if(!idResult.IsSuccess())
//{
// qCWarning(mqttAwsWebsocket) << "(GetId): " <<
// idResult.GetError().GetExceptionName().c_str() << ":"
// <<
// idResult.GetError().GetMessage().c_str();
// // throw
//}
//
// QThread::sleep(5);
//
// Aws::CognitoIdentity::Model::GetCredentialsForIdentityRequest
// credForIdRequest;
// credForIdRequest.SetIdentityId(idResult.GetResult().GetIdentityId());
// credForIdRequest.AddLogins(m_providerUrl, idToken.c_str());
//
// auto credForIdResult =
// cognitoClient->GetCredentialsForIdentity(credForIdRequest);
// if(!idResult.IsSuccess())
//{
// qCWarning(mqttAwsWebsocket) << "(GetCredentialsForIdentity): "
// <<
// credForIdResult.GetError().GetExceptionName().c_str()
// << ":"
// <<
// credForIdResult.GetError().GetMessage().c_str();
// // throw
//}
//
// qDebug() << "COGNITO STS TOKEN RESULTS";
// qDebug() << "cognitoClient->GetId: " << idResult.IsSuccess();
// qDebug() << "cognitoClient->GetCredentialsForIdentity: " <<
// credForIdResult.IsSuccess(); credentials =
// credForIdResult.GetResult().GetCredentials();
///////////////////////////////////////////////////////////////////////////
// QThread::sleep(5);
credentials = cognitoAuth.GetAWSCredentials();
qDebug() << credentials.IsEmpty() << tries;
qDebug() << credentials.GetAWSAccessKeyId().c_str();
qDebug() << credentials.GetAWSSecretKey().c_str();
qDebug() << credentials.GetSessionToken().c_str();
qDebug() << credentials.IsExpired()
<< credentials.GetExpiration()
.ToLocalTimeString(Aws::Utils::DateFormat::RFC822)
.c_str();
}
Aws::ShutdownAPI(options);
return credentials;
}
int main(int argc, char **argv) {
// Comment just this line and the problem is fixed.
QCoreApplication app(argc, argv);
getSTS("<PAST_OPEN_ID_TOKEN_GOTTEN_FROM_REAL_APP>");
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(aws-sts LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt5 COMPONENTS Core)
set(BUILD_SHARED_LIBS ON)
find_package(AWSSDK REQUIRED COMPONENTS identity-management)
add_executable(aws-sts main.cpp)
target_link_libraries(aws-sts PRIVATE
Qt5::Core
${AWSSDK_LINK_LIBRARIES}
)
Update
I simplified the minimal working example since in fact just adding (or commenting ot) QCoreApplication app(argc, argv); is sufficient to reproduce the behavior. I mean just the object creation, no need for it to be a QGuiApplication or start the event loop with app.exec().
It turns out that the aws sdk is using cJSON which, when parsing numbers, may or may not get the local environment for decoding decimal point. But in both cases it will call double strtod(const char *nptr, char **endptr); to translate string to double, in the man page we can read (emphasis mine)
A decimal number consists of a nonempty sequence of decimal digits possibly containing a radix character (decimal point, locale-dependent, usually '.'), optionally followed by a decimal exponent. [...]
Apparently cJSON need this compilation variable to compile on Android.
AWS copied the lib here but did not copied the compilation variable ENABLE_LOCALES which should be enabled by default as stated in the issue linked above.
I am on Ubuntu 18.04, environment in English but dates/number in French (decimal point is ',' here in France).
I am creating an issue on the AWS SDK repo to set the compilation variable ENABLE_LOCALES and on cJSON to discuss and avoid further error like this one.
A potential fix could also be to force the application to use English locales but that is not always possible.

Error: any_cast<T>(any&&) broken on Windows but works in Linux

First of all, I'm a C++ novice so be gentle. In my cross-platform project I've run into an issue I can't sort out using VS Studio 2019 via the nar builder in Maven. The build works a-ok on Linux, but on Windows 10 x64 the build fails here:
[ERROR] OUTPUT>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\include\any(429): error C2338: any_cast<T>(any&&) requires T to be constructible from remove_cv_t<remove_reference_t<T>>
[INFO] OUTPUT>c++/SRTServer.cpp(188): note: see reference to function template instantiation '_Ty &std::any_cast<std::shared_ptr<NetworkConnection>&>(std::any &&)' being compiled
[INFO] OUTPUT> with
[INFO] OUTPUT> [
[INFO] OUTPUT> _Ty=std::shared_ptr<NetworkConnection> &
[INFO] OUTPUT> ]
The NetworkConnection is in an included h file and consists of
class NetworkConnection {
public:
NetworkConnection();
virtual ~NetworkConnection();
std::any object;
uint16_t connectorId;
};
Lines 183-193 of SRTServer.cpp
void gotData(ElasticFrameProtocol::pFramePtr &rPacket) {
std::cout << "Got NAL-units of size " << unsigned(rPacket->mFrameSize) <<
" pts " << unsigned(rPacket->mPts) << " is broken? " << rPacket->mBroken <<
" from EFP connection " << unsigned(rPacket->mSource) << std::endl;
// TODO the NetworkConnection must be looked up to get the server id and client id
auto nc = std::any_cast<std::shared_ptr<NetworkConnection> &>(rPacket->mSource); // the source being a NetworkConnection is a guess right now
// get the client from the network connection
auto client = std::any_cast<std::shared_ptr<Client> &>(nc->object);
// call the receive method
recvData(rPacket->pFrameData, rPacket->mFrameSize, client->serverId, client->connectorId, rPacket->mStream);
}
As mentioned in the comments the casting of mSource (uint8_t) to a NetworkConnection (Class) will fail. And as you say -> // the source being a NetworkConnection is a guess right now.
There is probably another part of the code where you should do the casting. If more code is provided then we can help.
/Anders

How to access SetThreadDescription() in Windows 2016 Server, Version 1607

If I just call SetThreadDescription() from WinAPI, it works on Windows 10, Version 2004. However, on Windows 2016 Server, 1607 it produces the following message box:
The procedure entry point SetThreadDescription could not be located in the dynamic link library
and the path to my executable program follows in the message.
According to this article:
SetThreadDescription is only available by Run Time Dynamic Linking on
Windows Server 2016, 1607.
So I tried dynamic linking as follows:
typedef HRESULT (WINAPI *TSetThreadDescription)(HANDLE, PCWSTR);
namespace {
TSetThreadDescription gpSetThreadDescription = nullptr;
}
void Initialize() {
HMODULE hKernel32 = GetModuleHandleA("Kernel32.dll");
if (hKernel32 == nullptr) {
cerr << "FATAL: failed to get kernel32.dll module handle, error: " << GetLastError() << endl;
quick_exit(5);
}
gpSetThreadDescription = reinterpret_cast<TSetThreadDescription>(
GetProcAddress(hKernel32, "SetThreadDescription"));
if (gpSetThreadDescription == nullptr) {
cerr << "FATAL: failed to get SetThreadDescription() address, error: " << GetLastError() << endl;
quick_exit(6);
}
}
This code also works on Windows 10. However, I'm getting error 127 ("The specified procedure could not be found") on Windows Server 2016.
What am I doing wrong about the run-time dynamic linking?
Apparently, despite MSDN says "DLL: Kernel32.dll", the function is actually in KernelBase.DLL, so I've fixed the problem after changing to:
HMODULE hKernelBase = GetModuleHandleA("KernelBase.dll");

Wt a.exe file won't run

I am trying to start developing in WT, but it's not working out. I am using Windows 8, downloaded Wt 3.3.1, and had downloaded the codeblocks-12.11mingw-setup_user.exe which has the GCC compiler and GDB debugger. But I am not using code blocks, because the compiler didn't like the cmake preproccessor directives in WtConfig.h. So I tried to compile manually (I am a newb at using this type of technique, so I had to look it up).
I have my project as:
└───HelloWorldWt
└───source
├───bin
│ ├───Debug
│ │ └───CMakeFiles
│ │ └───CMakeFiles
│ └───Release
├───build
└───source
| └───CMakeFiles
| └───wt_project.wt.dir
| |___CMakeLists.txt
| |
| |___main.cpp
|____CMakeLists.txt
The main.cpp has (this is the HelloWorld example from http://www.webtoolkit.eu/wt/examples/):
/*
* Copyright (C) 2008 Emweb bvba, Heverlee, Belgium.
*
* See the LICENSE file for terms of use.
*/
#include <Wt/WApplication>
#include <Wt/WBreak>
#include <Wt/WContainerWidget>
#include <Wt/WLineEdit>
#include <Wt/WPushButton>
#include <Wt/WText>
// c++0x only, for std::bind
// #include <functional>
using namespace Wt;
/*
* A simple hello world application class which demonstrates how to react
* to events, read input, and give feed-back.
*/
class HelloApplication : public WApplication
{
public:
HelloApplication(const WEnvironment& env);
private:
WLineEdit *nameEdit_;
WText *greeting_;
void greet();
};
/*
* The env argument contains information about the new session, and
* the initial request. It must be passed to the WApplication
* constructor so it is typically also an argument for your custom
* application constructor.
*/
HelloApplication::HelloApplication(const WEnvironment& env)
: WApplication(env)
{
setTitle("Hello world"); // application title
root()->addWidget(new WText("Your name, please ? ")); // show some text
nameEdit_ = new WLineEdit(root()); // allow text input
nameEdit_->setFocus(); // give focus
WPushButton *button
= new WPushButton("Greet me.", root()); // create a button
button->setMargin(5, Left); // add 5 pixels margin
root()->addWidget(new WBreak()); // insert a line break
greeting_ = new WText(root()); // empty text
/*
* Connect signals with slots
*
* - simple Wt-way
*/
button->clicked().connect(this, &HelloApplication::greet);
/*
* - using an arbitrary function object (binding values with boost::bind())
*/
nameEdit_->enterPressed().connect
(boost::bind(&HelloApplication::greet, this));
/*
* - using a c++0x lambda:
*/
// b->clicked().connect(std::bind([=]() {
// greeting_->setText("Hello there, " + nameEdit_->text());
// }));
}
void HelloApplication::greet()
{
/*
* Update the text, using text input into the nameEdit_ field.
*/
greeting_->setText("Hello there, " + nameEdit_->text());
}
WApplication *createApplication(const WEnvironment& env)
{
/*
* You could read information from the environment to decide whether
* the user has permission to start a new application
*/
return new HelloApplication(env);
}
int main(int argc, char **argv)
{
/*
* Your main method may set up some shared resources, but should then
* start the server application (FastCGI or httpd) that starts listening
* for requests, and handles all of the application life cycles.
*
* The last argument to WRun specifies the function that will instantiate
* new application objects. That function is executed when a new user surfs
* to the Wt application, and after the library has negotiated browser
* support. The function should return a newly instantiated application
* object.
*/
int retval = WRun(argc, argv, &createApplication);
char* ch = new ch();
cin() >> ch;
return retval;
}
The HelloWorldWt/CMakeLists.txt has:
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
PROJECT(WT_HELLO_WORLD)
SET (WT_CONNECTOR "wtfcgi" CACHE STRING "Connector used (wthttp or wtfcgi)")
ADD_SUBDIRECTORY(source)
The HelloWorldWt/source/CMakeLists.txt has
SET(WT_PROJECT_SOURCE
main.cpp
)
SET(WT_PROJECT_TARGET wt_project.wt)
ADD_EXECUTABLE(${WT_PROJECT_TARGET} ${WT_PROJECT_SOURCE})
TARGET_LINK_LIBRARIES(${WT_PROJECT_TARGET} ${WT_CONNECTOR} wt)
INCLUDE_DIRECTORIES("C:/Users/Me/My Code Libraries/wt-3.3.1/src")
I then ran
cmake .. -G "MinGW Makefiles" from the MyCode directory
That created a few files,
this created cmake_install.cmake, among other files.
I then ran: cmake .. -G "MinGW Makefiles" from HelloWorldWt/source
then I ran: cmake -P cmake_install.cmake
I then had:
My Code\HelloWorldWt\source\build\CMakeFiles\2.8.12\CompilerIdCXX\a.exe file, and I clicked that program to run it, and a console window just opened then closed.
what am I missing here?, I am trying to get a Wt application running, but can't seem to do it yet
(Maybe I should note that when I use the command:
cmake -P cmake_install.cmake
the cmd console, replies with
-- Install configuration: ""
and then goes back to the prompt. - If that helps).
My Code\HelloWorldWt\source\build\CMakeFiles\2.8.12\CompilerIdCXX\a.exe
Is not the file you want to run. It is an internal CMake test cmake creates during configuration to verify that the selected compiler even compiles and detect the target architecture.
You executable will be called
My Code\HelloWorldWt\source\build\wt_project.wt.exe
when you actually compile it.
To compile it, you either call make, or other appropriate build command depending on the selected generator, or you can ask cmake to call it for you with the command:
cmake --build .
The code you pasted contains syntax error—
cin() >> ch;
should be
std::cin >> ch;
(and ch should be a char, not char *)—which confirms you didn't yet try to compile it.
I should add that brief look at the WT documentation suggests the resulting executable should also need a bunch of options before it does anything interesting too.
We are using g++ since its a c++ interface (opposed to gcc), and scons as the build model. This works well and was pretty simple to deploy. I would suggest trying the next Ubuntu 14.04 release as it will contain a stable Wt version in its packages.

Meaning of a numerical ErrorMessage

I am trying to interface with an OEM library. Everything worked on one computer but I am getting lots of problems on another computer.
I the code is throwing a COM exception but I can't figure out the meaning of a error code that doesn't have a ErrorMessage();
The code
#include "stdafx.h"
#include <afx.h>
#include <iostream>
using namespace std;
#import "MTBApi.tlb" named_guids //raw_interfaces_only
using namespace MTBApi;
void DisplayError(_com_error* e)
{
CString message;
// if it is an application error thrown by .NET
if (e->Error() >= 0x80041000)
{
IErrorInfo* info;
BSTR msg;
info = e->ErrorInfo();
info->GetDescription(&msg);
info->Release();
message = CString(msg);
}
// other com errors
else
{
message = e->ErrorMessage();
}
cout << "MTB Error: " << message <<":"<<(unsigned int) e->Error()<< endl;
}
int main(int argc, char **argv)
{
for (int i = 0 ; i < 4 ; i++)
{
IMTBConnectionPtr m_MTBConnection;
try
{
cout <<"1" << endl;
HRESULT a = CoInitializeEx(NULL,COINIT_SPEED_OVER_MEMORY);
cout <<"2" << endl;
m_MTBConnection = IMTBConnectionPtr(CLSID_MTBConnection);
cout <<"3" << endl;
m_MTBConnection->Close();
cout <<"4" << endl;
CoUninitialize();
cout <<"5" << endl;
}
catch(_com_error e)
{
DisplayError(&e);
}
cout << endl;
}
}
The runtime output
1
2
MTB Error: 00000000002205F8:2147746132
1
2
MTB Error: 00000000002205F8:2147746132
1
2
MTB Error: 00000000002205F8:2147746132
1
2
MTB Error: 00000000002205F8:2147746132
Rather Verbose Output from Dependency Walker
http://pastebin.com/7Y33z3Pj
cout << "MTB Error: " << message <<":"<<(unsigned int) e->Error()<< endl;
cout isn't very good at displaying Unicode strings, it merely displays the string pointer value. Not useful of course, use wcout instead. And favor displaying the error code in hex. 0x80040154 is a very common COM error, "Class not registered". Thousands of questions about it already, you just need to get the COM server registered properly. Ask the vendor or author if you don't know how to do that.
00000000002205F8 looks like a memory pointer. You are passing a CString to cout, which only accepts char* or std::string for string values. Maybe the CString contains a Unicode string that is not being converted to Ansi correctly. Also, when calling IErrorInfo::GetDescription(), you are leaking the returned BSTR. You need to free it with SysFreeString() when you are done using it.
Error code 2147746132 (hex 0x80040154) is Severity=FAIL, Facility=FACILITY_ITF, Code=340. FACILITY_ITF typically means the error code is a custom error code defined by the interface that failed. But in this case, 0x80040154 is also a standard error code: REGDB_E_CLASSNOTREG.
If your problem is to rectify the error which you are getting then
then issue is as #Remy pointed out , your com assembly is not registered in the machine you are currently executing your program rather in the other machine it got registered. Register the assembly (for eg COMAssembly.dll which is in C:\ drive) by running the following command in command prompt.
regsvr32 c:\COMAssembly.dll
if its a C++ com assembly , if its a C# assembly register it by using command
regasm c:\COMAssembly.dll
(where regasm can be run in a VS command prompt , otherwise if you are running in normal command prompt then you have to first call vsvars32.bat then call regasm)