{"id":289,"date":"2007-08-03T00:00:00","date_gmt":"2007-08-03T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/comparing-python-and-powershell-dba-scripting\/"},"modified":"2022-04-27T21:25:27","modified_gmt":"2022-04-27T21:25:27","slug":"comparing-python-and-powershell-dba-scripting","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/database-administration-sql-server\/comparing-python-and-powershell-dba-scripting\/","title":{"rendered":"Comparing Python and PowerShell DBA Scripting"},"content":{"rendered":"<p>I became interested in scripting about a year or two ago when I landed a DBA job in a larger shop that was primarily focused on production support and Database Change Management. I was assigned several projects, each of which had at least three servers, Dev, QA, and Prod.<\/p>\n<p>It quickly became apparent to me that keeping up with all the typical daily DBA tasks would require some automation. I had compiled an extensive set of SQL scripts to help with my daily tasks and I had dabbled with VBScript but it didn&#8217;t quite get my juices flowing. So, I continued searching, trying Perl and then Python, which I had tinkered with at home on a Linux box.<\/p>\n<p>I ended up deciding on Python, mostly because of its clean syntax which makes it really easy to read. An article entitled &#8220;Python for Oracle Geeks&#8221; was also an influence. All DBAs are busy, so I was looking for a language that I could be productive with in a minimum amount of time. I am by no means an expert at Python or PowerShell. I am a full-time DBA, remember?<\/p>\n<p>So, I&#8217;ve gotten to the point where I&#8217;ve automated several mundane DBA tasks and was pretty happy with my progress, when along comes PowerShell from Microsoft. I had heard about Monad but didn&#8217;t really pay it much attention because I was pretty satisfied with Python. Then, I sat for Gert Draper&#8217;s presentation on PowerShell at the Spring 2007 SQL Connections Conference in Orlando, Florida. I was very impressed so I bought Bruce Payette&#8217;s PowerShell book and dove in.<\/p>\n<p>My thoughts could be summarised as follows<\/p>\n<p>Why scripting?<\/p>\n<ul>\n<li>Automate repetitive tasks<\/li>\n<li>Query multiple servers for information in one script, run at the command line and returning the results in a single pass as text, HTML, or XLS.<\/li>\n<\/ul>\n<p>Why Python?<\/p>\n<ul>\n<li>Easy to read.<\/li>\n<li>No comic cursing, parentheses, or braces.<\/li>\n<li>Easy to learn<\/li>\n<li>Plenty of documentation on the Internet to help a newbie<\/li>\n<li>Available across multiple operating systems.<\/li>\n<li>A general purpose programming language used by the likes of Amazon.com, Google, and Industrial Light and Magic.<\/li>\n<\/ul>\n<p>Why PowerShell?<\/p>\n<ul>\n<li>Finally, a shell scripting environment for Microsoft Windows.<\/li>\n<li>Easier to get to the MS internals?<\/li>\n<li>Less code to complete the same task? Maybe.<\/li>\n<li>Learn about .Net, WMI, and the Windows Internals as you learn PowerShell<\/li>\n<li>Future integration into SQL Server.<\/li>\n<\/ul>\n<p>So, I&#8217;ve started translating my scripts to PowerShell in an effort to learn it and see how it compares to Python<\/p>\n<h2>The Examples<\/h2>\n<p>All of the examples to follow are simple ones that a full-time DBA has hacked together to try and ease the burden of the daily DBA chores.<\/p>\n<p>Nothing earth shattering here,\u00a0but I hope that you will find them useful. They are<\/p>\n<ol>\n<li><a href=\"#first\">Listing installed hot fixes, i.e. DST patch<\/a><\/li>\n<li><a href=\"#second\">Checking free space on drives.<\/a><\/li>\n<li><a href=\"#third\">Finding a database across multiple servers<\/a><\/li>\n<li><a href=\"#fourth\">Checking the version of SQL Server installed<\/a><\/li>\n<\/ol>\n<p>I&#8217;ll show the Python code first then the equivalent PowerShell for each task along with appropriate comments. I&#8217;ll also demonstrate how to output the results as HTML, text, or Excel spreadsheet.<\/p>\n<p>This past Spring, we had to make sure that the DST patch was installed on all of our database servers. We have approximately 300 of them.<\/p>\n<p>For most of them, we could determine from the following script that the patch was installed. There were some special cases but this script saved a lot of time.<\/p>\n<p>The basic idea for all the examples is to loop through a list of servers contained in a text file, connect to each server, run the query, and write the results out in the desired format.<\/p>\n<p>The Python scripts demonstrated will work with either <a href=\"http:\/\/www.activestate.com\/Products\/activepython\/\">ActivePython 2.4 or 2.5\u00a0from ActiveState.com<\/a>. It&#8217;s likely these scripts will work with <a href=\"http:\/\/www.codeplex.com\/Wiki\/View.aspx?ProjectName=IronPython\">IronPython also<\/a> but I have yet to verify it.<\/p>\n<h3 id=\"first\">Listing installed hot fixes, i.e. DST patch<\/h3>\n<h4>Python:<\/h4>\n<div>\nimport\u00a0string,sys,win32com.client<br \/>\nfrom\u00a0win32com.client\u00a0import\u00a0DispatchBaseClass<br \/>\nListOfServers=&#8217;c:\\\\MyDir\\\\AFewServers.txt&#8217;<br \/>\ntxtfile\u00a0=\u00a0open(&#8216;C:\\\\MyDir\\\\DSTPatched.txt&#8217;,&#8217;w&#8217;)<br \/>\nfor\u00a0line\u00a0in\u00a0open(ListOfServers,&#8217;r&#8217;).readlines():<br \/>\n\u00a0servers\u00a0=\u00a0string.split(string.strip(line),&#8217;\\n&#8217;)<br \/>\n\u00a0svr=servers[0]<br \/>\n\u00a0print\u00a0svr<br \/>\n\u00a0objWMIService\u00a0=\u00a0win32com.client.Dispatch(&#8220;WbemScripting.SWbemLocator&#8221;)<br \/>\n\u00a0objSWbemServices\u00a0=\u00a0objWMIService.ConnectServer(svr,&#8221;root\\cimv2&#8243;)<br \/>\n\u00a0colItems\u00a0=\u00a0objSWbemServices.ExecQuery(&#8220;Select\u00a0*\u00a0from<br \/>\nWin32_QuickFixEngineering\u00a0Where\u00a0ServicePackInEffect\u00a0=\u00a0&#8216;KB928388&#8242;&#8221;)<br \/>\n\u00a0for\u00a0objItem \u00a0in\u00a0colItems:<br \/>\n\u00a0\u00a0txtfile.write\u00a0(&#8216;CS\u00a0Name:\u00a0&#8216;\u00a0+\u00a0str(objItem.CSName)\u00a0+\u00a0&#8216;\\n&#8217;)<br \/>\n\u00a0\u00a0txtfile.write\u00a0(&#8216;Service\u00a0Pack\u00a0In\u00a0Effect:\u00a0&#8216;\u00a0+<br \/>\nstr(objItem.ServicePackInEffect)\u00a0+\u00a0&#8216;\\n&#8217;)<br \/>\n\u00a0\u00a0txtfile.write\u00a0(&#8216;\\n&#8217;)<br \/>\ntxtfile.close<\/div>\n<p>The results written to a text file are&#8230;<\/p>\n<p>CS Name: AT-RISCSQL143<br \/>\nService Pack In Effect: KB928388<\/p>\n<p>CS Name: AT-RISCDCC15N01<br \/>\nService Pack In Effect: KB928388<\/p>\n<p><em>(Our patches are pushed by Marimba which doesn&#8217;t typically set a lot of these values in our environment.)<\/em><\/p>\n<h4>PowerShell:<\/h4>\n<div>\n<p>foreach ($svr in get-content &#8220;<a>C:\\ MyDir\\AFewServers.txt<\/a>&#8220;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0 { $svr; get-wmiobject Win32_QuickFixEngineering | findstr KB928388 }<\/p>\n<\/div>\n<p>produces&#8230;<\/p>\n<p>AT-RISCSQL143<br \/>\nServicePackInEffect : KB928388<br \/>\nDescription : Hotfix for Windows XP (KB928388)<\/p>\n<p>Obviously, the most compelling concept here is that it took significantly fewer lines to produce the desired result. In defense of Python, the code that is needed to access the server, read input, and write output requires minimal changes once you&#8217;ve written your first Python script.\u00a0You can quickly modify\u00a0this\u00a0initial Python template script to accomplish other tasks.<\/p>\n<h3 id=\"second\">Checking free space on drives<\/h3>\n<p>Using Python, I just simply run master..xp_fixeddrives against a list of servers and format the output.<\/p>\n<h4>Python:<\/h4>\n<div>\n#\u00a0CheckDiskSpace.py<br \/>\n#\u00a0<br \/>\n#\u00a0A\u00a0script\u00a0to\u00a0check\u00a0disk\u00a0space\u00a0on\u00a0all\u00a0database\u00a0servers.\u00a0\u00a0<\/p>\n<p>import\u00a0getpass,string,sys,win32com.client<br \/>\nfrom\u00a0win32com.client\u00a0import\u00a0DispatchBaseClass<\/p>\n<p>#ListOfServers=&#8217;c:\\\\MyDir\\\\AFewServers.txt&#8217;<br \/>\nListOfServers=&#8217;c:\\\\MyDir\\\\AllServers.txt&#8217;<\/p>\n<p>uid\u00a0=\u00a0&#8216;rdameron&#8217;<\/p>\n<p>#\u00a0take\u00a0your\u00a0pick:\u00a0HTML\u00a0or\u00a0Excel<br \/>\n#htmfile\u00a0=\u00a0open(&#8216;c:\\\\MyDir\\\\SQLChkSpaceLog.htm&#8217;,&#8217;w&#8217;)<br \/>\nhtmfile\u00a0=\u00a0open(&#8216;c:\\\\MyDir\\\\SQLChkSpaceLog.xls&#8217;,&#8217;w&#8217;)<\/p>\n<p>htmfile.write(&#8216;&lt;TITLE&gt;SQL\u00a0Server\u00a0Space\u00a0Report&lt;\/TITLE&gt;\\n&#8217;)<\/p>\n<p>for\u00a0line\u00a0in\u00a0open(ListOfServers,&#8217;r&#8217;).readlines():<br \/>\n\u00a0\u00a0if\u00a0line[0]&lt;&gt;&#8217;#&#8217;:<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0servers\u00a0=\u00a0string.split(string.strip(line),&#8217;\\n&#8217;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0svr=servers [0]<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0print\u00a0svr<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0htmfile.write(&#8216;&lt;TABLE\u00a0WIDTH=100%\u00a0CELLPADDING=2\u00a0BORDER=2&gt;\\n&#8217;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0htmfile.write(&#8216;&lt;TR&gt;\\n&#8217;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0htmfile.write(&#8216;&lt;TD\u00a0BGCOLOR=aqua\u00a0ALIGN=CENTER\u00a0VALIGN=top\u00a0WIDTH=20%&gt;&lt;B&gt;&lt;FONT\u00a0FACE=&#8221;ARIAL&#8221;\u00a0SIZE=2&gt;&#8217;\u00a0+\u00a0svr\u00a0+\u00a0&#8216;&lt;\/FONT&gt;&lt;\/B&gt;&lt;\/TD&gt;\\n&#8217;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0htmfile.write(&#8216;&lt;TD\u00a0BGCOLOR=aqua\u00a0ALIGN=CENTER\u00a0VALIGN=top\u00a0WIDTH=80%&gt;&lt;B&gt;&lt;FONT\u00a0FACE=&#8221;ARIAL&#8221;\u00a0SIZE=2&gt;Free\u00a0Space\u00a0Report&lt;\/FONT&gt;&lt;\/B&gt;&lt;\/TD&gt;\\n&#8217;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0htmfile.write(&#8216;&lt;\/TR&gt;\\n&#8217;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0htmfile.write(&#8216;&lt;TD\u00a0BGCOLOR=aqua\u00a0ALIGN=LEFT\u00a0VALIGN=top\u00a0WIDTH=10%&gt;&lt;B&gt;&lt;FONT\u00a0FACE=&#8221;ARIAL&#8221;\u00a0SIZE=2&gt;Drive&lt;\/FONT&gt;&lt;\/B&gt;&lt;\/TD&gt;\\n&#8217;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0htmfile.write(&#8216;&lt;TD\u00a0BGCOLOR=aqua\u00a0ALIGN=LEFT\u00a0VALIGN=top\u00a0WIDTH=20%&gt;&lt;B&gt;&lt;FONT\u00a0FACE=&#8221;ARIAL&#8221;\u00a0SIZE=2&gt;MB\u00a0Free&lt;\/FONT&gt;&lt;\/B&gt;&lt;\/TD&gt;\\n&#8217;)\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0htmfile.write(&#8216;&lt;\/TR&gt;\\n&#8217;)<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0adoConn\u00a0=\u00a0win32com.client.Dispatch(&#8216;ADODB.Connection&#8217;)<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0connect\u00a0 =\u00a0&#8220;Provider=SQLOLEDB.1;Data\u00a0Source=%s;Initial\u00a0Catalog=master;Integrated\u00a0Security=SSPI;&#8221;\u00a0%\u00a0(svr)<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0sql\u00a0=\u00a0&#8216;<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0SET\u00a0NOCOUNT\u00a0ON<\/p>\n<p>EXEC\u00a0master.dbo.xp_fixeddrives<\/p>\n<p>&#8216;<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0adoConn.Open(connect)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0query\u00a0=\u00a0adoConn.Execute(sql)<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0while\u00a0not\u00a0query[0].EOF:<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0drive=query[0].Fields(0).Value<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0free=query[0].Fields(1).Value<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0htmfile.write(&#8216;&lt;TR&gt;\\n&#8217;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0htmfile.write(&#8216;&lt;TD\u00a0VALIGN=top&gt;&lt;FONT\u00a0FACE=&#8221;COURIER&#8221;\u00a0SIZE=2&gt;%s&lt;\/FONT&gt;&lt;\/TD&gt;\\n&#8217;\u00a0%\u00a0(drive))<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0htmfile.write(&#8216;&lt;TD\u00a0VALIGN=top&gt;&lt;FONT\u00a0FACE=&#8221;COURIER&#8221;\u00a0SIZE=2&gt;%s&lt;\/FONT&gt;&lt;\/TD&gt;\\n&#8217;\u00a0%\u00a0(free))<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0htmfile.write(&#8216;&lt;\/TR&gt;\\n&#8217;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0query [0].MoveNext()<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0htmfile.write(&#8216;&lt;\/TABLE&gt;\\n&#8217;)<\/p>\n<p>htmfile.close()<br \/>\nadoConn\u00a0=\u00a0None<\/p>\n<\/div>\n<p>Now, here are two ways to check free space with PowerShell&#8230;<\/p>\n<h4>PowerShell<\/h4>\n<div>\n<p>#1 Output as HTML<\/p>\n<p>foreach ($svr in get-content &#8220;C:\\MyDir\\AFewServers.txt&#8221;) { $svr; Get-WmiObject -Class Win32_LogicalDisk -Filter &#8220;DriveType=3&#8221; -ComputerName $svr | ConvertTo-Html -property DeviceID,FreeSpace,Size -title &#8220;Free Space&#8221; -body $svr &gt;&gt; c:\\FreeSpace.html}<\/p>\n<p>#2 Output as table<\/p>\n<p>foreach ($svr in get-content &#8220;<a>C:\\MyDir\\AFewServers.txt<\/a>&#8220;){<br \/>\n\u00a0\u00a0\u00a0 $dt = new-object &#8220;System.Data.DataTable&#8221;<br \/>\n\u00a0\u00a0\u00a0 $cn = new-object System.Data.SqlClient.SqlConnection\u00a0&gt;<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;server=$svr;database=master;Integrated Security=sspi&#8221;\u00a0<br \/>\n\u00a0\u00a0\u00a0 $cn.Open()<br \/>\n\u00a0\u00a0\u00a0 $sql = $cn.CreateCommand()<br \/>\n\u00a0\u00a0\u00a0 $svr<br \/>\n\u00a0\u00a0\u00a0 $sql.CommandText = &#8220;EXEC master.dbo.xp_fixeddrives&#8221;<br \/>\n\u00a0\u00a0\u00a0 $rdr = $sql.ExecuteReader()<br \/>\n\u00a0\u00a0\u00a0 $dt.Load($rdr)<br \/>\n\u00a0\u00a0\u00a0 $cn.Close()<br \/>\n\u00a0\u00a0\u00a0 $dt | Format-Table -autosize<br \/>\n}<\/p>\n<\/div>\n<h3 id=\"third\">Finding a database across multiple servers\u00a0<\/h3>\n<h4>Python<\/h4>\n<div>\n#\u00a0A\u00a0script\u00a0to\u00a0find\u00a0all\u00a0occurrences\u00a0of\u00a0a\u00a0database\u00a0on\u00a0multiple\u00a0servers.<br \/>\n#\u00a0Also,\u00a0demonstrates\u00a0passing\u00a0arguments\u00a0from\u00a0the\u00a0command\u00a0line\u00a0and\u00a0error\u00a0handling<br \/>\n#\u00a0Writes\u00a0output\u00a0to\u00a0a\u00a0text\u00a0file.<br \/>\n#\u00a0<br \/>\n#\u00a0Usage:\u00a0finddb.py\u00a0DatabaseName<\/p>\n<p>import\u00a0string,sys,win32com.client<br \/>\nfrom\u00a0win32com.client\u00a0import\u00a0DispatchBaseClass<\/p>\n<p>\n#\u00a0Python\u00a0automatically\u00a0stores\u00a0the\u00a0command-line\u00a0arguments\u00a0as\u00a0a\u00a0list\u00a0of\u00a0strings\u00a0in\u00a0the\u00a0argv\u00a0variable\u00a0of\u00a0the\u00a0sys\u00a0module.<br \/>\n#\u00a0If\u00a0you\u00a0want\u00a0to\u00a0see\u00a0the\u00a0list\u00a0of\u00a0command-line\u00a0arguments,\u00a0remove\u00a0the\u00a0#\u00a0in\u00a0column\u00a01\u00a0to\u00a0uncomment\u00a0the\u00a0line\u00a0&#8211;\u00a0print\u00a0sys.argv.<br \/>\n#\u00a0sys.argv[0]\u00a0always\u00a0contains\u00a0the\u00a0name\u00a0of\u00a0the\u00a0script.<br \/>\n#print\u00a0sys.argv\u00a0\u00a0<\/p>\n<p>#\u00a0Accept\u00a0command-line\u00a0argument\u00a0for\u00a0name\u00a0of\u00a0database\u00a0to\u00a0search\u00a0for.<br \/>\ndbname\u00a0=\u00a0sys.argv[1]<\/p>\n<p>#ListOfServers=&#8217;c:\\\\MyDir\\\\AllServers.txt&#8217;<br \/>\nListOfServers=&#8217;c:\\\\\u00a0MyDir\\\\AFewServers.txt&#8217;<\/p>\n<p>txtfile\u00a0=\u00a0open(&#8216;C:\\\\MyDir\\\\FindDB.txt&#8217;,&#8217;w&#8217;)<br \/>\ntxtfile.write(&#8216;Looking\u00a0for\u00a0database:\u00a0\u00a0&#8216;+\u00a0dbname\u00a0+\u00a0&#8216;\\n&#8217;)<br \/>\ntxtfile.write(&#8216;\\n&#8217;)<\/p>\n<p>for\u00a0line\u00a0in \u00a0open(ListOfServers,&#8217;r&#8217;).readlines():<br \/>\n\u00a0\u00a0if\u00a0line[0]&lt;&gt;&#8217;#&#8217;:<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0servers\u00a0=\u00a0string.split(string.strip(line),&#8217;,&#8217;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0svr=servers[0]<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0print\u00a0svr<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0sql\u00a0=\u00a0None<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0txtfile.write(svr\u00a0+\u00a0&#8216;:\u00a0\\n&#8217;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0adoConn\u00a0=\u00a0win32com.client.Dispatch(&#8216;ADODB.Connection&#8217;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0connect\u00a0=\u00a0&#8220;Provider=SQLOLEDB.1;Data\u00a0Source=%s;Initial\u00a0Catalog=UMRdb;Integrated\u00a0Security=SSPI;&#8221;\u00a0%\u00a0(svr)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0sql\u00a0=\u00a0&#8220;SELECT\u00a0name\u00a0FROM\u00a0master..sysdatabases\u00a0WHERE\u00a0name\u00a0=\u00a0&#8216;&#8221;\u00a0+\u00a0dbname\u00a0+\u00a0&#8220;&#8216;&#8221;<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0try:\u00a0\u00a0\u00a0#\u00a0Python\u00a0uses\u00a0&#8216;try\u00a0&#8211;\u00a0except&#8217;\u00a0to\u00a0do\u00a0error\u00a0handling<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0adoConn.Open( connect)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0except:\u00a0<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0txtfile.write(&#8216;\\t&#8217;\u00a0+\u00a0&#8220;Oops,\u00a0I\u00a0wasn&#8217;t\u00a0able\u00a0to\u00a0connect\u00a0to\u00a0&#8221;\u00a0+\u00a0svr\u00a0<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 +\u00a0&#8220;.\u00a0\u00a0Make\u00a0sure\u00a0the\u00a0server\u00a0name\u00a0is\u00a0correct.\u00a0\\n&#8221;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0continue<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0qry\u00a0=\u00a0adoConn.Execute(sql)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0qry[0].EOF:\u00a0\u00a0#database\u00a0was\u00a0not\u00a0found\u00a0<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0txtfile.write(&#8216;\\t&#8217;\u00a0+\u00a0&#8216;Not\u00a0here!&#8217;\u00a0+\u00a0&#8216;\\n&#8217;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0while\u00a0not\u00a0qry[0].EOF:\u00a0\u00a0#database\u00a0was\u00a0found<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0db=qry[0].Fields(0).Value<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0txtfile.write(&#8216;\\t&#8217;\u00a0+\u00a0&#8216;Found\u00a0it!\u00a0&#8216;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0txtfile.write(&#8216;\\t&#8217;\u00a0+\u00a0db\u00a0+\u00a0&#8216;\\n&#8217;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 qry[0].MoveNext()<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<br \/>\ntxtfile.close()<br \/>\nadoConn\u00a0=\u00a0None<\/p>\n<\/div>\n<h4>PowerShell:<\/h4>\n<div>\n<p>foreach ($svr in get-content &#8220;<a>C:\\MyDir\\AFewServers.txt<\/a>&#8220;){<br \/>\n\u00a0\u00a0\u00a0 $dt = new-object &#8220;System.Data.DataTable&#8221;<br \/>\n\u00a0\u00a0\u00a0 $cn = new-object System.Data.SqlClient.SqlConnection\u00a0\u00a0\u00a0 &#8220;server=$svr;database=master;Integrated Security=sspi&#8221;<br \/>\n\u00a0\u00a0\u00a0 $cn.Open()<br \/>\n\u00a0\u00a0\u00a0 $sql = $cn.CreateCommand()<br \/>\n\u00a0\u00a0\u00a0 #$svr<br \/>\n\u00a0\u00a0\u00a0 $sql.CommandText = &#8220;SELECT @@SERVERNAME AS Server_Name, name FROM master..sysdatabases WHERE name = &#8216;DatabaseYourLookingFor'&#8221;<br \/>\n\u00a0\u00a0\u00a0 $rdr = $sql.ExecuteReader()<br \/>\n\u00a0\u00a0\u00a0 $dt.Load($rdr)<br \/>\n\u00a0\u00a0\u00a0 $cn.Close()<br \/>\n\u00a0\u00a0\u00a0 $dt | Format-Table<br \/>\n}<\/p>\n<\/div>\n<h3 id=\"fourth\">Checking the version of SQL Server installed<\/h3>\n<h4>Python<\/h4>\n<div>\n#<br \/>\n#\u00a0A\u00a0script\u00a0to\u00a0check\u00a0the\u00a0SQL\u00a0Server\u00a0version\u00a0and\u00a0service\u00a0pack\u00a0on\u00a0multiple\u00a0servers<br \/>\n#\u00a0Writes\u00a0output\u00a0to\u00a0a\u00a0text\u00a0file.<br \/>\n#<br \/>\nimport\u00a0string,sys,win32com.client<br \/>\nfrom\u00a0win32com.client\u00a0import\u00a0DispatchBaseClass<\/p>\n<p>ListOfServers=&#8217;c:\\\\MyDir\\\\AllServers.txt&#8217;<br \/>\nuid\u00a0=\u00a0&#8216;rdameron&#8217;<br \/>\ntxtfile\u00a0=\u00a0open(&#8216;c:\\\\MyDir\\\\SQLVersions.txt&#8217;,&#8217;w&#8217;)<\/p>\n<p>for\u00a0line\u00a0in\u00a0open(ListOfServers,&#8217;r&#8217;).readlines():<br \/>\n\u00a0\u00a0if\u00a0line[0]&lt;&gt;&#8217;#&#8217;:<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0servers\u00a0=\u00a0string.split(string.strip(line),&#8217;\\n&#8217;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0svr=servers[0]<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0print\u00a0svr<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0sql\u00a0=\u00a0None<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0txtfile.write(&#8216;\\n&#8217;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0txtfile.write( svr\u00a0+\u00a0&#8216;:\u00a0\u00a0\\n&#8217;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0adoConn\u00a0=\u00a0win32com.client.Dispatch(&#8216;ADODB.Connection&#8217;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0connect\u00a0=\u00a0&#8220;Provider=SQLOLEDB.1;Data\u00a0Source=%s;Initial\u00a0Catalog=UMRdb;Integrated\u00a0Security=SSPI;&#8221;\u00a0%\u00a0(svr)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0sql\u00a0=\u00a0&#8220;SELECT\u00a0SERVERPROPERTY(&#8216;ProductVersion&#8217;)\u00a0AS\u00a0Version,\u00a0SERVERPROPERTY(&#8216;ProductLevel&#8217;)\u00a0as\u00a0SP&#8221;<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0#print\u00a0sql<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0adoConn.Open(connect)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0alog\u00a0=\u00a0adoConn.Execute(sql)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0while\u00a0not\u00a0alog[0].EOF:<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0version=alog[0].Fields(0).Value<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0sp=alog[0].Fields(1).Value<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0txtfile.write(&#8216;Version:\u00a0&#8216;\u00a0+\u00a0\u00a0version\u00a0+\u00a0&#8216;\\n&#8217;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0txtfile.write(&#8216;ServicePack:\u00a0&#8216;\u00a0+\u00a0sp\u00a0+\u00a0&#8216; \\n&#8217;)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0alog[0].MoveNext()<br \/>\ntxtfile.close()<br \/>\nadoConn\u00a0=\u00a0None<\/div>\n<h4>PowerShell:<\/h4>\n<div>\n<p>\u00a0foreach ($svr in get-content &#8220;<a>C:\\MyDir\\AFewServers.txt<\/a>&#8220;){<br \/>\n\u00a0\u00a0\u00a0 $dt = new-object &#8220;System.Data.DataTable&#8221;<br \/>\n\u00a0\u00a0\u00a0 $cn = new-object System.Data.SqlClient.SqlConnection &#8220;server=$svr;database=master;Integrated Security=sspi&#8221;<br \/>\n\u00a0\u00a0\u00a0 $cn.Open()<br \/>\n\u00a0\u00a0\u00a0 $sql = $cn.CreateCommand()<br \/>\n\u00a0\u00a0\u00a0 $sql.CommandText = &#8220;SELECT @@SERVERNAME AS ServerName, SERVERPROPERTY(&#8216;ProductVersion&#8217;) AS Version, SERVERPROPERTY(&#8216;ProductLevel&#8217;) as SP&#8221;<br \/>\n\u00a0\u00a0\u00a0 $rdr = $sql.ExecuteReader()<br \/>\n\u00a0\u00a0\u00a0 $dt.Load($rdr)<br \/>\n\u00a0\u00a0\u00a0 $cn.Close()<br \/>\n\u00a0\u00a0\u00a0 $dt | Format-Table -autosize<br \/>\n}<\/p>\n<\/div>\n<h2>Conclusions:<\/h2>\n<p>I&#8217;m pretty excited about what PowerShell offers. I&#8217;m beginning to think it&#8217;s easier to get things done with it and it looks like you can get more done with fewer lines of code using PowerShell. I found Python a bit easier to read initially but I&#8217;m getting used to the PowerShell syntax with the help of Bruce Payette&#8217;s PowerShell book and several PowerShell blogs and forum posts. Plenty of support has built up around PowerShell that helped me to write this article both from Microsoft and PowerShell users. One thing I won&#8217;t forget is Gert Drapers saying during his conference presentation that prior to PowerShell he used Perl for his admin scripts. It obvious from Bruce Payette&#8217;s book that Microsoft did take a significant amount of inspiration from languages like Python and Perl to build PowerShell. No matter which scripting language you choose, I think to be really effective in a large environment you must learn to script. I&#8217;m hooked on PowerShell because of what it can do to make my life simpler in our Microsoft environment but also the exposure to .Net and WMI that it provides for a DBA<\/p>\n<h2>Additional Reading:<\/h2>\n<p>&#8220;Windows PowerShell in Action&#8221; by Bruce Payette<\/p>\n<p>&#8220;Dive Into Python&#8221; by Mark Pilgrim<\/p>\n<p>code prettified by the <a href=\"http:\/\/www.simple-talk.com\/prettifier\/\">Simple-Talk Prettifier<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Just when it seemed that there were were no adequate scripting systems for DBAs that could access .NET, along came two. Powershell and Python.&hellip;<\/p>\n","protected":false},"author":221826,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143527,146042],"tags":[4143,4170,4635,4809,4150],"coauthors":[50394],"class_list":["post-289","post","type-post","status-publish","format-standard","hentry","category-database-administration-sql-server","category-python","tag-net","tag-database-administration","tag-powershell","tag-python-powershell","tag-sql"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/289","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221826"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=289"}],"version-history":[{"count":5,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/289\/revisions"}],"predecessor-version":[{"id":74697,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/289\/revisions\/74697"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=289"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=289"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=289"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=289"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}