Friday, 20 May 2011

The specified service has been marked for deletion

While attempting to uninstall then reinstall a bespoke Windows service recently, I kept getting this error: "The specified service has been marked for deletion" (error 1072).

I'm running Windows 7, and normally the Services console can be open without affecting creation and deletion of services. But it wasn't even open anyway, yet something was still locking the service control manager.

I just couldn't figure this out...

Until I realized, some time later, that the Windows Update icon had been visible for a few days. I'd delayed installing the updates because I didn't want a reboot. So I installed them, rebooted the machine, and hey presto! I can once again uninstall and reinstall the service repeatedly without problems...

Saturday, 31 July 2010

Listing IIS 7 websites

Ever wanted to enumerate the websites on a Windows Vista/2008/7 machine running IIS 7.0 or 7.5? If so, here's how you can do it using C++...

#include <list>
#include <string>
#include <comdef.h>
#include <comutil.h>
#include <ahadmin.h>
#include <ahadmin_i.c>

bool ListIIS7Websites( std::list<std::string>& websites )
{
  ATL::CComPtr<IAppHostAdminManager> manager;
  if (FAILED( manager.CoCreateInstance( __uuidof( AppHostAdminManager ))))
    return false;

  ATL::CComPtr<IAppHostElement> section;
  if (FAILED( manager->GetAdminSection( _bstr_t( L"system.applicationHost/sites" ), _bstr_t( L"MACHINE/WEBROOT/APPHOST" ), &section )))
    return false;

  ATL::CComPtr<IAppHostElementCollection> coll;
  if (FAILED( section->get_Collection( &coll )))
    return false;

  DWORD count = 0;
  if (FAILED( coll->get_Count( &count )) || (count == 0))
    return false;

  for (DWORD i = 0; i < count; ++i)
  {
    _variant_t var;
    var.vt = VT_INT;
    var.intVal = i;
    ATL::CComPtr<IAppHostElement> elem;
    if (FAILED( coll->get_Item( var, &elem )))
      continue;

    ATL::CComPtr<IAppHostProperty> prop;
    if (FAILED( elem->GetPropertyByName( _bstr_t( L"name" ), ? )))
      continue;
    _variant_t varName;
    if (FAILED( prop->get_Value( &varName )) || (varName.vt != VT_BSTR))
      continue;

    websites.push_back( (const char*)_bstr_t( varName.bstrVal, true ));
  }

  return true;
}

Listing IIS 6 websites

Ever wanted to enumerate the websites on a Windows 2003 or XP machine running IIS 6.0 or 5.1? If so, here's how you can do it using C++...

#include <list>
#include <string>
#include <comdef.h>
#include <comutil.h>
#include <activeds.h>
#pragma comment( lib, "activeds.lib" )
#include <adshlp.h>
#pragma comment( lib, "adsiid.lib" )

bool ListIIS6Websites( std::list<std::string>& websites ) const
{
  ATL::CComPtr<IADsContainer> pWebserver;
  if (FAILED( ::ADsGetObject( L"IIS://localhost/w3svc", IID_IADsContainer, (void**)&pWebserver )))
    return false;

  IEnumVARIANT* pEnum = NULL;
  if (FAILED( ::ADsBuildEnumerator( pWebserver, &pEnum )))
    return false;

  while (true)
  {
    _variant_t var;
    ULONG count = 0;
    if (FAILED( ::ADsEnumerateNext( pEnum, 1, &var, &count )) || (count == 0))
      break; //no more websites

    ATL::CComPtr<IADs> item;
    if (FAILED( V_DISPATCH(&var)->QueryInterface( IID_IADs, (void**)&item )))
      continue;

    BSTR bstrClass = NULL;
    if (FAILED( item->get_Class( &bstrClass )))
      continue;
    std::string strClass = (const char*)_bstr_t( bstrClass );
    if (strClass != "IIsWebServer")
      continue; //this isn't a website

    _variant_t comment;
    if (FAILED( item->Get( _bstr_t( L"ServerComment" ), &comment )))
      continue;

    websites.push_back( (const char*)_bstr_t( comment.bstrVal, true ));
  }

  ::ADsFreeEnumerator( pEnum );

  return true;
}