Sunteți pe pagina 1din 13

SQL WMI Provider

This article explains SQL WMI architecture and how to use SQL WMI provider from developers perspective.

Table of Contents
1. 2. 3. A. B. C. D. E. 4. SQL WMI Provider Introduction ................................................................................................ 3 SQL WMI Provider Components.................................................................................................. 5 How to use SQL WMI provider..................................................................................................... 6 Using Powershell ......................................................................................................................... 6 Using VBScript ............................................................................................................................ 7 Using C# ....................................................................................................................................... 8 Using C++ .................................................................................................................................... 9 Using SMO WMI ...................................................................................................................... 10 How to debug SQL WMI provider .............................................................................................. 12

SQLMgmt.com

Page 2

1. SQL WMI Provider - Introduction


Is there any WMI (Windows Management Instrumentation) support in SQL Server? Well, if we navigate to root\Microsoft\SqlServer namespace from WMI CIM Studio, we see two WMI provider namespaces as follows.

Figure 1 - SQL WMI namespace (SQL Server 2008)

We have ComputerManagement namespace (implemented in sqlmgmprovider.dll) which is mainly used by SQL Server Configuration Manager, and the other one ServerEvents (sqlwep.dll) which is used for server event notifications. (Note: if you search for all*. mof files under %Program Files%\Microosft SQL Server folder, you will also notice that there are some xe*.mof files under MSSQL\Binn. The schemas from these mof files go under root\WMI\EventTrace, and are used for SQL 2008 XEvent (Extended Events) feature.) In this post, we will look into ComputerManagement WMI provider. Microsoft SQL WMI provider for Computer Management was first introduced in SQL Server 2005. Since then, a few classes were added to SQL Server 2008 / SQL Server 2008 R2. Major feature of this SQL WMI provider includes SQL server service control, SQL service enumeration, client network settings, server network protocol settings, etc. The SQL WMI provider uses different namespace depending on SQL version:
SQL 2005 : root\Microsoft\SqlServer\ComputerManagement SQL 2008 (R2): root\Microsoft\SqlServer\ComputerManagement10 SQL 11 : root\Microsoft\SqlServer\ComputerManagement11

SQLMgmt.com

Page 3

Logical Architecture
Here is the high level logical architecture of the SQL WMI provider and its consumers. First, there are WMI clients that use the functionality of SQL WMI provider. SQL Server Configuration Manager(SQL CM) is the primary user, per se. SMO WMI (Microsoft.SqlServer.SqlWmiManagement.dll) provides all the SQL WMI functionality to .NET developers and SMO users. In addition, DBA can easily use VBScript or Powershell to access SQL WMI provider and of course C++/C# developers can use WMI API to write WMI client to access the SQL WMI provider.

Figure 2 - SQL WMI logical architecture

SQLMgmt.com

Page 4

2. SQL WMI Provider Components


The SQL WMI Provider consists of two main components, located in %Program Files%\Microsoft SQL Server\100\Shared folder.

Sqlmgmprovider.dll : This is a COM DLL that hosts all SQL WMI classes. Since its a COM DLL, it should be registered by using regsvr32.exe. SQL setup will do this so you dont have to do anything but there might be rare cases you want to register again. (ex: C> regsvr32 sqlmgmprovider.dll) sqlmgmprovider*.mof : The MOF file contains the SQL WMI schemas. This mof file is handy if you want to check property name or method name of the specific WMI class. The schemas are saved to CIM repository by running mofcomp.exe. Again, SQL setup will do this for you but just in case you need to do it : C> mofcomp sqlmgmproviderxpsp2up.mof (in admin console for Vista/Win7)

The SQL WMI provider (sqlmgmprovider) uses WMI SDK Provider framework library (framedyn.dll). If you look at SQL WMI mof file (sqlmgmproviderxpsp2up.mof) , you can see that the provider is an instance provider and also a method provider. So all the classes in sqlmgmprovider have the following methods : EnumerateInstances, GetObject, ExecQuery, PutInstance, DeleteInstance and ExecMethod. Not all method implementation is required, though, so some methods simply can return WBEM_E_PROVIDER_NOT_CAPABLE.

