Python 2.7, WMI Unexpected COM Error -2147352567 Non-domain system connecting to domain system

monitoringpythonwindowswmi

I'm new to using WMI; trying to write an app that connects to remote systems through WMI. I need this app to watch for user logins, when users logoff, and users going idle. On the logon, to end a process that the app starts on the system. On the logoff or idle, I'd like it to restart the service. This way I'm hoping to maximize use of the machine, while not impacting users.

I have the following code, mostly attempting to use Python WMI v1.4.9:

import wmi
import os
import threading
import getpass

class Application():
def __init__(self):
    self.getCredentials(self)
    self.getHostnames(self)
    self.makeConnection(self)
    self.runProgram(self)

def makeConnection(self, parent):
    parent.server = parent.hostlist.pop()
    print "makeConnection"
    parent.wmiConnection = wmi.WMI(parent.server, user=parent.username, password=parent.password)
    #For proof of concept, I'm settling for a single system for now.  I can write the threading later.

def runProgram(self,parent):
    print "runProgram"
    parent.wmiConnection.Win32_Process.Create(CommandLine="cmd")

def getCredentials(self, parent):
    parent.domain = raw_input('Domain: ')
    parent.username = raw_input('Username: ')
    parent.password = getpass.getpass(stream=None)

def getHostnames(self, parent):
    if os.path.exists("hosts.txt"):
        parent.hostslistfile = open("hosts.txt", "r")
        parent.hostlist = parent.hostslistfile.readlines()
        parent.hostslistfile.close()

if __name__ == "__main__":
app = Application()

I'm stuck attempting to pass credentials to the makeConnection(). I know the server accepts WMI queries, because I can run makeConnection() without specifying user= and password= from a system connected to the domain; the resulting connection is successful. I try to pass user as domain\user and am unable to find documentation for how to do this more properly.

The actual error I receive is as follows:

Traceback (most recent call last):
  File "C:\Users\Urist\Dropbox\code\foreman.py", line 35, in <module>
    app = Application()
  File "C:\Users\Urist\Dropbox\code\foreman.py", line 10, in __init__
    self.makeConnection(self)
  File "C:\Users\Urist\Dropbox\code\foreman.py", line 15, in makeConnection
    parent.wmiConnection = wmi.WMI(parent.server, user=parent.username, password
=parent.password)
  File "C:\Python27\lib\site-packages\wmi.py", line 1290, in connect
    handle_com_error ()
  File "C:\Python27\lib\site-packages\wmi.py", line 241, in handle_com_error
    raise klass (com_error=err)
wmi.x_wmi: <x_wmi: Unexpected COM Error (-2147352567, 'Exception occurred.', (0,
  u'SWbemLocator', u'The RPC server is unavailable. ', None, 0, -2147023174), Non
e)>

There appears to be a typo in the WMI cookbook. However, using a reference in the beginning WMI tutorial, I can successfully create a remote connection by doing:

connection = wmi.WMI("HOSTNAME", user=r"domain\user", password="password")

I have since then modified the makeConnection() module to the following:

def makeConnection(self, parent):
    parent.passedUsername = "r\"" + parent.username + "\""
    parent.server = parent.hostlist.pop()
    #print parent.server, parent.passedUsername
    parent.wmiConnection = wmi.WMI(parent.server, user=parent.passedUsername, password=parent.password)

Unfortunately, this does not work and still returns the original error despite parent.passedUsername being accurate.

Best Answer

It wasn't actually the credentials that were causing the error. Instead it was the hosts.txt file and using pop() to obtain a hostname from a list that is return seperated. The code executes correctly if you do the following instead:

def makeConnection(self, parent):
    parent.server = parent.hostlist.pop().strip()
    parent.wmiConnection = wmi.WMI(computer=parent.server, user=parent.username, password=parent.password)
Related Topic