<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://powershell.com/cs/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Search results for 'app:weblogs' matching tags 'Chad Miller' and 'Windows PowerShell'</title><link>http://powershell.com/cs/search/SearchResults.aspx?q=app:weblogs&amp;tag=Chad+Miller,Windows+PowerShell&amp;orTags=0&amp;o=DateDescending</link><description>Search results for 'app:weblogs' matching tags 'Chad Miller' and 'Windows PowerShell'</description><dc:language>en-US</dc:language><generator>CommunityServer 2008.5 (Build: 30929.2835)</generator><item><title>10 Tips for the SQL Server PowerShell Scripter</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2013/05/06/10-tips-for-the-sql-server-powershell-scripter.aspx</link><pubDate>Mon, 06 May 2013 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:23298</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;strong style="font-size:12px;"&gt;Summary&lt;/strong&gt;&lt;span style="font-size:12px;"&gt;: Microsoft PowerShell MVP, Chad Miller shares his top ten tips for the SQL Server Windows PowerShell scripter.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. Today&amp;rsquo;s blog is a bit unique. I was throwing around ideas with Chad Miller, and somehow we came up with the idea that he would share some tips for the SQL Server Windows PowerShell scripter. You can read more about Chad and see his other blog posts on the &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/tags/chad+miller/" target="_blank"&gt;Hey, Scripting Guy! Blog site&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And now, Chad&amp;hellip;&lt;/p&gt;
&lt;h3&gt;1. Use here-strings&lt;/h3&gt;
&lt;p&gt;Here-strings are great for working with strings that span multiple lines or contain characters you would normally need to escape, such as embedded quotes. Like regular strings, when using here-strings, you still get variables replaced by their values.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$group = &amp;quot;PRD&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;span style="font-size:12px;"&gt;#Don&amp;#39;t do this:&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;span style="font-size:12px;"&gt;$query = &amp;quot;SELECT DISTINCT&amp;quot;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$query +=&amp;quot;`n s.server_name&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$query += &amp;quot;`n FROM&amp;nbsp;&amp;nbsp;&amp;nbsp; msdb.dbo.sysmanagement_shared_registered_servers s&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$query +=&amp;quot;`n JOIN msdb.dbo.sysmanagement_shared_server_groups g ON s.server_group_id = g.server_group_id&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$query += &amp;quot;`n WHERE&amp;nbsp;&amp;nbsp; g.name = &amp;#39;$group&amp;#39;&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Instead use a here-string:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$query = @&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;SELECT DISTINCT&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; s.server_name&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;FROM&amp;nbsp;&amp;nbsp;&amp;nbsp; msdb.dbo.sysmanagement_shared_registered_servers s&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; JOIN msdb.dbo.sysmanagement_shared_server_groups g ON s.server_group_id = g.server_group_id&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;WHERE &amp;nbsp;&amp;nbsp;g.name = &amp;#39;$group&amp;#39;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;@&lt;/p&gt;
&lt;p&gt;Not only is the here-string example more readable, but you can also copy and paste it right into SQL Server Management Studio. You test your queries before running them in Windows Powershell, right? for For more information about here-strings, see &lt;a href="http://technet.microsoft.com/en-us/library/hh847740.aspx" target="_blank"&gt;about_Quoting_Rules&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;2. Leverage Central Management Server&lt;/h3&gt;
&lt;p&gt;Some administrators may store their list of servers in text files or Active Directory organizational units, but you have a SQL Server Central Management Server (CMS). Use your CMS to pull lists of servers and SQL Server instances for input into Windows PowerShell scripts.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$serverInstances = sqlcmd -S myCMServerInstance -d msdb -Q $query -h -1 -W&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$serverInstances | foreach {new-object Microsoft.SqlServer.Management.Smo.Server($($_.server_name)) } |&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Select Name, PhysicalMemory, @{n=&amp;#39;MaxServerMemory&amp;#39;; e={$_.Configuration.MaxServerMemory.RunValue}}&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Get server names by removing instance name i.e. Z001\SQL1 becomes Z001&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$servers = sqlcmd -S myCMServerInstance -d msdb -Q $query -h -1 -W | foreach { $_ -replace &amp;quot;\\.*|,.*&amp;quot; }&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;invoke-command -ComputerName $servers -ScriptBlock {get-psdrive -PSProvider FileSystem}&lt;/p&gt;
&lt;p&gt;For more information, see &lt;a href="http://msdn.microsoft.com/en-us/library/bb895144.aspx" target="_blank"&gt;Administer Multiple Servers Using Central Management Servers&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;3. Load SMO assemblies&lt;/h3&gt;
&lt;p&gt;SQL Server Management Objects (SMO) is the API you&amp;#39;ll use to script against SQL Server. To use SMO, you must first load the SMO assemblies. If you have SQL Server&amp;nbsp;2012, all you need to do to load assemblies is call &lt;strong&gt;Import-Module sqlps&lt;/strong&gt;. This will load the SMO assemblies with the sqlps module. If you&amp;#39;re not using 2012 or would prefer to load the assemblies without the sqlps module, you&amp;#39;ll need to use &lt;strong&gt;Add-Type&lt;/strong&gt; with the fully qualified name:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#For SQL Server 2008 R2 and&amp;nbsp;SQL Server 2008&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;add-type -AssemblyName &amp;quot;Microsoft.SqlServer.ConnectionInfo, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91&amp;quot; -ErrorAction Stop&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;add-type -AssemblyName &amp;quot;Microsoft.SqlServer.Smo, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91&amp;quot; -ErrorAction Stop&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;add-type -AssemblyName &amp;quot;Microsoft.SqlServer.SMOExtended, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91&amp;quot; -ErrorAction Stop&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;add-type -AssemblyName &amp;quot;Microsoft.SqlServer.SqlEnum, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91&amp;quot; -ErrorAction Stop&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;add-type -AssemblyName &amp;quot;Microsoft.SqlServer.Management.Sdk.Sfc, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91&amp;quot; -ErrorAction Stop&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#For SQL Server 2012&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;add-type -AssemblyName &amp;quot;Microsoft.SqlServer.ConnectionInfo, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91&amp;quot; -ErrorAction Stop&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;add-type -AssemblyName &amp;quot;Microsoft.SqlServer.Smo, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91&amp;quot; -ErrorAction Stop&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;add-type -AssemblyName &amp;quot;Microsoft.SqlServer.SMOExtended, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91&amp;quot; -ErrorAction Stop&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;add-type -AssemblyName &amp;quot;Microsoft.SqlServer.SqlEnum, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91&amp;quot; -ErrorAction Stop&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;add-type -AssemblyName &amp;quot;Microsoft.SqlServer.Management.Sdk.Sfc, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91&amp;quot; -ErrorAction Stop&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#See loaded SMO assemblies&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;[appdomain]::CurrentDomain.GetAssemblies() | where {$_.FullName -like &amp;quot;*sqlserver*&amp;quot;}&lt;/p&gt;
&lt;p&gt;Like SQL Server Management Studio, SMO is backwards compatible so you can script against 2000 and 2005 SQL Server using either the 2008 or 2012 version of SMO.&lt;/p&gt;
&lt;h3&gt;4. Exercise Invoke-Sqlcmd with caution&lt;/h3&gt;
&lt;p&gt;One of the cmdlets that is included with SQL Server&amp;nbsp;2012, SQL Server&amp;nbsp;2008&amp;nbsp;R2, and SQL Server&amp;nbsp;2008 is &lt;strong&gt;Invoke-Sqlcmd&lt;/strong&gt;. As the name implies, the cmdlet tries to be a Windows PowerShell version of the venerable sqlcmd utility introduced in SQL Server 2005 and enhanced with each SQL Server release. The &lt;strong&gt;Invoke-Sqlcmd&lt;/strong&gt; cmdlet has &lt;a href="https://connect.microsoft.com/SQLServer/SearchResults.aspx?SearchQuery=invoke-sqlcmd" target="_blank"&gt;several bugs and workarounds that you should be aware of&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One issue is with the &lt;strong&gt;QueryTimeout&lt;/strong&gt; setting. At the time of this writing, the documentation incorrectly states the following about &lt;strong&gt;QueryTimeout&lt;/strong&gt; parameter:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;help Invoke-Sqlcmd -Parameter QueryTimeout&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;QueryTimeout&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp; Specifies the number of seconds before the queries time out. If a timeout value is not specified, the queries do not time out. The timeout must be an integer between 1 and 65535.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp; Required?&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; false&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp; Position?&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; named&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp; Default value&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp; Accept pipeline input?&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; false&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp; Accept wildcard characters?&amp;nbsp; false&lt;/p&gt;
&lt;p&gt;This isn&amp;#39;t true, which can be easily proven by running this simple test:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;invoke-sqlcmd &amp;quot;waitfor delay &amp;#39;00:00:31&amp;#39;&amp;quot; -Database master -ServerInstance $env:computername&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Invoke-Sqlcmd : Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.&lt;/p&gt;
&lt;p&gt;So, you&amp;#39;ll need to specify a query timeout. In SQL Server&amp;nbsp;2012, the bug was partially fixed and you can specify 0, which means no&lt;strong&gt; QueryTimeout&lt;/strong&gt;:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;invoke-sqlcmd &amp;quot;waitfor delay &amp;#39;00:00:31&amp;#39;&amp;quot; -Database master -ServerInstance $env:computername\sql1 -querytimeout 0&lt;/p&gt;
&lt;p&gt;When you use the SQL Server&amp;nbsp;2008&amp;nbsp;R2 or SQL Server&amp;nbsp;2008 versions of &lt;strong&gt;Invoke-Sqlcmd&lt;/strong&gt;, specifying 0 doesn&amp;#39;t work. Instead, you&amp;#39;ll need to provide a value greater than 1. Here&amp;#39;s a trick that works:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;invoke-sqlcmd &amp;quot;waitfor delay &amp;#39;00:00:31&amp;#39;&amp;quot; -Database master -ServerInstance $env:computername\sql1 -querytimeout ([int]::MaxValue)&lt;/p&gt;
&lt;p&gt;One other issue that isn&amp;#39;t a bug, but something to be aware of&amp;hellip;&lt;/p&gt;
&lt;p&gt;If you&amp;#39;re querying data with columns larger than 4,000 characters for XML or char data types, or 1,024 bytes for binary data types, you&amp;#39;ll want to override the default settings for &lt;strong&gt;MaxCharLength&lt;/strong&gt; or &lt;strong&gt;MaxBinaryLength&lt;/strong&gt; parameters:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#By default character data larger than 4,000 is truncated&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;invoke-sqlcmd &amp;quot;select REPLICATE(&amp;#39;x&amp;#39;, 4001)&amp;quot; -Database master -ServerInstance $env:computername\sql1 | foreach {($_.Column1).length}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;4000&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#This is fixed by specifying a value for the maxcharlength parameter&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;invoke-sqlcmd &amp;quot;select REPLICATE(&amp;#39;x&amp;#39;, 4001)&amp;quot; -Database master -ServerInstance $env:computername\sql1&amp;nbsp; -maxcharlength ([int]::MaxValue) | foreach {($_.Column1).length}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;4001&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#See help for more information on max length parameters&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;help invoke-sqlcmd -Parameter max*&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;-MaxCharLength&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Specifies the maximum number of characters returned for columns with character or Unicode data types, such as&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; char, nchar, varchar, and nvarchar. The default is 4,000 characters.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Required?&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; false&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Position?&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; named&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Default value&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Accept pipeline input?&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; false&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Accept wildcard characters?&amp;nbsp; false&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;-MaxBinaryLength&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Specifies the maximum number of bytes returned for columns with binary string data types, such as binary and&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; varbinary. The default is 1,024 bytes.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Required?&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; false&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Position?&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; named&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Default value&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;Accept pipeline input?&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; false&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Accept wildcard characters?&amp;nbsp; false&lt;/p&gt;
&lt;p&gt;One serious issue with &lt;strong&gt;Invoke-Sqlcmd&lt;/strong&gt; is around error handling. As an example, the following command does not produce an error in &lt;strong&gt;Invoke-Sqlcmd&lt;/strong&gt; at the time of this writing:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;invoke-sqlcmd -ServerInstance $env:computername\sql1 -Database tempdb -Query &amp;quot;select 1/0&amp;quot; -OutputSqlErrors $true -AbortOnError -SeverityLevel 0 -ErrorLevel 0&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Sqlcmd.exe and SQL Server Management Studio return an error:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;sqlcmd.exe -S &amp;quot;%COMPUTERNAME%&amp;quot; -d tempdb -Q &amp;quot;select 1/0&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Msg 8134, Level 16, State 1, Server YourServer, Line 1 Divide by zero error encountered.&lt;/p&gt;
&lt;p&gt;Unfortunately, there aren&amp;#39;t any good workarounds for the error handling issue other than don&amp;#39;t use &lt;strong&gt;Invoke-Sqlcmd&lt;/strong&gt; if you need error handling. There are other issues with &lt;strong&gt;Invoke-Sqlcmd&lt;/strong&gt;, which the command-line utility, sqlcmd.exe, doesn&amp;#39;t have.&lt;/p&gt;
&lt;p&gt;In any case it&amp;#39;s trivial to write your own &lt;strong&gt;Invoke-Sqlcmd&lt;/strong&gt; replacement. For more information, see &lt;a href="http://gallery.technet.microsoft.com/scriptcenter/7985b7ef-ed89-4dfd-b02a-433cc4e30894"&gt;Invoke-Sqlcmd2&lt;/a&gt; in the Script Center Repository.&lt;/p&gt;
&lt;p&gt;You may want to continue to use sqlcmd.exe for scripted data loading.&lt;/p&gt;
&lt;h3&gt;5. Don&amp;#39;t forget SQL Server command-line utilities&lt;/h3&gt;
&lt;p&gt;One of tenets of Windows PowerShell is to not needlessly write scripts. What I mean by this is instead of writing a script to perform an action, first see if there&amp;#39;s a cmdlet that accomplishes the task. Think of a cmdlet as a script that you don&amp;#39;t have to write.&lt;/p&gt;
&lt;p&gt;And if there isn&amp;#39;t a cmdlet available? Here&amp;#39;s where Windows PowerShell (being a shell) comes in handy. You can still use the native Windows console applications. You might even find that if there is Windows PowerShell cmdlet, the console application simply works better. At the top of my list of SQL Server command-line utilities that are still very useful: &lt;strong&gt;sqlcmd&lt;/strong&gt;, &lt;strong&gt;dtutil&lt;/strong&gt;, and &lt;strong&gt;dtexec&lt;/strong&gt;, and Red Gate &lt;strong&gt;sqlcompare&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;6. Read the SMO documentation&lt;/h3&gt;
&lt;p&gt;If you&amp;#39;re going to write scripts that use SMO, you&amp;#39;ll probably want to spend some time looking at the SMO documentation. Rather than hunt through the documentation, I find it easier to search the web for the SMO documentation on a particular class. Add the term &amp;quot;SMO class&amp;quot; to your web search, for example, &amp;quot;smo server class.&amp;quot; The first item in your search results will usually be the MSDN documentation.&lt;/p&gt;
&lt;h3&gt;7. Don&amp;#39;t use Windows PowerShell for everything&lt;/h3&gt;
&lt;p&gt;If you know T-SQL or SQL Server Reporting Services, the solutions you build can leverage the best tool for the job. What&amp;#39;s really cool is using Windows PowerShell as only one part of the solution. One of my favorite patterns is to use Windows PowerShell to collect information, load the data into a SQL Server table, and then present the data as a web-based report in SQL Server Reporting Services.&lt;/p&gt;
&lt;p&gt;Check out my previous post, &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2010/11/01/use-powershell-to-collect-server-data-and-write-to-sql.aspx" target="_blank"&gt;Use PowerShell to Collect Server Data and Write to SQL&lt;/a&gt; for more information. Let&amp;#39;s face it, sometimes using Windows PowerShell is more complex than what&amp;#39;s needed. Do you need to interactively run query across multiple SQL Servers? It doesn&amp;#39;t get much simpler than multiserver queries in SQL Server Management Studio.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/5367.hsg_2D00_5_2D00_6_2D00_13_2D00_1.jpg"&gt;&lt;img title="Image of menu" src="http://blogs.technet.com/resized-image.ashx/__size/350x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/5367.hsg_2D00_5_2D00_6_2D00_13_2D00_1.jpg" alt="Image of menu" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;8. Load data with Out-GridView&lt;/h3&gt;
&lt;p&gt;Although you could mess with scripts to export data directly into Excel or convert CSV files, a quick and dirty way to get data into Excel is to simply copy and paste from &lt;strong&gt;Out-GridView&lt;/strong&gt;. This also works on small tables you open in SQL Server Management Studio Object Explorer: right-click &lt;strong&gt;Table&lt;/strong&gt; and select &lt;strong&gt;Edit Top 200 Rows&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;You&amp;#39;ll then be able to paste &lt;strong&gt;Out-GridView&lt;/strong&gt; output rows into a SQL Server table. This is especially useful when you need to run a Windows PowerShell command one-time and insert the data into Excel. Here&amp;#39;s an example script called &lt;a href="http://gallery.technet.microsoft.com/scriptcenter/Get-SqlSpn-17d5c0d7" target="_blank"&gt;Get-SqlSpn&lt;/a&gt;, which grabs all the SPNs in a domain related to SQL Server. I&amp;#39;ll then use &lt;strong&gt;Out-GridView&lt;/strong&gt; with CTRL+A and CTRL+C to copy, and then CTRL+V to paste into Excel.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;. ./get-sqlspn.ps1&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;$spns = Get-SqlSpn&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#4. Get Column Headers&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$object = $spns | select -first 1&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$ht = @{}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;foreach($property in $object.PsObject.get_properties()) {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp; $ht.add($property.Name.ToString(),$property.Name.ToString())&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;new-object psobject -Property $ht | out-gridview&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Copy/Paste heading row to Excel (Ctrl-A, Ctrl-C)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$spns | out-gridview&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Copy/Paste spns to Excel (Ctrl-A, Ctrl-C)&lt;/p&gt;
&lt;p&gt;This image shows an example of where I copy from:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8284.hsg_2D00_5_2D00_6_2D00_13_2D00_2.jpg"&gt;&lt;img title="Image of menu" src="http://blogs.technet.com/resized-image.ashx/__size/400x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8284.hsg_2D00_5_2D00_6_2D00_13_2D00_2.jpg" alt="Image of menu" width="400" height="132" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And here is my paste into Excel:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/4555.hsg_2D00_5_2D00_6_2D00_13_2D00_3.jpg"&gt;&lt;img title="Image of menu" src="http://blogs.technet.com/resized-image.ashx/__size/400x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/4555.hsg_2D00_5_2D00_6_2D00_13_2D00_3.jpg" alt="Image of menu" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;9. Adjust SMO StatementTimeout&lt;/h3&gt;
&lt;p&gt;The default statement time setting for SMO is 10 minutes. Of course, some operations (such as a backup or restore) can take longer than the default timeout of 600 seconds (10 minutes). Set the &lt;strong&gt;StatementTimeout&lt;/strong&gt; setting to no timeout by specifying 0:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$server = new-object (&amp;quot;Microsoft.SqlServer.Management.Smo.Server&amp;quot;) &amp;quot;Z001\SQL&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$server.ConnectionContext.StatementTimeout = 0&lt;/p&gt;
&lt;h3&gt;10. Handle Windows Powershell errors in SQL Server Agent jobs&lt;/h3&gt;
&lt;p&gt;By default the &lt;strong&gt;ErrorActionPreference&lt;/strong&gt; is set to Continue, and this has implications on how errors bubble up to the SQL Server Job Server. If you run a Windows PowerShell command as a SQL Server Agent job and there are no syntax errors yet, the command produces an error (for example, attempting to get operating system information from an unavailable server). The SQL Server Agent job will report success. If you want an error condition to halt execution of a SQL Server Agent job or to produce an error, you&amp;#39;ll need to add some error handling. You can set up a SQL Server Agent job with Windows PowerShell Job Step as follows:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;get-wmiobject Win32_OperatingSystem -ComputerName &amp;#39;nothere&amp;#39;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3441.hsg_2D00_5_2D00_6_2D00_13_2D00_4.jpg"&gt;&lt;img title="Image of menu" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3441.hsg_2D00_5_2D00_6_2D00_13_2D00_4.jpg" alt="Image of menu" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The job will run successfully, but if you run it directly in Windows PowerShell, you&amp;#39;ll see:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;get-wmiobject Win32_OperatingSystem -ComputerName &amp;#39;nothere&amp;#39;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;get-wmiobject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;At line:1 char:1&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;+ get-wmiobject Win32_OperatingSystem -ComputerName &amp;#39;nothere&amp;#39;&lt;/p&gt;
&lt;p&gt;To bubble up Windows PowerShell errors to SQL Server Agent, you&amp;#39;ll need to do one of the following:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A. Set your $ErrorActionPreference = &amp;quot;Stop&amp;quot;&lt;/strong&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$erroractionpreference = &amp;quot;Stop&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;get-wmiobject Win32_OperatingSystem -ComputerName &amp;#39;nothere&amp;#39;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;B. Set ErrorAction at the cmdlet-level (more granular)&lt;/strong&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;get-wmiobject Win32_OperatingSystem -ComputerName &amp;#39;nothere&amp;#39;&amp;nbsp; -ErrorAction &amp;#39;Stop&amp;#39;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;C. Use Try/Catch with ErrorActionPreference or ErrorAction &lt;/strong&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;try {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; get-wmiobject Win32_OperatingSystem -ComputerName &amp;#39;nothere&amp;#39; -ErrorAction &amp;#39;Stop&amp;#39;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;catch {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw &amp;quot;Something went wrong&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; #or rethrow error&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; #throw $_&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; #or throw an error no message&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; #throw&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;D. Continue, and fail the SQL Server Agent job&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s say you have a collection of computers and you want to continue on the error, but you also want to fail the job. In this case you can make use of the &lt;strong&gt;ErrorVariable&lt;/strong&gt;:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Note the -ErrorVariable parameter takes a variable name without the $ prefix.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;get-wmiobject Win32_OperatingSystem -ComputerName &amp;#39;localhost&amp;#39;,&amp;#39;nothere&amp;#39;,&amp;#39;Win7boot&amp;#39; -ErrorVariable myError&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;if ($myError)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;{ throw (&amp;quot;$myError&amp;quot;) }&lt;/p&gt;
&lt;p&gt;~Chad&lt;/p&gt;
&lt;p&gt;Thank you, Chad, for some extremely practical information. Well done! Join me tomorrow for the exciting conclusion to our SQL Server Week as we have a guest blog written by SQL Server MVP, Kendal Van ***.&lt;/p&gt;
&lt;p&gt;I invite you to follow me on &lt;a href="http://bit.ly/scriptingguystwitter" target="_blank"&gt;Twitter&lt;/a&gt; and &lt;a href="http://bit.ly/scriptingguysfacebook" target="_blank"&gt;Facebook&lt;/a&gt;. If you have any questions, send email to me at &lt;a href="mailto:scripter@microsoft.com" target="_blank"&gt;scripter@microsoft.com&lt;/a&gt;, or post your questions on the &lt;a href="http://bit.ly/scriptingforum" target="_blank"&gt;Official Scripting Guys Forum&lt;/a&gt;. See you tomorrow. Until then, peace.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ed Wilson, Microsoft Scripting Guy&lt;/strong&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3570404" width="1" height="1" alt="" /&gt;</description></item><item><title>Expert Commentary: 2012 Scripting Games Advanced Event 4</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2012/04/19/expert-commentary-2012-scripting-games-advanced-event-4.aspx</link><pubDate>Thu, 19 Apr 2012 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:16037</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;: Microsoft MVP, Chad Miller, provides expert commentary for 2012 Scripting Games Advanced Event 4.&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. Chad Miller is the expert commentator for Advanced Event 4.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Chad is a senior manager of database administration at Raymond James Financial. Chad has worked with Microsoft SQL Server since 1999, and he has been automating administration tasks by using Windows PowerShell since 2007. Chad is a Windows PowerShell MVP and the project coordinator and developer of the Windows PowerShell-based CodePlex project, SQL Server PowerShell Extensions (SQLPSX). Chad leads the Tampa PowerShell User Group, and he is a frequent speaker at users groups, SQL Saturdays, and Code Camps.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Blog:&amp;nbsp;&lt;a href="http://sev17.com/" target="_blank"&gt;Sev17&amp;mdash;SQL Server, PowerShell, and so on&lt;/a&gt;&lt;br /&gt; Twitter:&amp;nbsp;&lt;a href="https://twitter.com/#!/cmille19" target="_blank"&gt;@cmille19&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The function &lt;b&gt;Get-FolderSize&lt;/b&gt; reports the folder size of the specified folder and all subfolders. A path (folder) must be provided to the &lt;b&gt;Get-FolderSize&lt;/b&gt; function.&lt;/p&gt;
&lt;p&gt;To display the folder size for the current directory, use:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;b&gt;Get-FolderSize&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0407.hsg_2D00_4_2D00_19_2D00_12_2D00_adv_2D00_1.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/450x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0407.hsg_2D00_4_2D00_19_2D00_12_2D00_adv_2D00_1.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To display folder size information for a list of folders, use:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;b&gt;Get-FolderSize Desktop,Downloads,DropBox&lt;/b&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;or&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;b&gt;Get-Content folders.txt | Get-FolderSize&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The code for this script is shown here:&lt;/p&gt;
&lt;p&gt;#######################&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;lt;#&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;.SYNOPSIS&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Gets folder size.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;.DESCRIPTION&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;The Get-FolderSize function gets the folder size at the specified location.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;.EXAMPLE&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-FolderSize .&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;This command gets the folder size of the current directory. The dot (.) represents the item at the current location.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;.EXAMPLE&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-FolderSize C:\Windows&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;This command the folder size of the Windows directory.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;.INPUTS&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.String&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; You can pipe a string that contains a path to Get-FolderSize.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;.OUTPUTS&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Selected.System.Management.Automation.PSCustomObject&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;.NOTES&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Version History&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;v1.0&amp;nbsp;&amp;nbsp; - Chad Miller - Initial release&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#&amp;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;function Get-FolderSize&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;{&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [CmdletBinding()]&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; param(&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [ValidateNotNullorEmpty()]&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [string[]]$Path&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; BEGIN {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function Format-FolderSize&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; param($Size)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($Size -ge 1GB) {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;{0:N2} Gigabytes&amp;quot; -f $($Size/1GB)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; elseif ($Size -ge 1MB) {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;{0:N2} Megabytes&amp;quot; -f $($Size/1MB)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;{0:N2} Bytes&amp;quot; -f $Size&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } #Format-FolderSize&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PROCESS {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Get-Item $Path |&amp;nbsp; Foreach-Object {$_; $_ | Get-Childitem -Recurse} |&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Where-Object {$_.PSIsContainer}&amp;nbsp; |&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Select-Object FullName, @{name=&amp;#39;Size&amp;#39;;expression={$(Get-ChildItem $_.FullName -Recurse | Measure-Object -Sum -Property Length).Sum}} |&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sort-Object Size -Descending |&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Select-Object @{name=&amp;quot;Folder&amp;quot;;expression={$_.FullName}}, @{name=&amp;#39;Size of Folder&amp;#39;;expression={$(Format-FolderSize -Size $_.Size)}}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; END {}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;} #Get-FolderSize&lt;/p&gt;
&lt;p&gt;The main section of script is shown here:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/5684.hsg_2D00_4_2D00_19_2D00_12_2D00_adv_2D00_2.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/5684.hsg_2D00_4_2D00_19_2D00_12_2D00_adv_2D00_2.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The approach I took to solve this problem follows the structures of the PROCESS block of the script. I would start with step one and proceed to the next steps only&amp;nbsp;when the results from the previous steps have been achieved.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use the Get-Item cmdlet to retrieve information about the specified path. The ForEach-Object cmdlet returns the item, and Get-ChildItem is called recursively to retrieve all child items.&lt;/li&gt;
&lt;li&gt;Apply a filter using Where-Object, which tests whether the PSIsContainer property is true, which means the item is of type directory.&lt;/li&gt;
&lt;li&gt;After we have the specified directory and all subdirectories, use select-object to retrieve the FullName property, and add a Size property by using a hash table with name and expression keys. The expression uses the Measure-Object cmdlet, summing on the Length property.&lt;/li&gt;
&lt;li&gt;Now sort the object by the newly added Size property.&lt;/li&gt;
&lt;li&gt;Finally, use the &lt;b&gt;Select-Object&lt;/b&gt; cmdlet to emit a custom object with &lt;b&gt;Folder&lt;/b&gt; and &lt;b&gt;Size of Folder&lt;/b&gt; properties. The &lt;b&gt;Size of Folder&lt;/b&gt; property makes use of the function &lt;b&gt;Format-FolderSize&lt;/b&gt;, which is defined in the BEGIN block of &lt;b&gt;Get-FolderSize&lt;/b&gt;. The &lt;b&gt;Format-FolderSize&lt;/b&gt; handles formatting the folder size in the appropriate unit of measurement (gigabytes, megabytes, or bytes). By defining the &lt;b&gt;Format-Folder&lt;/b&gt; function in the BEGIN block, the function is private and not visible outside of the &lt;b&gt;Get-FolderSize&lt;/b&gt; function.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;~Chad&lt;/p&gt;
&lt;p&gt;The 2012 Scripting Games Guest Commentator Week will continue tomorrow when we will present the scenario for Event 5.&lt;/p&gt;
&lt;p&gt;I invite you to follow me on &lt;a href="http://bit.ly/scriptingguystwitter" target="_blank"&gt;Twitter&lt;/a&gt; and &lt;a href="http://bit.ly/scriptingguysfacebook" target="_blank"&gt;Facebook&lt;/a&gt;. If you have any questions, send email to me at &lt;a href="mailto:scripter@microsoft.com" target="_blank"&gt;scripter@microsoft.com&lt;/a&gt;, or post your questions on the &lt;a href="http://bit.ly/scriptingforum" target="_blank"&gt;Official Scripting Guys Forum&lt;/a&gt;. See you tomorrow. Until then, peace.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Ed Wilson, Microsoft Scripting Guy&lt;/b&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3491280" width="1" height="1" alt="" /&gt;</description></item><item><title>Four Easy Ways to Import CSV Files to SQL Server with PowerShell</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2011/11/28/four-easy-ways-to-import-csv-files-to-sql-server-with-powershell.aspx</link><pubDate>Mon, 28 Nov 2011 06:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:13400</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;: Learn four easy ways to use Windows PowerShell to import CSV files into SQL Server.&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. &amp;nbsp;I was chatting this week with Microsoft PowerShell MVP, Chad Miller, about the &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/tags/windows+powershell/csv+and+other+delimited+files/" target="_blank"&gt;series of blogs I recently wrote about using CSV files&lt;/a&gt;. He thought a helpful addition to the posts would be to talk about importing CSV files into a SQL Server. I most heartily agreed. Welcome to Guest Blogger Week. We will start off the week with a bang-up article by Chad Miller. Chad has previously written &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/tags/windows+powershell/guest+blogger/chad+miller/" target="_blank"&gt;guest blogs&lt;/a&gt; for the Hey, Scripting Guy! Blog. Here is a little information about Chad:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Chad Miller is a SQL Server database admin and the senior manager of database administration at Raymond James Financial.&amp;nbsp;In his spare time, he is the project coordinator and developer of&amp;nbsp;the CodePlex project SQL Server PowerShell Extensions (&lt;a href="http://sqlpsx.codeplex.com/" target="_blank"&gt;SQLPSX&lt;/a&gt;). Chad leads the &lt;a href="http://powershellgroup.org/tampa.fl" target="_blank"&gt;Tampa Windows PowerShell User Group&lt;/a&gt;, and he is a frequent speaker at SQL Saturdays and Code Camps.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Contact information:&lt;br /&gt; Blog: &lt;a href="http://sev17.com/" target="_blank"&gt;Sev17&lt;/a&gt;&lt;br /&gt; Twitter: &lt;a href="http://twitter.com/#!/cmille19" target="_blank"&gt;cmille19&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Importing CSV files into SQL Server&lt;/h1&gt;
&lt;p&gt;Windows PowerShell has built in support for creating CSV files by using the &lt;b&gt;Export-CSV&lt;/b&gt; cmdlet. However, the creation of a CSV file is usually only a short stop in an overall process that includes loading the file into another system. In this post, we&amp;#39;ll look at a few scripted-based approaches to import CSV data into SQL Server. &lt;b&gt;Note&lt;/b&gt;: SQL Server includes a component specifically for data migration called SQL Server Integration Services (SSIS), which is beyond the scope of this article.&lt;/p&gt;
&lt;h2&gt;T-SQL BULK INSERT command&lt;/h2&gt;
&lt;p&gt;The T-SQL &lt;a href="http://msdn.microsoft.com/en-us/library/ms188365.aspx" target="_blank"&gt;BULK INSERT &lt;/a&gt;command is of the easiest ways to import CSV files into SQL Server. The BULK INSERT command requires a few arguments to describe the layout of the CSV file and the location of file. Let&amp;#39;s look at an example of creating a CSV file by using &lt;b&gt;Export-CSV&lt;/b&gt;, and then importing the information into a SQL Server table by using BULK INSERT.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Requirements&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sysadmin or insert and bulkadmin to SQL Server&lt;/li&gt;
&lt;li&gt;Local access to SQL Server&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Setup&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;1. Download the following script: &lt;a href="http://gallery.technet.microsoft.com/ScriptCenter/7985b7ef-ed89-4dfd-b02a-433cc4e30894/" target="_blank"&gt;Invoke-SqlCmd2.ps1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://gallery.technet.microsoft.com/ScriptCenter/7985b7ef-ed89-4dfd-b02a-433cc4e30894/"&gt;&lt;/a&gt;2. Create a table disk space by copying the following code in SQL Server Management Studio.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Note&lt;/b&gt;: The example uses a database named &amp;quot;hsg.&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;CREATE TABLE dbo.diskspace(&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;UsageDate datetime,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;SystemName varchar(50),&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Label varchar(50),&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;VolumeName varchar(50),&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Size decimal(6,2),&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Free decimal(6,2),&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PrecentFree decimal(5,2)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;)&lt;/p&gt;
&lt;p&gt;The following image shows the command in SQL Server Management Studio.&lt;/p&gt;
&lt;pre&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8540.HSG_2D00_11_2D00_28_2D00_11_2D00_1.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8540.HSG_2D00_11_2D00_28_2D00_11_2D00_1.jpg" alt="Image of query" title="Image of query" /&gt;&lt;/a&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;/pre&gt;
&lt;p&gt;3. Save the following script as Get-DiskSpaceUsage.ps1, which will be used as the demonstration script later in this post.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;param($ComputerName=&amp;quot;.&amp;quot;)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WmiObject -computername &amp;quot;$computername&amp;quot; Win32_Volume -filter &amp;quot;DriveType=3&amp;quot; | foreach {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;new-object PSObject -property @{&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;UsageDate = $((Get-Date).ToString(&amp;quot;yyyy-MM-dd&amp;quot;))&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;SystemName = $_.SystemName&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Label = $_.Label&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;VolumeName = $_.Name&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Size = $([math]::round(($_.Capacity/1GB),2))&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Free = $([math]::round(($_.FreeSpace/1GB),2))&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PercentFree = $([math]::round((([float]$_.FreeSpace/[float]$_.Capacity) * 100),2))&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;} | Select UsageDate, SystemName, Label, VolumeName, Size, Free, PercentFree&lt;/p&gt;
&lt;p&gt;Now we will use the script Get-DiskSpaceUsage.ps1 that I presented earlier. It lists information about disk space, and it stores the information in a CSV file.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;span class="Apple-style-span" style="white-space:pre;"&gt;./get-diskusage.ps1 | export-csv -Path &amp;quot;C:\Users\Public\diskspace.csv&amp;quot; -NoTypeInformation&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The generated CSV file shows that &lt;b&gt;Export-CSV&lt;/b&gt; includes a text delimiter of double quotes around each field:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;UsageDate&amp;quot;,&amp;quot;SystemName&amp;quot;,&amp;quot;Label&amp;quot;,&amp;quot;VolumeName&amp;quot;,&amp;quot;Size&amp;quot;,&amp;quot;Free&amp;quot;,&amp;quot;PercentFree&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;2011-11-20&amp;quot;,&amp;quot;WIN7BOOT&amp;quot;,&amp;quot;RUNCORE SSD&amp;quot;,&amp;quot;D:\&amp;quot;,&amp;quot;59.62&amp;quot;,&amp;quot;31.56&amp;quot;,&amp;quot;52.93&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;2011-11-20&amp;quot;,&amp;quot;WIN7BOOT&amp;quot;,&amp;quot;DATA&amp;quot;,&amp;quot;E:\&amp;quot;,&amp;quot;297.99&amp;quot;,&amp;quot;34.88&amp;quot;,&amp;quot;11.7&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;2011-11-20&amp;quot;,&amp;quot;WIN7BOOT&amp;quot;,,&amp;quot;C:\&amp;quot;,&amp;quot;48&amp;quot;,&amp;quot;6.32&amp;quot;,&amp;quot;13.17&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;2011-11-20&amp;quot;,&amp;quot;WIN7BOOT&amp;quot;,&amp;quot;HP_TOOLS&amp;quot;,&amp;quot;F:\&amp;quot;,&amp;quot;0.1&amp;quot;,&amp;quot;0.09&amp;quot;,&amp;quot;96.55&amp;quot;&lt;/p&gt;
&lt;p&gt;Although many programs handle CSV files with text delimiters (including SSIS, Excel, and Access), BULK INSERT does not. To use BULK INSERT without a lot of work, we&amp;#39;ll need to remove the double quotes. We can use a quick and dirty way of simply replacing all the quotes in the CSV file. In the blog post &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2011/11/02/remove-unwanted-quotation-marks-from-csv-files-by-using-powershell.aspx" target="_blank"&gt;Remove Unwanted Quotation Marks from CSV Files by Using PowerShell&lt;/a&gt;, the Scripting Guys explains how to remove double quotes. This method can be used for circumstances where you know it won&amp;#39;t cause problems. How do you know? Well, the data being generated from our &lt;b&gt;Get-DiskspaceUsage&lt;/b&gt; should never have double quotes or commas in the data. So here&amp;#39;s the code to remove the double quotes:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;(Get-Content C:\Users\Public\diskspace.csv) | foreach {$_ -replace &amp;#39;&amp;quot;&amp;#39;} | Set-Content C:\Users\Public\diskspace.csv&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;UsageDate,SystemName,Label,VolumeName,Size,Free,PercentFree&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;2011-11-20,WIN7BOOT,RUNCORE SSD,D:\,59.62,31.56,52.93&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;2011-11-20,WIN7BOOT,DATA,E:\,297.99,34.88,11.7&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;2011-11-20,WIN7BOOT,,C:\,48,6.32,13.17&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;2011-11-20,WIN7BOOT,HP_TOOLS,F:\,0.1,0.09,96.55&lt;/p&gt;
&lt;p&gt;Now we are ready to import the CSV file as follows:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;. .\Invoke-SqlCmd2.ps1&lt;/p&gt;
&amp;nbsp;
&lt;p style="padding-left:30px;"&gt;$query = @&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;BULK INSERT hsg.dbo.diskspace FROM &amp;#39;C:\Users\Public\diskspace.csv&amp;#39;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;WITH (FIRSTROW = 2, FIELDTERMINATOR = &amp;#39;,&amp;#39;, ROWTERMINATOR = &amp;#39;\n&amp;#39;)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;@&lt;/p&gt;
&amp;nbsp;
&lt;p style="padding-left:30px;"&gt;Invoke-SqlCmd2 -ServerInstance &amp;quot;$env:computername\sql1&amp;quot; -Database hsg -Query $query&lt;/p&gt;
&lt;p&gt;The following data shows that our CSV file was successfully imported.&lt;/p&gt;
&lt;table cellpadding="0"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p align="center"&gt;&lt;b&gt;UsageDate&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p align="center"&gt;&lt;b&gt;System&lt;br /&gt; Name&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p align="center"&gt;&lt;b&gt;Label&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p align="center"&gt;&lt;b&gt;Volume&lt;br /&gt; Name&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p align="center"&gt;&lt;b&gt;Size&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p align="center"&gt;&lt;b&gt;Free&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p align="center"&gt;&lt;b&gt;Percent&lt;br /&gt; Free&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;11/20/2011 12:00:00 AM&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;WIN7BOOT&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;RUNCORE SSD&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;D:\&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;59.62&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;31.56&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;52.93&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;11/20/2011 12:00:00 AM&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;WIN7BOOT&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;DATA&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;E:\&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;297.99&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;34.88&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;11.70&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;11/20/2011 12:00:00 AM&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;WIN7BOOT&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;C:\&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;48.00&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;6.32&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;13.17&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;11/20/2011 12:00:00 AM&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;WIN7BOOT&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;HP_TOOLS&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;F:\&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;0.10&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;0.09&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;96.55&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;BULK INSERT works reasonably well, and it is very simple. However, there are some drawbacks, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You need elevated permissions on SQL Server.&lt;/li&gt;
&lt;li&gt;BULK INSERT doesn&amp;#39;t easily understand text delimiters.&lt;/li&gt;
&lt;li&gt;Using the UNC path to files requires an additional setup, as documented under &lt;a href="http://msdn.microsoft.com/en-us/library/ms188365.aspx" target="_blank"&gt;Permissions on the BULK INSERT site&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For these reasons, let&amp;#39;s look at some alternate approaches.&lt;/p&gt;
&lt;h2&gt;Before there was Windows PowerShell, there was LogParser&lt;/h2&gt;
&lt;p&gt;LogParser is a command-line tool and scripting component that was originally released by Microsoft in the IIS&amp;nbsp;6.0 Resource Kit. LogParser provides query access to different text-based files and output capability to various data sources including SQL Server. Even though this little tool hasn&amp;#39;t been updated since 2005, it has some nice features for loading CSV files into SQL Server.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Setup&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Download and install &lt;a href="http://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;amp;id=24659" target="_blank"&gt;LogParser 2.2&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;LogParser can do a few things that we couldn&amp;#39;t easily do by using BULK INSERT, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Automatically create a table based on the CSV layout&lt;/li&gt;
&lt;li&gt;Handle the text delimiter of double quotes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Note&lt;/b&gt;: CSV files do not need to be local.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Using LogParser&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You can use the LogParser command-line tool or a COM-based scripting interface. Let&amp;#39;s look at examples of both.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LogParser command-line tool&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;LogParser requires some special handling, which is why we use &lt;b&gt;Start-Process&lt;/b&gt;. Some switches and arguments are difficult to work with when running directly in Windows PowerShell. Also Windows Powershell_ISE will not display output from LogParser that are run via the command-line tool. Here is the syntax for running a command to generate and load a CSV file:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;./get-diskspaceusage.ps1 | export-csv -Path &amp;quot;C:\Users\Public\diskspace.csv&amp;quot; -NoTypeInformation -Force&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Uncomment/comment set-alias for x86 vs. x64 system&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#set-alias logparser &amp;quot;C:\Program Files\Log Parser 2.2\LogParser.exe&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;set-alias logparser &amp;quot;C:\Program Files (x86)\Log Parser 2.2\LogParser.exe&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;start-process -NoNewWindow -FilePath logparser -ArgumentList @&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;SELECT * INTO diskspaceLP FROM C:\Users\Public\diskspace.csv&amp;quot; -i:CSV -o:SQL -server:&amp;quot;Win7boot\sql1&amp;quot; -database:hsg -driver:&amp;quot;SQL Server&amp;quot; -createTable:ON&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;@&lt;/p&gt;
&lt;p&gt;Looking at SQL Server, we see that our newly created table contains the CSV file:&lt;/p&gt;
&lt;table cellpadding="0"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p align="center"&gt;&lt;b&gt;Filename&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p align="center"&gt;&lt;b&gt;Row&lt;br /&gt; Number&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p align="center"&gt;&lt;b&gt;Usage&lt;br /&gt; Date&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p align="center"&gt;&lt;b&gt;System&lt;br /&gt; Name&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p align="center"&gt;&lt;b&gt;Label&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p align="center"&gt;&lt;b&gt;Volume&lt;br /&gt; Name&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p align="center"&gt;&lt;b&gt;Size&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p align="center"&gt;&lt;b&gt;Free&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p align="center"&gt;&lt;b&gt;Percent&lt;br /&gt; Free&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;C:\Users\Public\diskspace.csv&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;2&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;2011-11-20&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;WIN7BOOT&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;RUNCORE SSD&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;D:\&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;59.62&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;31.56&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;52.93&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;C:\Users\Public\diskspace.csv&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;3&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;2011-11-20&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;WIN7BOOT&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;DATA&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;E:\&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;297.99&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;34.88&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;11.7&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;C:\Users\Public\diskspace.csv&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;4&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;2011-11-20&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;WIN7BOOT&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;C:\&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;48&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;6.32&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;13.16&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;C:\Users\Public\diskspace.csv&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;5&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;2011-11-20&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;WIN7BOOT&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;HP_TOOLS&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;F:\&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;0.1&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;0.09&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;96.55&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;b&gt;CreateTable &lt;/b&gt;switch will create the table if it does not exist; and if it does exist, it will simply append the rows to the existing table. Also notice that we got two new columns: Filename and Row Number, which could come in handy if we are loading a lot of CSV files. You can eliminate the Filename and Row Number columns by specifying the column list in the &lt;b&gt;Select&lt;/b&gt; statement as we&amp;#39;ll see in a moment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LogParser COM scripting&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Using the COM-based approach to LogParser is an alternative method to using the command line. Although the COM-based approach is a little more verbose, you don&amp;#39;t have to worry about wrapping the execution in the &lt;b&gt;Start-Process&lt;/b&gt; cmdlet. The COM-based approach also handles the issue with Windows Powershell ISE. Here is code to work with the COM object:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$logQuery = new-object -ComObject &amp;quot;MSUtil.LogQuery&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$inputFormat = new-object -comobject &amp;quot;MSUtil.LogQuery.CSVInputFormat&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$outputFormat = new-object -comobject &amp;quot;MSUtil.LogQuery.SQLOutputFormat&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$outputFormat.server = &amp;quot;Win7boot\sql1&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$outputFormat.database = &amp;quot;hsg&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$outputFormat.driver = &amp;quot;SQL Server&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$outputFormat.createTable = $true&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$query = &amp;quot;SELECT UsageDate, SystemName, Label, VolumeName, Size, Free, PercentFree INTO diskspaceLPCOM FROM C:\Users\Public\diskspace.csv&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$null = $logQuery.ExecuteBatch($query,$inputFormat,$outputFormat)&lt;/p&gt;
&lt;p&gt;The main drawback to using LogParser is that it requires, well&amp;hellip;installing LogParser. For this reason, let&amp;#39;s look at one more approach.&lt;/p&gt;
&lt;h2&gt;Use Windows PowerShell to collect server data and write to SQL Server&lt;/h2&gt;
&lt;p&gt;In my previous Hey, Scripting Guy! post, &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2010/11/01/use-powershell-to-collect-server-data-and-write-to-sql.aspx" target="_blank"&gt;Use PowerShell to Collect Server Data and Write to SQL&lt;/a&gt;, I demonstrated some utility functions for loading any Windows PowerShell data into SQL Server. Let&amp;#39;s revisit this solution using the CSV file example:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Setup&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Download the following scripts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://gallery.technet.microsoft.com/ScriptCenter/4208a159-a52e-4b99-83d4-8048468d29dd/" target="_blank"&gt;Out-DataTable.ps1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://gallery.technet.microsoft.com/ScriptCenter/c193ed1a-9152-4bda-b5c0-acd044e68b2c/" target="_blank"&gt;Add-SqlTable.ps1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://gallery.technet.microsoft.com/ScriptCenter/2fdeaf8d-b164-411c-9483-99413d6053ae/" target="_blank"&gt;Write-DataTable.ps1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://gallery.technet.microsoft.com/ScriptCenter/7985b7ef-ed89-4dfd-b02a-433cc4e30894/" target="_blank"&gt;Invoke-SqlCmd2.ps1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Run the following code to create a CSV file, convert to a data table, create a table in SQL Server, and load the data:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;. .\out-datatable.ps1&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;. .\Add-SqlTable.ps1&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;. .\write-datatable.ps1&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;. .\Invoke-SqlCmd2.ps1&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$dt = .\Get-DiskSpaceUsage.ps1 | Out-DataTable&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Add-SqlTable -ServerInstance &amp;quot;Win7boot\Sql1&amp;quot; -Database &amp;quot;hsg&amp;quot; -TableName diskspaceFunc -DataTable $dt&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-DataTable -ServerInstance &amp;quot;Win7boot\Sql1&amp;quot; -Database &amp;quot;hsg&amp;quot; -TableName &amp;quot;diskspaceFunc&amp;quot; -Data $dt&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;invoke-sqlcmd2 -ServerInstance &amp;quot;Win7boot\Sql1&amp;quot; -Database &amp;quot;hsg&amp;quot; -Query &amp;quot;SELECT * FROM diskspaceFunc&amp;quot; | Out-GridView&lt;/p&gt;
&lt;p&gt;The following image shows the resulting table in Grid view.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3362.hsg_2D00_11_2D00_28_2D00_11_2D00_2.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3362.hsg_2D00_11_2D00_28_2D00_11_2D00_2.jpg" alt="Image of table" title="Image of table" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The observant reader will notice that I didn&amp;#39;t write the information to a CSV file. Instead, I created an in-memory data table that is stored in my &lt;b&gt;$dt&lt;/b&gt; variable. This is because by using this approach, there was not a need to create a CSV file, but for completeness let&amp;#39;s apply the solution to our CSV loading use case:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;. .\out-datatable.ps1&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;. .\Add-SqlTable.ps1&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;. .\write-datatable.ps1&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;. .\Invoke-SqlCmd2.ps1&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;./get-diskspaceusage.ps1 | export-csv -Path &amp;quot;C:\Users\Public\diskspace.csv&amp;quot; -NoTypeInformation -Force&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$dt = Import-Csv -Path &amp;quot;C:\Users\Public\diskspace.csv&amp;quot; | Out-DataTable&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Add-SqlTable -ServerInstance &amp;quot;Win7boot\Sql1&amp;quot; -Database &amp;quot;hsg&amp;quot; -TableName diskspaceFunc -DataTable $dt&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-DataTable -ServerInstance &amp;quot;Win7boot\Sql1&amp;quot; -Database &amp;quot;hsg&amp;quot; -TableName &amp;quot;diskspaceFunc&amp;quot; -Data $dt&lt;/p&gt;
&lt;p&gt;This post demonstrated three approaches to loading CSV files into tables in SQL Server by using a scripted approach. The approaches range from using the very simple T-SQL BULK INSERT command, to using LogParser, to using a Windows PowerShell function-based approach.&lt;/p&gt;
&lt;p&gt;Thank you, Chad, for sharing this information with us. It looks like your last four scripts have the makings of an awesome NetAdminCSV module.&lt;/p&gt;
&lt;p&gt;I invite you to follow me on &lt;a href="http://bit.ly/scriptingguystwitter" target="_blank"&gt;Twitter&lt;/a&gt; and &lt;a href="http://bit.ly/scriptingguysfacebook" target="_blank"&gt;Facebook&lt;/a&gt;. If you have any questions, send email to me at &lt;a href="mailto:scripter@microsoft.com" target="_blank"&gt;scripter@microsoft.com&lt;/a&gt;, or post your questions on the &lt;a href="http://bit.ly/scriptingforum" target="_blank"&gt;Official Scripting Guys Forum&lt;/a&gt;. See you tomorrow. Until then, peace.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Ed Wilson, Microsoft Scripting Guy&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3467053" width="1" height="1" alt="" /&gt;</description></item></channel></rss>