Detect a crashed COM+ app via PowerShell ?

Duncan 51 Reputation points
2021-04-15T11:28:27.177+00:00

As far as I know you can recycle a COM+ app by using...

List COM+ components

$comAdmin = New-Object -com ("COMAdmin.COMAdminCatalog.1")
$applications = $comAdmin.GetCollection("Applications")
$applications.Populate()

foreach ($application in $applications)
{

$components = $applications.GetCollection("Components",$application.key)
$components.Populate()
foreach ($component in $components)
{

    $dllName = $component.Value("DLL")
    $componentName = $component.Name

    "Component Name:$componentName"
    "DllName: $dllName`n"
}

}

Stop/Start Components

$comAdmin.StartApplication("appName")
$comAdmin.ShutdownApplication("appName")

But how can we detect that our COM+ app has crashed - can this be detected by a PowerShell script?

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,422 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Song Zhu - MSFT 906 Reputation points
    2021-04-16T07:49:54.98+00:00

    As far as I know, PowerShell is not able to detect whether the application crashed. You can use WMI to detect it.

    Here is a code sample:

    #define CREATE 1  
    #define DELETE 0  
      
    using namespace std;  
      
    typedef function<void(void)> TNotificationFunc;  
    IWbemObjectSink* RegisterProcessCallback(IWbemServices* pSvc, TNotificationFunc callback, LPCWSTR ProcessName, BOOL flag);  
      
      
    class EventSink : public IWbemObjectSink {  
      
        friend IWbemObjectSink* RegisterProcessCallback(IWbemServices* pSvc, TNotificationFunc callback, LPCWSTR ProcessName, BOOL flag);  
        CComPtr<IWbemServices> pSvc;  
        CComPtr<IWbemObjectSink> pStubSink;  
        LONG m_IRef;  
        TNotificationFunc m_callback;  
      
    public:  
        EventSink(TNotificationFunc callback) :m_IRef(0), m_callback(callback) {}  
        ~EventSink() {  
        }  
      
        virtual ULONG STDMETHODCALLTYPE AddRef() {  
            return InterlockedIncrement(&m_IRef);  
        }  
      
        virtual ULONG STDMETHODCALLTYPE Release() {  
            LONG IRef = InterlockedDecrement(&m_IRef);  
            if (IRef == 0)  
                delete this;  
            return IRef;  
        }  
      
        virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv) {  
            if (riid == IID_IUnknown || riid == IID_IWbemObjectSink) {  
                *ppv = (IWbemObjectSink*)this;  
                AddRef();  
                return WBEM_S_NO_ERROR;  
            }  
            else return E_NOINTERFACE;  
        }  
      
        virtual HRESULT STDMETHODCALLTYPE Indicate(  
            LONG lObjectCount,  
            IWbemClassObject __RPC_FAR* __RPC_FAR* apObjArray  
        ) {  
            for (int i = 0; i < lObjectCount; i++)  
            {  
                m_callback();  
                _variant_t vtProp;  
                HRESULT hr = S_OK;  
                hr = apObjArray[i]->Get(_bstr_t(L"TargetInstance"), 0, &vtProp, 0, 0);  
                if (!FAILED(hr))  
                {  
                    IUnknown* str = vtProp;  
                    hr = str->QueryInterface(IID_IWbemClassObject, reinterpret_cast<void**>(&apObjArray[i]));  
                    if (SUCCEEDED(hr))  
                    {  
                        _variant_t cn;  
                        hr = apObjArray[i]->Get(L"Handle", 0, &cn, NULL, NULL);  
                        if (SUCCEEDED(hr))  
                        {  
                            if ((cn.vt == VT_NULL) || (cn.vt == VT_EMPTY))  
                                wcout << "ProcessId : " << ((cn.vt == VT_NULL) ? "NULL" : "EMPTY") << endl;  
                            else  
                                wcout << "ProcessId : " << cn.bstrVal << endl;  
                        }  
                        VariantClear(&cn);  
                    }  
                }  
                VariantClear(&vtProp);  
            }  
            return WBEM_S_NO_ERROR;  
        }  
        virtual HRESULT STDMETHODCALLTYPE SetStatus(LONG IFlags, HRESULT hResult, BSTR strParam, IWbemClassObject __RPC_FAR* pObjParam) {  
            return WBEM_S_NO_ERROR;  
        }  
    };  
    void connect2WMI(IWbemServices** pSvc)  
    {  
        HRESULT hres;  
        CComPtr<IWbemLocator> pLoc;  
      
        hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);  
        if (FAILED(hres)) {  
            cout << "Failed to create IWbemLocator object."  
                << " Err code = 0x"  
                << hex << hres << endl;  
            throw std::exception("CreationEvent initialization failed");  
        }  
        hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, pSvc);  
        if (FAILED(hres)) {  
            cout << "Could not connect. Error code = 0x" << hex << hres << endl;  
            throw std::exception("CreationEvent initialization failed");  
        }  
        hres = CoSetProxyBlanket(*pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);  
        if (FAILED(hres)) {  
            cout << "Coult not set proxy blanket, Error code =0x" << hex << hres << endl;  
            throw std::exception("CreationEvent initialization failed");  
        }  
    }  
    IWbemObjectSink* RegisterProcessCallback(IWbemServices* pSvc, TNotificationFunc callback, LPCWSTR ProcessName, BOOL flag) {  
        HRESULT hres;  
        CComPtr<EventSink> pSink(new EventSink(callback));  
        CComPtr<IUnsecuredApartment> pUnsecApp;  
        hres = CoCreateInstance(CLSID_UnsecuredApartment, NULL, CLSCTX_LOCAL_SERVER, IID_IUnsecuredApartment, (void**)&pUnsecApp);  
        CComPtr<IUnknown> pStubUnk;  
        pUnsecApp->CreateObjectStub(pSink, &pStubUnk);  
        IWbemObjectSink* pStubSink = NULL;  
        pStubUnk->QueryInterface(IID_IWbemObjectSink, (void**)&pStubSink);  
      
      
        wstring buffer = L"SELECT * FROM ";  
        if (flag == CREATE)  
            buffer += L"__InstanceCreationEvent";  
        else if (flag == DELETE)  
            buffer += L"__InstanceDeletionEvent";  
        buffer = buffer + L" WITHIN 1 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.Name = '" + ProcessName + L"'";  
        hres = pSvc->ExecNotificationQueryAsync(_bstr_t(L"WQL"), _bstr_t(buffer.c_str()), WBEM_FLAG_SEND_STATUS, NULL, pStubSink);  
      
        if (FAILED(hres)) {  
            cout << "ExecNotificationQueryAsync failed with = 0x" << hex << hres << endl;  
            throw std::exception("CreationEvent initialization failed");  
        }  
        return pStubSink;  
    }  
      
    void CreateEventCallBack() { cout << "Create " << endl; /*connect()*/ }  
    void DeleteEventCallBack() { cout << "Delete " << endl; /*disconnect()*/ }  
      
    int main() {  
        CoInitializeEx(0, COINIT_MULTITHREADED);  
        IWbemServices* pSvc = NULL;  
        connect2WMI(&pSvc);  
        IWbemObjectSink* CreateSink = RegisterProcessCallback(pSvc, CreateEventCallBack, L"notepad.exe", CREATE);  
        IWbemObjectSink* DeleleSink = RegisterProcessCallback(pSvc, DeleteEventCallBack, L"notepad.exe", DELETE);  
      
        getchar();  
        cout << "Exit " << endl;  
        pSvc->CancelAsyncCall(CreateSink);  
        pSvc->CancelAsyncCall(DeleleSink);  
        CreateSink->Release();  
        DeleleSink->Release();  
        pSvc->Release();  
        CoUninitialize();  
    }  
    
    0 comments No comments