One of interesting components that sqlmgmprovider relying on is svrenumapi.dll (SQL 2005) / svrenumapi100.dll (SQL 2008), which basically provides SQL service related funcationalities such as enumerating services, start or stop the service, etc. For 64bit, its worth noting that there exist 64bit sqlmgmprovider.dll (under C:\Program Files) and 32bit sqlmgmprovider.dll (under C:Program Files (x86)). So depending on situation, you can have 2 wmiprvse.exe processes for SQL WMI in 64bit.

SQLMgmt.com

Page 5

3. How to use SQL WMI provider


There are a slew of ways to use SQL WMI provider. Some people use scripting while others want more sophisticated control by using C++/C#. Lets take some examples.

A. Using Powershell
Lets try to find what kind of SQL server network protocol are enabled. The following script enumerates enabled protocol. The result shows only TCP/IP is enabled.
PS C:> Get-WmiObject -namespace root\Microsoft\SqlServer\ComputerManagement10 -class ServerNetworkProtocol -filter Enabled=true __GENUS :2 __CLASS : ServerNetworkProtocol __SUPERCLASS : __DYNASTY : ServerNetworkProtocol __RELPATH : ServerNetworkProtocol.InstanceName=MSSQLSERVER, ProtocolName=Tcp __PROPERTY_COUNT :5 __DERIVATION : {} __SERVER : YONGSL __NAMESPACE : root\Microsoft\SqlServer\ComputerManagement10 __PATH : YONGSL\root\Microsoft\SqlServer\ComputerManagement10:ServerNetworkProtocol.InstanceName=M SSQLSE RVER,ProtocolName=Tcp Enabled : True InstanceName : MSSQLSERVER MultiIpConfigurationSupport : True ProtocolDisplayName : TCP/IP ProtocolName : Tcp

Now, lets enable NamePipe protocol against default instance. This time we use SetEnable() method in ServerNetworkProtocol class.
PS C:> $var = gwmi -namespace root\Microsoft\SqlServer\ComputerManagement10 class ServerNetworkProtocol -filter InstanceName=MSSQLSERVER AND ProtocolName=Np PS C:> $var.SetEnable()

After the method is done, we can check the result by using the first query above. But this time I used WQL (Wmi Query Language) to just take another query example.

SQLMgmt.com

Page 6

PS C:> gwmi -namespace root\Microsoft\SqlServer\Computer\Management10 -query SELECT * FROM ServerNetworkProtocol WHERE InstanceName=MSSQLSERVER | Select ProtocolName,Enabled ProtocolName Sm Np Tcp Via Enabled False True True False

B. Using VBScript
Here is a VBScript example. It uses GetObject with WINMGMTS moniker. Please note we added impersonatelevel and namespace in it. The script is pretty straigt forward. It simply connects to ComputerManagement10 namespace, gets SqlService objects and displays its property.
Set objNamespace = GetObject("WINMGMTS:{impersonationlevel=impersonate}//./root/Microsoft/SqlServer/ComputerMan agement10") Set inst = objNamespace.ExecQuery("SELECT * FROM ClientSettings") wscript.echo "PRESS ENTER TO CONTINUE.... (Attach debugger if needed)" WScript.StdIn.ReadLine Set services = objNamespace.ExecQuery("SELECT * FROM SqlService") IF services.Count = 0 THEN WScript.Echo "No data found for SqlService" END IF WScript.Echo vbNewLine & "SQL Services" FOR EACH svc IN services WScript.Echo "ServiceName: " & svc.ServiceName & vbNewLine next

SQLMgmt.com

Page 7

