We help IT Professionals succeed at work.

win32 log off user remotely

ossentoo asked
Medium Priority
Last Modified: 2007-12-19
Is there an API function that I could use to log off a workstation remotely (not shutdown or reboot)?  I've been using ExitWindowsEx and InitiateSystemShutdown, but the former doesn't allow remote control , and the latter doesn't have remote log off.

Watch Question

as far as i know you can do this only using WMI..
i give you an example i made some minutes ago for your problem.. unfortunatelly i did not finished it, i still have an error - but i don't have the time to dig and solve it.. i'll explain it at the end.. (sorry, but i really can't afford spending more time on it)

in order to compile it you need WMI SDK, obtainable at http://msdn.microsoft.com/downloads/default.asp?url=/downloads/sample.asp?url=/MSDN-FILES/027/001/552/msdncompositedoc.xml

for this task i made a simple com object, with a single method, defined as it follows:

      typedef [public] enum ActionEnum
            ActionLogoff = 0,
            ActionReboot = 2,
            ActionForceLogoff = 4,
            ActionForceReboot = 6,
            ActionPowerDown = 8,
            ActionForcePowerDown = 12,
      } ActionEnum;

            helpstring("IShutdown Interface"),
      interface IShutdown : IDispatch
            [id(1), helpstring("method Action")] HRESULT Action(BSTR bstrComputer, ActionEnum nAction);

and the method's code is:

STDMETHODIMP CShutdown::Action(BSTR bstrComputer, ActionEnum nAction)
      HRESULT hr;

    CComPtr<IWbemLocator> pLocator;
    CComPtr<IWbemServices> pServices;

      CComBSTR bstrPath = L"//";
      CComBSTR bstrObject = L"Win32_OperatingSystem";
      CComBSTR bstrMethod = L"Win32Shutdown";
      CComBSTR bstrLanguage = SysAllocString(L"WQL");
      CComBSTR bstrQuery = SysAllocString(L"select * from Win32_OperatingSystem where Primary=true");
      CComBSTR bstrFlags = L"Flags";
      CComBSTR bstrReserved = L"Reserved";

      //get the initial namespace of the CIM Object Manager
      hr = pLocator.CoCreateInstance(__uuidof(WbemLocator), 0, CLSCTX_INPROC_SERVER);
      if (FAILED(hr))
            return hr;

      //create an instance for the interface that connects WBEM services
      hr = pLocator->ConnectServer(bstrPath, NULL, NULL, NULL, 0, NULL, NULL, &pServices);
      if (FAILED(hr))
            return hr;

      //authenticate to the service, using current credentials
      if (FAILED(hr))
            return hr;

      //query WMI for objects: get the Win32_OperatingSystem class using WQL
      CComPtr<IEnumWbemClassObject> pEnumWbem;

      hr = pServices->ExecQuery(bstrLanguage, bstrQuery, WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumWbem);
      if (FAILED(hr))
            return hr;

      //for each returned object call Win32Shutdown
      IWbemClassObject* pWbemObject;
      DWORD nRetObjects;


      while (pEnumWbem->Next(WBEM_INFINITE, 1, &pWbemObject, &nRetObjects) == S_OK)
          CComPtr<IWbemClassObject> pClass;
            CComPtr<IWbemClassObject> pMethod;
            CComPtr<IWbemClassObject> pInParams;
            CComPtr<IWbemClassObject> pOutParams;

            //get the class definition of Win32_OperatingSystem
            hr = pServices->GetObject(bstrObject, 0, NULL, &pClass, NULL);
            if (FAILED(hr))
                  return hr;

            //get our method
            hr = pClass->GetMethod(bstrMethod, 0, &pMethod, NULL);
            if (FAILED(hr))
                  return hr;
            //create a new object for in parameters
            hr = pMethod->SpawnInstance(0, &pInParams);
            if (FAILED(hr))
                  return hr;

            //add parameters
            CComVariant var;
            V_VT(&var) = VT_I4;
            V_I4(&var) = (short)nAction;
            hr = pInParams->Put(bstrFlags, 0, &var, 0);
            if (FAILED(hr))
                  return hr;

            //call Win32Shutdown with our action
            hr = pServices->ExecMethod(bstrObject, bstrMethod, 0L, NULL, pInParams, NULL, NULL);


      return hr;

in visual basic it should work tested like if follows:

      dim s as new shutdown

the one error it still remains is that when calling
      hr = pServices->ExecMethod(bstrObject, bstrMethod, 0L, NULL, pInParams, NULL, NULL);
it returns with "Invalid method parameters", which means that either i did not construct the parameters as they should be in pInParams (i've tried also to add the "Reserved" parameter as sint32 = VT_I4 but still it didn't worked), or there is needed a pOutParams and set there the return value..
i don't know.. maybe you'll find out..

i hope that this helpes you, at least a little bit.. (and sorry again for not having a "complete and functional answer")


Thanks for your help.  I'll check it out.

Explore More ContentExplore courses, solutions, and other research materials related to this topic.