We help IT Professionals succeed at work.

win32 log off user remotely

ossentoo
ossentoo asked
on
Medium Priority
515 Views
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.

Thanks
Comment
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;

      [
            object,
            uuid(11D28172-9D56-41F3-8C8F-3944D8510086),
            dual,
            helpstring("IShutdown Interface"),
            pointer_default(unique)
      ]
      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"//";
      bstrPath.AppendBSTR(bstrComputer);
      bstrPath.Append(L"/root/cimv2");
      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
      hr = CoSetProxyBlanket(pServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
      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;

       pEnumWbem->Reset();

      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))
            {
                  pWbemObject->Release();
                  return hr;
            }

            //get our method
            hr = pClass->GetMethod(bstrMethod, 0, &pMethod, NULL);
            if (FAILED(hr))
            {
                  pWbemObject->Release();
                  return hr;
            }
      
            //create a new object for in parameters
            hr = pMethod->SpawnInstance(0, &pInParams);
            if (FAILED(hr))
            {
                  pWbemObject->Release();
                  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))
            {
                  pWbemObject->Release();
                  return hr;
            }

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

            pWbemObject->Release();
      }

      return hr;
}

in visual basic it should work tested like if follows:

      dim s as new shutdown
      s.action(ActionLogoff)

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")

Author

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

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