C. Using C#
The following samples are using .NET WMI classes whose namespace is System.Management. Sample1 enumerates all the instances of SqlService class, which basically list all SQL Server services.
using System.Management; void Sample1() { // Specify server, SQL WMI namespace and class name ManagementPath mgmtPath = new ManagementPath(); mgmtPath.Server = "YONGSL"; mgmtPath.NamespacePath = @"root\Microsoft\SqlServer\ComputerManagement10"; //For SQL 2008 mgmtPath.ClassName = "SqlService"; // Get instances of the SqlService class ManagementClass mgmtcls = new ManagementClass(mgmtPath); ManagementObjectCollection mgmtColl = mgmtcls.GetInstances(); // Enumerates Sql Service info foreach (ManagementObject mgmtObj in mgmtColl) { string svc = string.Format("{0} ({1}) ServiceAccount={2}", mgmtObj["ServiceName"], mgmtObj["Description"], mgmtObj["StartName"]); Console.WriteLine(svc); Console.WriteLine(); } // Using WMI path ManagementPath mp = new ManagementPath(); mp.Path = @"\\YONGSL\root\Microsoft\SqlServer\ComputerManagement10:SqlService.ServiceName='MSSQLSE RVER',SqlServiceType=1"; ManagementObject mo = new ManagementObject(mp); Console.WriteLine("Startname = {0}", mo["Startname"]); }

Another example - Sample2 - is using WQL to query SqlService with State property is 4 (which means Running service state). Some State values you might be interested in are Running=4, Stopped=1, Paused=7.
void Sample2() { // Search running SQL Services only ManagementObjectSearcher search = new ManagementObjectSearcher( @"\\.\root\Microsoft\SqlServer\ComputerManagement10", // scope SQLMgmt.com Page 8

"SELECT * FROM SqlService WHERE State=4"); // query // Get resultset ManagementObjectCollection coll = search.Get(); // Display results Console.WriteLine("[ Currently running SQL Services ]"); foreach (ManagementObject obj in coll) { Console.WriteLine(obj["ServiceName"]); } }

D.

Using C++

The following code illustrates the example of enumerating SQL Services in C++. First, we need to call CoInitialize to use COM and get WbemLocator. Once locator is aquired, connect to SQL WMI namespace. In this example, we used WQL to retrieve all SQL service instances.
#include <windows.h> #define _WIN32_DCOM #include <wbemidl.h> #pragma comment(lib, "wbemuuid.lib") #include <iostream> using namespace std; #include <comdef.h> void _tmain(int argc, _TCHAR* argv[]) { // CoInit HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT,RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0); // Connect to SQL WMI IWbemLocator *pWbemLocator = NULL; IWbemServices *pServices = NULL; hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (void**) &pWbemLocator); _bstr_t bstrNamespace = L"root\Microsoft\SqlServer\ComputerManagement10"; hr = pWbemLocator->ConnectServer(bstrNamespace, NULL, NULL, NULL, 0, NULL, NULL, &pServices); pWbemLocator->Release(); // Query for all SQL Services SQLMgmt.com Page 9

IEnumWbemClassObject* pEnumerator = NULL; hr = pServices->ExecQuery( bstr_t("WQL"), bstr_t("SELECT * FROM SqlService"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator); IWbemClassObject *pSqlSvc; ULONG ret = 0; while (pEnumerator) { hr = pEnumerator->Next(WBEM_INFINITE, 1, &pSqlSvc, &ret); if (!ret) break; VARIANT vName; hr = pSqlSvc->Get(L"ServiceName", 0, &vName, 0, 0); wcout << "Service Name : " << vName.bstrVal << endl; VariantClear(&vName); VARIANT vBinaryPath; hr = pSqlSvc->Get(L"BinaryPath", 0, &vBinaryPath, 0, 0); wcout << "-- Full EXE Command : " << vBinaryPath.bstrVal << endl << endl; VariantClear(&vBinaryPath); } pServices->Release(); pServices = NULL; CoUninitialize(); return; };

E.

Using SMO WMI

SMO provides a managed wrapper for SQL WMI provider. In order to use SMO WMI, you have to add reference to Microsoft.SqlServer.SqlWmiManagement.dll and then you will see the below Microsoft.SqlServer.Management.Smo.Wmi namespace (some dependent DLLs might need to be added) .
using System; using Microsoft.SqlServer.Management.Smo.Wmi; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { ManagedComputer comp = new ManagedComputer("(local)");

SQLMgmt.com

Page 10

// List all SQL Services foreach (Service svc in comp.Services) { Console.WriteLine("{0}: {1}", svc.Name, svc.DisplayName); } // List enabled server protocols for default instance Console.WriteLine("Enabled Server Protocols for MSSQLSERVER instance:"); foreach (ServerProtocol svrProt in comp.ServerInstances["MSSQLSERVER"].ServerProtocols) { if (svrProt.IsEnabled) { Console.WriteLine(svrProt.Name + " : Enabled"); } } // List enabled client protocols Console.WriteLine("Enabled Client Protocols:"); foreach (ClientProtocol cliProt in comp.ClientProtocols) { if (cliProt.IsEnabled) { Console.WriteLine(cliProt.Name + " : Enabled"); } } } } }

SQLMgmt.com

Page 11

4. How to debug SQL WMI provider


When SQL WMI provider is called from its client, wmiprvse.exe process (for XP or later) is created and load sqlmgmprovider.dll and executes the corresponding methods. wmiprvse.exe is transient process which means it is dynamically created on demand and dies if no more subsequent WMI call is requested. So for debugging WMI provider, sometimes it's challenging to attach (remote breakin) the running wmiprvse.exe process. In order to debug the WMI process, typically you can use the following steps. One thing to note is that wmiprvse can - as I said - come and goes, sometimes quicker than you expect. So need to attach debugger before it's gone.

Run "C> tlist -m sqlmgmprovider.dll" You will get PID of wmiprvse.exe. Attach the debugger with the PID. Ex) C> windbg -p 2438

Once you attach the debugger, you can find a method you want to set breakpoint by simply examine the class. Let us take a quick example. Say, for example, you want to look into SQL Service enumeration part. To find the corresponding method, let's examine CSqlServerInstance C++ class (this is SqlService WMI class).

0:006> x sqlmgmprovider!CSqlServerInstance::* 539a0324 sqlmgmprovider!CSqlServerInstance::PutInstance = <no type information> 5399b6a3 sqlmgmprovider!CSqlServerInstance::PauseService = <no type information> 5399c431 sqlmgmprovider!CSqlServerInstance::CreateComputerInstance = <no type information> 5399ae5e sqlmgmprovider!CSqlServerInstance::ExecMethod = <no type information> 53981818 sqlmgmprovider!CSqlServerInstance::`vftable' = <no type information> 5399bd2d sqlmgmprovider!CSqlServerInstance::SetServiceAccount = <no type information> 5399a85d sqlmgmprovider!CSqlServerInstance::CSqlServerInstance = <no type information> 5399af94 sqlmgmprovider!CSqlServerInstance::GetServiceType = <no type information> 5399b479 sqlmgmprovider!CSqlServerInstance::StopService = <no type information> 5399b228 sqlmgmprovider!CSqlServerInstance::GetObject = <no type information> 539a0324 sqlmgmprovider!CSqlServerInstance::DeleteInstance = <no type information> 5399b350 sqlmgmprovider!CSqlServerInstance::SetStartMode = <no type information> 5399b005 sqlmgmprovider!CSqlServerInstance::`scalar deleting destructor' = <no type information> 5399b02b sqlmgmprovider!CSqlServerInstance::EnumerateInstances = <no type information>

SQLMgmt.com

Page 12

5399baa3 sqlmgmprovider!CSqlServerInstance::SetServiceAccountPassword = <no type information> 5399b005 sqlmgmprovider!CSqlServerInstance::`vector deleting destructor' = <no type information> 5399a897 sqlmgmprovider!CSqlServerInstance::~CSqlServerInstance = <no type information> 539a5165 sqlmgmprovider!CSqlServerInstance::ExecQuery = <no type information> 5399b57f sqlmgmprovider!CSqlServerInstance::StartServiceW = <no type information> 5399a8c1 sqlmgmprovider!CSqlServerInstance::LoadPropertyValues = <no type information> 5399b8a3 sqlmgmprovider!CSqlServerInstance::ResumeService = <no type information> Now you want to set breakpoint onto EnumerateInstances(). 0:006> bp sqlmgmprovider!CSqlServerInstance::EnumerateInstances 0:006> bl 0 e 5399b02b 0001 (0001) 0:**** sqlmgmprovider!CSqlServerInstance::EnumerateInstances 0:006> g ModLoad: 3fde0000 40221000 C:WINDOWSsystem32msi.dll ModLoad: 4ac60000 4ac75000 C:Program FilesMicrosoft SQL ServerMSSQL10.MSSQLSERVERMSSQLBinnsqlboot.dll Breakpoint 0 hit eax=53981818 ebx=692eb8f8 ecx=539bbaac edx=7c90e514 esi=539bbaac edi=00000111 eip=5399b02b esp=00e0f05c ebp=00e0f06c iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 sqlmgmprovider!CSqlServerInstance::EnumerateInstances: 5399b02b 682c020000 push 22Ch

And in order to look into class object, you can search them by using "x sqlmgmprovider!My* "

SQLMgmt.com

Page 13

S-ar putea să vă placă și