<?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 'Scripting Guy!' and 'services'</title><link>http://powershell.com/cs/search/SearchResults.aspx?q=app:weblogs&amp;tag=Scripting+Guy!,services&amp;orTags=0&amp;o=DateDescending</link><description>Search results for 'app:weblogs' matching tags 'Scripting Guy!' and 'services'</description><dc:language>en-US</dc:language><generator>CommunityServer 2008.5 (Build: 30929.2835)</generator><item><title>Send an Email Message with Service Status Via PowerShell</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2012/12/19/send-an-email-message-with-service-status-via-powershell.aspx</link><pubDate>Wed, 19 Dec 2012 06:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:20667</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;strong&gt;Summary:&lt;/strong&gt; Microsoft Scripting Guy, Ed Wilson, shows how to use Windows PowerShell to send an email message with service status info.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://img.microsoft.com/library/media/1033/technet/images/scriptcenter/qanda/q-sm.jpg" alt="Hey, Scripting Guy! Question" /&gt;&amp;nbsp;Hey, Scripting Guy! I have a number of services on a remote server that I would like to monitor. I would like to see the status of these services and receive these status updates via an email message. I have looked around on the Internet and not found a satisfactory script&amp;mdash;everything looks too complicated. Can you help me?&lt;/p&gt;
&lt;p&gt;&amp;mdash;DB&lt;/p&gt;
&lt;p&gt;&lt;img src="http://img.microsoft.com/library/media/1033/technet/images/scriptcenter/qanda/a-sm.jpg" alt="Hey, Scripting Guy! Answer" /&gt;&amp;nbsp;Hello DB,&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. Well, it is sort of cold and rainy down here in Charlotte, North Carolina. But tomorrow is supposed to be a beautiful sunny day. So, at least there is hope. If the weather is good, the Scripting Wife and I are planning on heading out to the Columbia Zoo in Columbia, South Carolina, tomorrow. They have a very nice zoo there, and we always enjoy spending a few hours there. Combine that with lunch out at a nice restaurant, and we end up having a great day.&lt;/p&gt;
&lt;p&gt;DB, monitoring the status of your services and sending you an email message does not have to be a zoo, it can be a really simple solution&amp;mdash;in fact, it is a single line of code.&lt;/p&gt;
&lt;h2&gt;Checking the status of services on a remote server&lt;/h2&gt;
&lt;p&gt;To check the status of services on a remote computer, I can use the &lt;strong&gt;Get-Service&lt;/strong&gt; cmdlet (assuming I have rights, and the appropriate ports in the Windows Firewall are open). In fact, it can be really easy. Suppose I want to check on the status of services associated with my SQL Server. In this case, it is really easy because the services begin with MSSQL. Therefore, I can use this bit of information, and do something like the following (&lt;strong&gt;gsv&lt;/strong&gt; is an alias for the &lt;strong&gt;Get-Service&lt;/strong&gt; cmdlet):&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;gsv -cn sql1 -Name mssql*&lt;/p&gt;
&lt;p&gt;One thing to keep in mind is that the &lt;strong&gt;Get-Service&lt;/strong&gt; cmdlet returns an object, or in this example, a series of objects. The ultimate goal is to write the information to an email message&amp;mdash;I cannot write an object to an email message. Therefore, I will need to convert the output to a string. Luckily, Windows PowerShell contains the &lt;strong&gt;Out-String&lt;/strong&gt; cmdlet. The code to retrieve SQL service information from a remote server named SQL1 and to return that information as a string is shown here, along with the associated output.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;14:57 C:\&amp;gt; gsv -cn sql1 -Name mssql* | out-string&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Status&amp;nbsp;&amp;nbsp; Name&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; DisplayName&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;nbsp; -----------&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Running&amp;nbsp; MSSQL$SHAREPOINT&amp;nbsp;&amp;nbsp; SQL Server (SHAREPOINT)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Running&amp;nbsp; MSSQLFDLauncher&amp;nbsp;&amp;nbsp;&amp;nbsp; SQL Full-text Filter Daemon Launche...&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Running&amp;nbsp; MSSQLSERVER&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SQL Server (MSSQLSERVER)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Stopped&amp;nbsp; MSSQLServerADHe... SQL Active Directory Helper Service&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Running&amp;nbsp; MSSQLServerOLAP... SQL Server Analysis Services (MSSQL...&lt;/p&gt;
&lt;h2&gt;Sending an email message&lt;/h2&gt;
&lt;p&gt;Windows PowerShell&amp;nbsp;2.0 introduced a very cool cmdlet&amp;mdash;the &lt;strong&gt;Send-MailMessage&lt;/strong&gt; cmdlet. The &lt;strong&gt;Send-MailMessage&lt;/strong&gt; cmdlet permits me to, well, send an email message. One of the great things to do is to create default values for this cmdlet&amp;mdash;such as the From field and the SMTPServer field. &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/12/03/use-powershell-default-parameter-values-to-simplify-scripts.aspx" target="_blank"&gt;In Windows PowerShell 3.0 this is easy to do&lt;/a&gt;, but for my one-liner today, I will not create default values. The key fields I need to populate are From, To, Subject, Message, and SMTPServer. For the message, I use the command I populated earlier to get the remote service information to a string. The resultant command appears here&amp;mdash;keep in mind, it is a single-line command that spans two lines on the blog.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Send-MailMessage -To edwilson@contoso.net -From &amp;quot;ed@iammred.net&amp;quot; -SmtpServer ex1.contoso.net -Subject &amp;quot;Service Status SQL1&amp;quot; -body ((gsv -cn sql1 -Name mssql*) | out-string)&lt;/p&gt;
&lt;p&gt;The email message 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/7776.hsg_2D00_12_2D00_19_2D00_12_2D00_01.png"&gt;&lt;img title="Image of email message" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/7776.hsg_2D00_12_2D00_19_2D00_12_2D00_01.png" alt="Image of email message" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;DB, that is all there is to using Windows PowerShell to retrieve the status of services on your remote server. You can easily plug this sort of one-line command into the Task Scheduler to send you a status message every hour, or as often as you feel you need the status update. &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/tags/scheduled+tasks/windows+powershell/" target="_blank"&gt;I have written quite a bit about using Windows PowerShell and the Task Scheduler&lt;/a&gt;. Join me tomorrow when I will talk about more cool Windows PowerShell stuff.&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=3541618" width="1" height="1" alt="" /&gt;</description></item><item><title>Use PowerShell to Find Non-Starting Automatic Services</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2012/12/18/use-powershell-to-find-non-starting-automatic-services.aspx</link><pubDate>Tue, 18 Dec 2012 06:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:20648</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;strong&gt;Summary:&lt;/strong&gt; Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to troubleshoot non-starting automatic services.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://img.microsoft.com/library/media/1033/technet/images/scriptcenter/qanda/q-sm.jpg" alt="Hey, Scripting Guy! Question" /&gt;&amp;nbsp;Hey, Scripting Guy! I have this server in a remote office that is running SharePoint. I do not know what version, but I am not certain that is a problem because it used to work. The problem is the workers in this remote office use this SharePoint server every day&amp;mdash;they update copies of an Excel spreadsheet that tracks their daily business activity. Anyway, the server is sort of old, and routinely runs with nearly 100 percent of the memory utilized, and 90 percent of the CPU utilized. Today, I got a call from the office manager saying that they cannot access SharePoint. I tried to make a remote desktop protocol (RDP) connection to troubleshoot the machine, but to be honest, with the limited bandwidth and hardware constraints on the machine, RDP creeps me out, and I want to give up in frustration. What I think I need to do is check the status of the services to see what is started, what is not, and if there are any error codes.&lt;/p&gt;
&lt;p&gt;&amp;mdash;DD&lt;/p&gt;
&lt;p&gt;&lt;img src="http://img.microsoft.com/library/media/1033/technet/images/scriptcenter/qanda/a-sm.jpg" alt="Hey, Scripting Guy! Answer" /&gt;&amp;nbsp;Hello DD,&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. Well today, the weather is balmy &amp;hellip; at least I think it is balmy, though not sure exactly what balmy is, so it may not actually be balmy. What the weather does do is remind me of when I was growing up in Florida. The weather outside is 60 degrees Fahrenheit with a humidity of nearly 80 percent. It is not raining, but after spending a bit of time outside, it feels like it will rain. The Magnolia tree in my front yard even has a couple of bloom buds on it, but whether those will turn into flowers or not remains to be seen. So why am I talking retro here? Well DD, it is because to check what you need to check will require you to take a retro-type of approach.&lt;/p&gt;
&lt;h2&gt;Obtaining service startmode and exit code information&lt;/h2&gt;
&lt;p&gt;I love using the &lt;strong&gt;Get-Service&lt;/strong&gt; Windows PowerShell cmdlet. In fact, the &lt;strong&gt;Get-Service&lt;/strong&gt; cmdlet is one of the cmdlets I refer to as a &amp;ldquo;demo&amp;rdquo; cmdlet. Why demo? Well, because it is so easy to use, and because it returns so much good information. I use it every time I am doing a demonstration of Windows PowerShell for network administrators who have never before seen Windows PowerShell. Luckily, that particular audience pool is rapidly shrinking, and I only occasionally speak to an audience where no one has seen Windows PowerShell previously.&lt;/p&gt;
&lt;p&gt;But, three pieces of information commonly required for troubleshooting Windows services are not returned by the &lt;strong&gt;Get-Service&lt;/strong&gt; cmdlet. These three pieces of information are the service &lt;em&gt;StartMode&lt;/em&gt;, the service &lt;em&gt;StartName&lt;/em&gt;, and &amp;nbsp;&lt;em&gt;ExitCode&lt;/em&gt;. To find these three pieces of information requires using the &lt;strong&gt;Win32_Service&lt;/strong&gt; WMI class.&lt;/p&gt;
&lt;h2&gt;Finding started and stopped services&lt;/h2&gt;
&lt;p&gt;DD, you stated that you want to see the &lt;em&gt;StartMode&lt;/em&gt;, &lt;em&gt;StartName&lt;/em&gt;, and the &lt;em&gt;ExitCode&lt;/em&gt; of the services. You also say you want to see what is started and what is not. You can easily get what is started and what is not from the &lt;strong&gt;Get-Service&lt;/strong&gt; cmdlet&amp;mdash;in fact, the &lt;strong&gt;Get-Service&lt;/strong&gt; cmdlet takes a &lt;strong&gt;ComputerName&lt;/strong&gt;&lt;em&gt; &lt;/em&gt;parameter, and therefore, it might work, depending on the firewall configuration.&lt;/p&gt;
&lt;p&gt;By using the Windows PowerShell&amp;nbsp;3.0 &lt;strong&gt;Get-CimInstance&lt;/strong&gt; cmdlet, the following command returns the service state (what is started and what is not) on a remote computer.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-CimInstance win32_service -computer sql1 | Sort state | select name, state&lt;/p&gt;
&lt;p&gt;The command and its output associated are 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/3288.hsg_2D00_12_2D00_18_2D00_12_2D00_01.png"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3288.hsg_2D00_12_2D00_18_2D00_12_2D00_01.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;By using the Windows PowerShell&amp;nbsp;2.0 cmdlets, the only change required is to change from using the &lt;strong&gt;Get-CimInstance&lt;/strong&gt; cmdlet to using the &lt;strong&gt;Get-WmiObject&lt;/strong&gt;. This command is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WmiObject win32_service -computer sql1 | Sort state | select name, state&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&amp;nbsp; &amp;nbsp;When converting a &lt;strong&gt;Get-WmiObject&lt;/strong&gt; command to &lt;strong&gt;Get-CimInstance&lt;/strong&gt;, keep in mind that the &lt;strong&gt;Get-WmiObject&lt;/strong&gt;&lt;em&gt; &lt;/em&gt;cmdlet uses &lt;strong&gt;&amp;ndash;Class&lt;/strong&gt;, and &lt;strong&gt;Get-CimInstance&lt;/strong&gt; cmdlet uses &lt;strong&gt;&amp;ndash;ClassName&lt;/strong&gt;. But using &lt;strong&gt;&amp;ndash;Class&lt;/strong&gt; (or even using it positionally as done in my previous example) works&amp;mdash; the problem would be converting a &lt;strong&gt;Get-CimInstance&lt;/strong&gt; cmdlet that had spelled out &lt;strong&gt;&amp;ndash;ClassName&lt;/strong&gt; to &lt;strong&gt;Get-WmiObject&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Finding start up accounts, exit codes, and startup type&lt;/h2&gt;
&lt;p&gt;To find information that is more directly related to troubleshooting, it is better to filter out information more directly related to why the service did not start. I am interested in, first, seeing if the service is set to start up automatically and to see if it is, in fact, running. I use the following filter:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;-Filter &amp;quot;startmode = &amp;#39;auto&amp;#39; AND state != &amp;#39;running&amp;#39;&amp;quot;&lt;/p&gt;
&lt;p&gt;Next, I select the name of the service, the startup account used by the service, and the exit code. The command using the &lt;strong&gt;Get-Ciminstance&lt;/strong&gt; cmdlet (along with output associated with the command is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;15:42 C:\&amp;gt; Get-CimInstance win32_service -Filter &amp;quot;startmode = &amp;#39;auto&amp;#39; AND state != &amp;#39;running&amp;#39;&amp;quot; -ComputerName sql1 | select name, startname, exitcode&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;name&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; startname&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;&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; exitcode&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;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;&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;&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;FIMSynchronizationService&amp;nbsp;&amp;nbsp;&amp;nbsp; Administrator@iammred.net&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1066&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;MSSQLServerADHelper100&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; NT AUTHORITY\NETWORKSERVICE&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1066&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;RemoteRegistry&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; NT AUTHORITY\LocalService&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;sppsvc&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; NT AUTHORITY\NetworkService&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;SQLAgent$SHAREPOINT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; NT AUTHORITY\NETWORK SER...&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0&lt;/p&gt;
&lt;p&gt;On Windows PowerShell&amp;nbsp;2.0, the command is the one showing here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WmiObject win32_service -Filter &amp;quot;startmode = &amp;#39;auto&amp;#39; AND state != &amp;#39;running&amp;#39;&amp;quot; -ComputerName sql1 | select name, startname, exitcode&lt;/p&gt;
&lt;p&gt;If a service has an exitcode value of 0, then it means that no error generated when the service exited. For some services, they start, and then stop, and then do not start back up again until they are needed (not all the time, mind you, just some of the time). If I want to hone in on services that do not have an exit code of 0, then I add one more bit of code to my filter. The revised filter is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;-Filter &amp;quot;startmode = &amp;#39;auto&amp;#39; AND state != &amp;#39;running&amp;#39; AND Exitcode !=0 &amp;quot;&lt;/p&gt;
&lt;p&gt;The complete command is shown here (note, this is a one-line command that is wrapped to display on the blog).&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-CimInstance win32_service -Filter &amp;quot;startmode = &amp;#39;auto&amp;#39; AND state != &amp;#39;running&amp;#39; AND Exitcode !=0 &amp;quot; -ComputerName sql1 | select name, startname, exitcode&lt;/p&gt;
&lt;p&gt;Using the Windows PowerShell&amp;nbsp;2.0 cmdlets, the command is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-wmiobject win32_service -Filter &amp;quot;startmode = &amp;#39;auto&amp;#39; AND state != &amp;#39;running&amp;#39; AND Exitcode !=0 &amp;quot; -ComputerName sql1 | select name, startname, exitcode&lt;/p&gt;
&lt;p&gt;Both commands and their output are 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/0702.hsg_2D00_12_2D00_18_2D00_12_2D00_02.png"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0702.hsg_2D00_12_2D00_18_2D00_12_2D00_02.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;DD, that is all there is to using Windows PowerShell to check on the status of Windows Services. Join me tomorrow when I will talk about some more cool Windows PowerShell stuff.&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=3541392" width="1" height="1" alt="" /&gt;</description></item><item><title>Three Cool PowerShell Service Tricks</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2012/08/27/three-cool-powershell-service-tricks.aspx</link><pubDate>Mon, 27 Aug 2012 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:18620</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;: Ed Wilson, the Microsoft Scripting Guy, talks about three cool Windows PowerShell tricks for working with services.&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. It does not matter what ones role is, whether an Exchange Server admin, a Group Policy guru, or even an ordinary every day power user, one eventually needs to work with services. Today I will show three cool tricks that involve using Windows PowerShell to work with services.&lt;/p&gt;
&lt;h2&gt;Stop multiple services at once&lt;/h2&gt;
&lt;p&gt;One of the nice features of the &lt;b&gt;Get-Service&lt;/b&gt; cmdlet is that it accepts an array. Therefore, I can find information about specific services by supplying the name of multiple services. This technique is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;PS C:\&amp;gt; Get-Service bits,wuauserv&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Status&amp;nbsp;&amp;nbsp; Name&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; DisplayName&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;nbsp;-----------&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Running&amp;nbsp; bits&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; Background Intelligent Transfer Ser...&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Running&amp;nbsp; wuauserv&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Windows Update&lt;/p&gt;
&lt;p&gt;The &lt;b&gt;Stop-Service&lt;/b&gt; cmdlet accepts an array of ServiceController objects (the type of object returned by the &lt;b&gt;Get-Service &lt;/b&gt;cmdlet). Therefore, I can pipe the results of the &lt;b&gt;Get-Service&lt;/b&gt; cmdlet to the &lt;b&gt;Stop-Service&lt;/b&gt; cmdlet to stop the array of services. This command is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-Service bits,wuauserv | Stop-Service&lt;/p&gt;
&lt;p&gt;To see what a command does prior to the actual execution of the command, use the &lt;b&gt;WhatIf&lt;/b&gt;&lt;i&gt; &lt;/i&gt;switch. In the image that follows, the use of the &lt;b&gt;WhatIf&lt;/b&gt;&lt;i&gt; &lt;/i&gt;switch to prototype the command appears, followed by the actual command to stop the services.&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/3036.HSG_2D00_8_2D00_27_2D00_12_2D00_01.png"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3036.HSG_2D00_8_2D00_27_2D00_12_2D00_01.png" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Start multiple services&lt;/h2&gt;
&lt;p&gt;The &lt;b&gt;Start-Service&lt;/b&gt; cmdlet also accepts an array of ServiceController objects as pipelined input. This means that I can use &lt;b&gt;Get-Service&lt;/b&gt; to look at my service status, and then pipe the objects to the &lt;b&gt;Start-Service&lt;/b&gt; cmdlet if required. This command 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/2626.HSG_2D00_8_2D00_27_2D00_12_2D00_02.png"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/2626.HSG_2D00_8_2D00_27_2D00_12_2D00_02.png" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Stopping and disabling services in one command&lt;/h2&gt;
&lt;p&gt;A cool thing is that I can use the &lt;b&gt;Get-Service&lt;/b&gt; cmdlet to check on a group of services. If I want to stop them, I can pipe the returned ServiceController object to the &lt;b&gt;Stop-Service&lt;/b&gt; cmdlet. But what if I also do not want the services to start up on the next reboot? Here is where some really cool stuff comes into play&amp;hellip;&lt;/p&gt;
&lt;p&gt;I use the &lt;b&gt;PassThru&lt;/b&gt;&lt;i&gt; &lt;/i&gt;switch, and the ServiceController objects will pass along the pipeline. I can then use those objects with the &lt;b&gt;Set-Service&lt;/b&gt; cmdlet and change the startup type of the services to Disabled. Here is the command to accomplish this task.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-Service bits,wuauserv | Stop-Service -PassThru | Set-Service -StartupType disabled&lt;/p&gt;
&lt;p&gt;Unfortunately, although &lt;b&gt;Set-Service&lt;/b&gt; permits setting the startup type of the service to Disabled, the &lt;b&gt;Get-Service&lt;/b&gt; cmdlet does not report the startup type of the service. To check on the results of our command, I need to use WMI. Here is the WMI command that I use to check the start mode of the services.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;gwmi win32_service -filter &amp;quot;name = &amp;#39;bits&amp;#39; OR name = &amp;#39;wuauserv&amp;#39;&amp;quot;&lt;/p&gt;
&lt;p&gt;The command and the associate output from the command are shown in the image that follows.&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/0447.HSG_2D00_8_2D00_27_2D00_12_2D00_03.png"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0447.HSG_2D00_8_2D00_27_2D00_12_2D00_03.png" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Join me tomorrow when I will talk about more way cool Windows PowerShell stuff.&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=3516149" width="1" height="1" alt="" /&gt;</description></item><item><title>The Scripting Wife Uses PowerShell to Find Service Accounts</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2012/02/15/the-scripting-wife-uses-powershell-to-find-service-accounts.aspx</link><pubDate>Wed, 15 Feb 2012 06:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:14664</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;: The Scripting Wife interrupts Brahms to learn how to use Windows PowerShell to find service accounts and service start modes.&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. One of life&amp;rsquo;s real pleasures is sitting around a fireplace, listening to a &lt;a href="http://en.wikipedia.org/wiki/Double_Concerto_(Brahms)" target="_blank"&gt;Brahms concerto&lt;/a&gt;, and sipping a cup of &lt;a href="http://en.wikipedia.org/wiki/Chamomile" target="_blank"&gt;chamomile tea&lt;/a&gt;. I like to add a bit of local honey, and drop in a cinnamon stick. So here I am&amp;hellip;mellow and as relaxed as a cat lying in a bay window on a warm summer afternoon. The &lt;a href="http://charlotte-sql.org/" target="_blank"&gt;Charlotte SQL User Group&lt;/a&gt; meeting tonight was awesome. We had not seen Chris Skorlinski (the speaker) since the &lt;a href="http://www.sqlsaturday.com/46/eventhome.aspx" target="_blank"&gt;Raleigh SQL Saturday&lt;/a&gt;, so we were excited to go. The Scripting Wife and I had a great time, and it was a nice chance to see some friends we had not seen for a while.&lt;/p&gt;
&lt;p&gt;Anyway, work finished, now it is time for a warm fire, a little Brahms, and a cup of warm (but not boiling) tea. About to nod off, I was suddenly startled back into reality as the overhead light suddenly switched on.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;How can you see in here in the dark,&amp;rdquo; the Scripting Wife exclaimed.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;There was nothing to see&amp;mdash;I was listening to Brahms,&amp;rdquo; I began.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;You need to turn that racket down. The neighbor&amp;rsquo;s dog is beginning to howl. I think he prefers Trace Adkins to that classical stuff anyway,&amp;rdquo; she continued, &amp;ldquo;As long as you are awake, I have a problem with a Windows PowerShell command.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;I see. I think it is you who likes Trace Adkins.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Yep, but don&amp;rsquo;t sidetrack me with talk about Trace Adkins, I need to be prepared for the 2012 Scripting Games so I do not embarrass you or me. Now back to what I came to ask you. I am trying to figure out what account a service uses to start, and I don&amp;rsquo;t see it. &amp;ldquo;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;And&amp;hellip;&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;And nothing. I type &lt;b&gt;Get-Service&lt;/b&gt;, and I do not see anything about service user accounts.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Show me your command,&amp;rdquo; I wearily asked.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;It is right here. Nothing hard&amp;hellip;see?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;She plopped down beside me on the sofa and showed me her laptop. She had typed the single command shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-Service&lt;/p&gt;
&lt;p&gt;The command and the output from the command are shown in the image that follows.&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/6266.hsg_2D00_2_2D00_15_2D00_12_2D00_01.png"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/6266.hsg_2D00_2_2D00_15_2D00_12_2D00_01.png" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;You know that there is more information don&amp;rsquo;t you?&amp;rdquo; I asked.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Well, duh,&amp;rdquo; she said. &amp;ldquo;OK, I will clear the screen and send the output to the &lt;b&gt;Format-List&lt;/b&gt; cmdlet.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Here is what the Scripting Wife did to clear the screen and to obtain all the information available from the &lt;b&gt;Get-Service&lt;/b&gt; cmdlet.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;She cleared the screen by using the &lt;b&gt;Clear-Host&lt;/b&gt; command. But instead of typing &lt;b&gt;Clear-Host&lt;/b&gt;, she used the &lt;b&gt;cls&lt;/b&gt;&lt;i&gt; &lt;/i&gt;shortcut command instead.&lt;/li&gt;
&lt;li&gt;Next, she pressed the Up arrow one time to retrieve the previous &lt;b&gt;Get-Service&lt;/b&gt; command.&lt;/li&gt;
&lt;li&gt;She then typed a space &amp;lt;space&amp;gt; by tapping the Space bar one time, and then she typed a pipe character (the pipe character | is located above the Enter key on my keyboard).&lt;/li&gt;
&lt;li&gt;She then typed a space and &lt;b&gt;Format-List&lt;/b&gt; * after the pipe character.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The complete command is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-Service | Format-List *&lt;/p&gt;
&lt;p&gt;The command and the associated output from the command are shown in the image that follows.&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/2146.hsg_2D00_2_2D00_15_2D00_12_2D00_02.png"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/2146.hsg_2D00_2_2D00_15_2D00_12_2D00_02.png" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;OK. I am looking at this output, and I still do not see anything about the service account that a service uses to start up,&amp;rdquo; she complained.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Well, I did not say it was there, did I? I just asked you if you had looked at all of the information that the &lt;b&gt;Get-Service&lt;/b&gt; cmdlet provides,&amp;rdquo; I stated. &amp;ldquo;To find the service account start-up information, you need to use WMI. Remember yesterday when we talked about &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/02/14/the-scripting-wife-uses-powershell-to-get-hardware-information.aspx" target="_blank"&gt;Using PowerShell to Get Hardware Information&lt;/a&gt;? You can use the same technique today as you used yesterday.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;The Scripting Wife thought for a few seconds, and then she typed the following command.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WmiObject &amp;ndash;list *service*&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Wow, that is a lot of information,&amp;rdquo; she exclaimed. She turned the laptop monitor so I could look at the display. Indeed, as is shown here, it is a lot of information.&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/1524.hsg_2D00_2_2D00_15_2D00_12_2D00_03.png"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1524.hsg_2D00_2_2D00_15_2D00_12_2D00_03.png" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Use the same technique that you used yesterday to find the WMI class you need to work with services,&amp;rdquo; I prompted.&lt;/p&gt;
&lt;p&gt;Within a few minutes, the Scripting Wife was pointing at &lt;b&gt;Win32_Service&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Now use the &lt;b&gt;Get-WmiObject&lt;/b&gt; cmdlet to query that WMI class,&amp;rdquo; I said.&lt;/p&gt;
&lt;p&gt;It did not take her long to modify her command line to query the &lt;b&gt;Win32_Service WMI&lt;/b&gt; class. Here is the command she composed.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WmiObject Win32_Service&lt;/p&gt;
&lt;p&gt;The command and the associated results are shown in the image that follows.&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/6011.hsg_2D00_2_2D00_15_2D00_12_2D00_04.png"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/6011.hsg_2D00_2_2D00_15_2D00_12_2D00_04.png" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;OK, so where are the service accounts?&amp;rdquo; she asked.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Remember, you need to use the same technique that you used with the &lt;b&gt;Get-Service&lt;/b&gt; cmdlet to retrieve all the information,&amp;rdquo; I said.&lt;/p&gt;
&lt;p&gt;She thought for a bit, then pressed the Up arrow to retrieve the previous command. Then she added a pipeline character and the &lt;b&gt;Format-List&lt;/b&gt; cmdlet. The revised command is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WmiObject win32_service | format-list *&lt;/p&gt;
&lt;p&gt;The command and its associated output are shown in the image that follows.&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/6683.hsg_2D00_2_2D00_15_2D00_12_2D00_05.png"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/6683.hsg_2D00_2_2D00_15_2D00_12_2D00_05.png" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;So where is the service account name?&amp;rdquo; she asked.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Look closely at the output. See where it says &lt;i&gt;StartName&lt;/i&gt;? That is the service account. See where it says &lt;i&gt;StartMode&lt;/i&gt;? That is the way the service starts,&amp;rdquo; I said, &amp;ldquo;Why don&amp;rsquo;t you create a table with just the &lt;i&gt;Name&lt;/i&gt;, &lt;i&gt;StartName&lt;/i&gt;, and &lt;i&gt;StartMode&lt;/i&gt;.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;This time the Scripting Wife did not hesitate. She first cleared the screen, then used the Up arrow to retrieve the previous command. She then edited it by changing it to a &lt;b&gt;Format-Table&lt;/b&gt; command. The command that she arrived at is shown here with its associated output.&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/4666.hsg_2D00_2_2D00_15_2D00_12_2D00_06.png"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/4666.hsg_2D00_2_2D00_15_2D00_12_2D00_06.png" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;That&amp;rsquo;s cool,&amp;rdquo; she said.&lt;/p&gt;
&lt;p&gt;And with that, she was gone. Just in time for the &lt;i&gt;Andante &lt;/i&gt;movement in D-major. Brahms may not have had Windows PowerShell in mind when he wrote, but somehow it seems to fit.&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=3480247" width="1" height="1" alt="" /&gt;</description></item><item><title>Speed Up Excel Automation with PowerShell</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2012/02/01/speed-up-excel-automation-with-powershell.aspx</link><pubDate>Wed, 01 Feb 2012 06:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:14302</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;: Microsoft PFE, Georges Maheu, optimizes the Windows PowerShell script he presented yesterday.&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. Our guest blogger today is Georges Maheu. Georges presented a script &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/31/beat-the-auditors-be-one-step-ahead-with-powershell.aspx" target="_blank"&gt;yesterday &lt;/a&gt;to gather Windows services information in an Excel spreadsheet. Although the script did an adequate job for a small number of computers, it does not scale well for hundreds of computers.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Note&lt;/b&gt;: All of the files from today, in addition to files for the entire week are in a zip file in the &lt;a href="http://gallery.technet.microsoft.com/scriptcenter/Get-on-thousands-of-ef3175c7" target="_blank"&gt;Script Repository&lt;/a&gt;.&amp;nbsp;Georges&amp;rsquo; team blog can be found at PFE Blog&amp;nbsp;&lt;a href="http://www.opsvault.com/" target="_blank"&gt;OpsVault&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Take it away Georges...&lt;/p&gt;
&lt;p&gt;Today, we look at scaling up yesterday&amp;rsquo;s script. As seen, the script makes an inventory of all services running on your servers and identifies those that are using non-standard accounts. The inventory is presented in an Excel spreadsheet.&lt;/p&gt;
&lt;p&gt;The first version of the script was linear and simple but somewhat slow; it works well for a small to mid-size environment, but it does not scale well for larger environments.&lt;/p&gt;
&lt;p&gt;When doing security assessments, most of the time, only a subset of computers is considered. The objective of an assessment is to locate a few examples of items to correct, not to make a complete inventory. However, when doing remediation planning, a complete inventory is required to evaluate the potential impact of applying modifications to the environment. The script presented yesterday is fine for doing assessments or complete inventory of smaller environments. To make a complete inventory of a larger environment, the script performance needs to be optimized.&lt;/p&gt;
&lt;p&gt;Unfortunately, I am not aware of profiler tools for Windows PowerShell. A profiler is a tool that enables you to compute the time spent in each line of code when running a script. There are other ways of estimating where most of your script spends its time. One of them is to create your own timers and track time at various locations.&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/5700.hsg_2D00_2_2D00_1_2D00_12_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/5700.hsg_2D00_2_2D00_1_2D00_12_2D00_1.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Another option is to use the &lt;b&gt;Measure-Command&lt;/b&gt; cmdlet.&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/0728.hsg_2D00_2_2D00_1_2D00_12_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/0728.hsg_2D00_2_2D00_1_2D00_12_2D00_2.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After you instrument the original script, the following statistics are generated:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;WMI query: ~ 0.25 seconds for responding local computer&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;WMI query: ~ 1.00 seconds for responding remote computer&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;WMI query: ~ 20.00 seconds for non-responding computer&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Ping dead computer:&amp;nbsp;&amp;nbsp;&amp;nbsp; ~2.5 seconds&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Writing sheet headers: ~ 1.5 seconds&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Writing sheet data:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ~ 120 seconds&lt;/p&gt;
&lt;p&gt;The two main pain points are making a WMI query on a non-responding , which takes about 20 seconds, and writing the data to Excel. If the target computers are servers, these should be few and far apart. However, if these are workstations, investing more time may be needed to address the non-responding computer issues.&lt;/p&gt;
&lt;p&gt;In any case, the big gain is obviously with writing data to Excel. After doing some research, the fastest way to write to Excel seems to be to write a range of data rather than writing it cell by cell. Several techniques could be used to achieve this data transfer. Let&amp;rsquo;s explore two of them&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;First method: CSV files&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The result of the WMI query can be &lt;a href="http://gallery.technet.microsoft.com/scriptcenter/7c56c444-2476-4625-b1d9-821f30280e44/" target="_blank"&gt;exported into a CSV file&lt;/a&gt; with the &lt;b&gt;Export-CSV&lt;/b&gt; cmdlet, and then read directly from Excel with the &lt;b&gt;$excel.workbooks.open() &lt;/b&gt;method. Although this looks simple, there is some gymnastics and plumbing involved to get this working. We will look into this further later this week.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Second method: Clipboard&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The result of the WMI query can be copied to the clipboard and then pasted into each spreadsheet. This method also avoids having to write the spreadsheet header.&lt;/p&gt;
&lt;p&gt;The first step is to load the clipboard class:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Add-Type -Assembly PresentationCore&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Warning&lt;/b&gt;: The &lt;b&gt;PresentationCore&lt;/b&gt; class is pretty fussy about its housing. It needs to know in which state its apartment is!&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;if ($host.Runspace.ApartmentState -notlike &amp;quot;STA&amp;quot;)&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; powershell -STA -file $myInvocation.myCommand.definition&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;Then the original code is modified with the following lines:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$services = Get-WmiObject win32_service `&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;nbsp; -ComputerName $computerName&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;if (($error.count -eq 0))&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; $data = ($services `&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&amp;nbsp; $properties `&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; | ConvertTo-Csv -Delimiter &amp;quot;`t&amp;quot; -NoTypeInformation) `&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 &amp;quot;`r`n&amp;quot;&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;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Windows.Clipboard]::setText($data)&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; #Const xlPasteAll = -4104&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $computerSheet.range(&amp;#39;a1&amp;#39;).pasteSpecial(-4104)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Windows.Clipboard]::setText(&amp;rdquo;&amp;rdquo;) #clear the buffer&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $computerSheet.usedRange.entireColumn.autoFit() `&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; | Out-Null&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;. . .&lt;/p&gt;
&lt;p&gt;The WMI query is the same as before. The new element is the &lt;b&gt;$data&lt;/b&gt; transformation. This step is required to allow pasting the services data to an appropriate format for Excel. If &lt;b&gt;$services&lt;/b&gt; is pasted directly as follows:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;[Windows.Clipboard]::setText($services)&lt;/p&gt;
&lt;p&gt;Only partial data is copied and not parsed into columns. Excel understands the CSV format; therefore, the &lt;b&gt;$service&lt;/b&gt; data is converted into the CSV format with the &lt;b&gt;ConvertTo-CSV&lt;/b&gt; cmdlet. The CSV data is then converted into one big string with the &lt;b&gt;&amp;ndash;join&lt;/b&gt; method. Et voil&amp;agrave;, the script is done. Well almost&amp;hellip;&lt;/p&gt;
&lt;p&gt;The static method &lt;b&gt;SetText&lt;/b&gt; from the &lt;b&gt;Windows.Clipboard&lt;/b&gt; class is used to copy data to the clipboard and then the office automation &lt;b&gt;PasteSpecial &lt;/b&gt;method is used to paste it into Excel.&lt;/p&gt;
&lt;p&gt;A neat trick that my good friend, &lt;a href="http://blogs.technet.com/b/heyscriptingguy/" target="_blank"&gt;Ed Wilson&lt;/a&gt;, showed me some time ago is how to find static methods with the &lt;b&gt;Get-Member&lt;/b&gt; cmdlet. If &lt;b&gt;[Windows.Clipboard]&lt;/b&gt; is sent to &lt;b&gt;get-member&lt;/b&gt;, only a subset of the methods available is obtained. But if the &lt;i&gt;Static&lt;/i&gt; parameter is used; the following additional methods will be displayed:&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/1374.hsg_2D00_2_2D00_1_2D00_12_2D00_3.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1374.hsg_2D00_2_2D00_1_2D00_12_2D00_3.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The &lt;b&gt;Select-Object&lt;/b&gt; cmdlet is used to change the order in which the columns are output. If you remember, in the original script, variables like &lt;b&gt;$columnCaption&lt;/b&gt; were used to determine column position.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$computerSheet.cells.item($row,$columnCaption) = $service.Caption&lt;/p&gt;
&lt;p&gt;In this script, an array combined with the &lt;b&gt;Select-Object&lt;/b&gt; cmdlet is used. Thereby, another modification has to be made:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$properties = `&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;Name&amp;quot;,&lt;b&gt;`&lt;/b&gt;&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;StartName&amp;quot;,&lt;b&gt;`&lt;/b&gt;&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; #removed some properties for brevity&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;WaitHint&amp;quot;&lt;/p&gt;
&lt;p&gt;Using an array this way avoids printing the headers as needed in the previous version of the script. To change the column order, simply change the order of the properties in the array.&lt;/p&gt;
&lt;p&gt;As you may recall, a test run in my home lab gathered data from 50 computers in 90 minutes with the original script. This new and improved version does the same 50 computers in less than three minutes, and it is 43 lines shorter!!&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/1104.hsg_2D00_2_2D00_1_2D00_12_2D00_4.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1104.hsg_2D00_2_2D00_1_2D00_12_2D00_4.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But wait, there is more&amp;hellip;&lt;/p&gt;
&lt;p&gt;The next challenge will be to scale this script from 50 servers to thousands of servers. Tomorrow, we will explore how we can again dramatically improve the performance of this script from three minutes down to 45 seconds by leveraging some Windows PowerShell&amp;nbsp;2.0 features.&lt;/p&gt;
&lt;p&gt;~ Georges&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Once again, thank you, Georges, for sharing with us today. The zip file you will find in the&amp;nbsp;&lt;a href="http://gallery.technet.microsoft.com/scriptcenter/Get-on-thousands-of-ef3175c7" target="_blank"&gt;Script Repository&lt;/a&gt;&amp;nbsp;has all the files and scripts from Georges this week.&amp;nbsp;Please join us tomorrow for Part 3 in the series.&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;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3476100" width="1" height="1" alt="" /&gt;</description></item><item><title>Beat the Auditors, Be One Step Ahead with PowerShell</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2012/01/31/beat-the-auditors-be-one-step-ahead-with-powershell.aspx</link><pubDate>Tue, 31 Jan 2012 06:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:14262</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;: Microsoft PFE, Georges Maheu, opens his security assessment toolbox to discuss a Windows PowerShell script he uses to look at Windows services.&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. Our guest blogger today is &lt;a href="http://blogs.technet.com/search/searchresults.aspx?q=georges&amp;amp;sections=7618"&gt;Georges Maheu&lt;/a&gt;. Georges is one of my best friends, and I had a chance to work with him again during my recent Canadian tour. While I was there, I asked him about writing a guest series, and we are fortunate that he did (you will love his four blogs). Here is a little byte about Georges.&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/5282.hsg_2D00_1_2D00_31_2D00_12_2D00_1.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/150x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/5282.hsg_2D00_1_2D00_31_2D00_12_2D00_1.jpg" alt="Photo of Georges Maheu" title="Photo of Georges Maheu" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Georges Maheu, CISSP, is a &lt;a href="http://www.opsvault.com/dedicated-support-engineers-what-they-are-and-how-they-can-help-you/" target="_blank"&gt;premier field engineer&lt;/a&gt; (PFE) and security technology lead for Microsoft Canada. As a senior PFE, he focuses on delegation of authority (how many domain admins do you really have?), on server hardening, and on using his scripts to perform security assessments. Georges has a passion for Windows PowerShell and WMI, and he uses them on a regular basis to gather information from Active Directory and computers. Georges also delivers popular scripting workshops to &lt;a href="http://www.microsoft.com/microsoftservices/en/us/support_premier.aspx" target="_blank"&gt;Microsoft Services Premier Support&lt;/a&gt; customers. Georges is a regular contributor to the Microsoft PFE blog, &lt;a href="http://www.opsvault.com/" target="_blank"&gt;OpsVault&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Note: All the scripts and associated files for this blog series can be found in the &lt;a href="http://gallery.technet.microsoft.com/scriptcenter/Get-on-thousands-of-ef3175c7" target="_blank"&gt;Script Repository&lt;/a&gt;. Remember to &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2011/04/02/scripting-wife-learns-about-unblocking-files-in-powershell.aspx" target="_blank"&gt;unblock&lt;/a&gt; and open the zip file.&lt;/p&gt;
&lt;p&gt;Take it away, Georges&amp;hellip;&lt;/p&gt;
&lt;p&gt;When premier customers call me, it is either because they have been compromised or because they are being audited. In either case, the first step is always the same: make an inventory. To assess risk, you need to understand what you are managing. Many customers have fancy gizmos to detect intrusion, but they often fail to look at the most simple things.&lt;/p&gt;
&lt;p&gt;Hey, if the barn doors are wide open, why look for mice holes!&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/2705.hsg_2D00_1_2D00_31_2D00_12_2D00_2.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/450x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/2705.hsg_2D00_1_2D00_31_2D00_12_2D00_2.jpg" alt="Image of barn" title="Image of barn" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So, what does all of this have to do with auditors? Well, auditors (read accountants) have investigated hundreds of attacks and concluded that several of them were done by using generic accounts as penetration vectors. Therefore, being accountants (read very organized); some auditors are now assessing generic accounts as part of their auditing.&lt;/p&gt;
&lt;p&gt;Here is a common scenario: An IT Pro created a generic account in 1999 to perform backups. Back then, the backup software required this service account to be a domain admin account. The password policy was six characters without complexity. Today, the account is still active; the password has never been changed.&lt;/p&gt;
&lt;p&gt;Auditors come along and provide you with a list of accounts with &amp;ldquo;no password required&amp;rdquo; and a list of accounts with obsolete passwords. Your manager tells you to investigate where these accounts are being used and wants you to create a remediation plan to change the passwords on these accounts.&lt;/p&gt;
&lt;p&gt;Generic accounts can be used by people (guest and administrator are two examples), used by applications, or used to run services. My security tool box contains several small scripts, an approach that I prefer to a Swiss army tool that tries to do everything.&lt;/p&gt;
&lt;p&gt;Today, we will look at one of my tool box scripts. This script will make an inventory of all services running on your computers and will identify which ones are using non-standard service accounts. The inventory is presented in an Excel spreadsheet (accountants and managers love spreadsheets, so this is a bonus).&lt;/p&gt;
&lt;p&gt;When you write scripts, always consider two factors: complexity and capacity (or performance). This first version of the script is linear and simple, but slow; it will do the work for a small to mid-size environment. Depending on your environment, it may take up to 15 minutes per server.&lt;/p&gt;
&lt;p&gt;The first step is to read the list of targeted computers. You could get this list directly from Active Directory, but most people prefer to have control over the computers that are being queried. In any case, a simple Windows PowerShell command can be used to create such a list:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;([adsisearcher]&amp;quot;objectCategory=computer&amp;quot;).findall() |&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp; foreach-object {([adsi]$_.path).cn} |&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp; out-file -Encoding ascii -FilePath computerList.txt&lt;/p&gt;
&lt;p&gt;Check the results with:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;get-content computerList.txt&lt;/p&gt;
&lt;p&gt;Now that a list of computers has been created, let&amp;rsquo;s open the tool box and look at portions of this first version script. Not always knowing where the script is run from, the path is stored programmatically in the &lt;b&gt;$scriptPath&lt;/b&gt; variable instead of being hard-coded. Because performance is important, time is also tracked.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;clear-host&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$startTime = Get-Date&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$scriptPath = Split-Path &lt;i&gt;-parent&lt;/i&gt; $myInvocation.myCommand.definition&lt;/p&gt;
&lt;p&gt;Creating an Excel spreadsheet is done with office automation. The &lt;b&gt;DisplayAlert&lt;/b&gt; property is set to $false to avoid the file-overwriting prompt when the file is saved at the end of the script. If the &lt;b&gt;Visible&lt;/b&gt; property is set to $true, make sure not to click inside an Excel spreadsheet while the script is running because this will change the focus and generate a Windows PowerShell error.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$excel = New-Object &lt;i&gt;-comObject&lt;/i&gt; excel.application&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$excel.visible = $true # or = $false&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$excel.displayAlerts = $false&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$workBook = $excel.workbooks.add()&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s move on by initializing our environment. The computer list is stored in an array automatically with the &lt;b&gt;Get-Content&lt;/b&gt; cmdlet, as shown here:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$computers = Get-Content &amp;quot;$scriptPath\Computers.txt&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$respondingComputers = 0 #Keep count of responding computers.&lt;/p&gt;
&lt;p&gt;The properties returned by a WMI query are not necessarily in the desired order. To simplify the layout, variables that will be used to define the columns for the data in Excel are initialized here. Notice the service &lt;b&gt;Name&lt;/b&gt; and &lt;b&gt;StartName&lt;/b&gt; are in the first two columns. The presentation order can be rearranged based on specific requirements.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$mainHeaderRow = 3&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$firstDataRow = 4&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$columnName = 01&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$columnStartName = 02&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$columnDisplayName = 03&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#removed some properties for brevity.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$columnSystemName = 24&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$columnTagId = 25&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$columnTotalSessions = 26&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$columnWaitHint = 27&lt;/p&gt;
&lt;p&gt;Names are then given to individual Excel spreadsheets and headers are added. The first sheet is used to keep statistics; the second one is really the core component of this report where all the exceptions will be recorded. These will be the accounts that the auditors will want you to manage.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$workBook.workSheets.item(1).name = &amp;quot;Info&amp;quot;&amp;nbsp; #Sheets index start at 1.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$workBook.workSheets.item(2).name = &amp;quot;Exceptions&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Delete the last sheet as there will be an extra one.&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$workBook.workSheets.item(3).delete()&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$infoSheet = $workBook.workSheets.item(&amp;quot;Info&amp;quot;)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$infoSheet.cells.item(1,1).value2 = &amp;quot;Nb of computers:&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$infoSheet.cells.item(1,2).value2 = $($computers).count&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$infoSheet.cells.item(1,2).horizontalAlignment = -4131 #$xlLeft&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$exceptionsSheet = $workBook.workSheets.item(&amp;quot;Exceptions&amp;quot;)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$exceptionsSheet.cells.item($mainHeaderRow,1) = &amp;quot;SystemName&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$exceptionsSheet.cells.item($mainHeaderRow,2) = &amp;quot;DisplayName&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$exceptionsSheet.cells.item($mainHeaderRow,3) = &amp;quot;StartName&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$exceptionsSheet.cells.item($mainHeaderRow,1).entireRow.font.bold = $true&lt;/p&gt;
&lt;p&gt;A nice trick-of-the-trade is to write a message that might get overwritten. In this case, if data is found, this line gets overwritten by the data.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#The next line will be overwritten if exceptions are found.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$exceptionsSheet.cells.item($firstDataRow,1) = &amp;quot;No exceptions found&amp;quot;&lt;/p&gt;
&lt;p&gt;The script can now start to process each computer. A new Excel tab is created for each computer and renamed with the computer name, a header is written, WMI is used to get the data, and the data is written to the Excel spreadsheet. Notice that the current spreadsheet is selected with &lt;b&gt;$computerSheet.select()&lt;/b&gt;. This is not required, but it will show some activity on the screen. Again, do not click in the spreadsheet because this will change the selected cell and generate an error.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;forEach ($computerName in $computers)&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; $computerName = $computerName.trim()&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $workBook.workSheets.add() | Out-Null&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Creating sheet for $computerName&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $workBook.workSheets.item(1).name = $computerName&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $computerSheet = $workBook.workSheets.item($computerName)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $computerSheet.select() #Show some activity on screen.&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; $error.Clear()&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $services = Get-WmiObject win32_service &lt;i&gt;-ComputerName&lt;/i&gt; $computerName&lt;/p&gt;
&lt;p&gt;The script performs very basic error handling. If no errors are found by the WMI query, data is written to the spreadsheet; otherwise, the error is logged in a text file. The order in which the data is written is irrelevant because variables are used to indicate in which column each field is being written.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (($error.count -eq 0))&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; Write-Host &amp;quot;Computer $computerName is responding.&amp;quot; &lt;i&gt;-ForegroundColor&lt;/i&gt; Green&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $row = $firstDataRow&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #Write headers&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $computerSheet.cells.item($mainHeaderRow,$columnCaption) = &amp;quot;Caption&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #removed some properties for brevity.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $computerSheet.cells.item($mainHeaderRow,$columnWaitHint) = &amp;quot;WaitHint&amp;quot;&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; $computerSheet.cells.item($mainHeaderRow,1).entireRow.font.bold = $true&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; forEach ($service in $services)&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; $service.displayName&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; $computerSheet.cells.item($row,$columnAcceptStop) = $service.AcceptStop&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; $computerSheet.cells.item($row,$columnCaption) = $service.Caption&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; $computerSheet.cells.item($row,$columnCheckPoint) = $service.CheckPoint&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; #removed some properties for brevity.&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;$computerSheet.cells.item($row,$columnWaitHint) = $service.WaitHint&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;&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; $row++&lt;/p&gt;
&lt;p&gt;The following section is where the crucial action occurs. The non-generic service accounts are identified here. This is done with an &lt;b&gt;if &lt;/b&gt;statement and by writing the exceptions to the exception sheet.&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # EXCEPTION SECTION&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; # To be customized based on your criteria&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;if (&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $service.startName -notmatch &amp;quot;LocalService&amp;quot; `&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; -and $service.startName -notmatch &amp;quot;Local Service&amp;quot; `&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; -and $service.startName -notmatch &amp;quot;NetworkService&amp;quot; `&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; -and $service.startName -notmatch &amp;quot;Network Service&amp;quot; `&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; -and $service.startName -notmatch &amp;quot;LocalSystem&amp;quot; `&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; -and $service.startName -notmatch &amp;quot;Local System&amp;quot;)&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; {&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; $exceptionsSheet.cells.item($exceptionRow,1) = $service.systemName&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;$exceptionsSheet.cells.item($exceptionRow,2) = $service.displayName&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; $exceptionsSheet.cells.item($exceptionRow,3) = $service.startName&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; $exceptionRow++&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; } #if ($service.startName&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; } #forEach ($service in $services)&lt;/p&gt;
&lt;p&gt;Then, the current spreadsheet is formatted and the responding computer counter is incremented. &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; $computerSheet.usedRange.entireColumn.autoFit() | Out-Null&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $respondingComputers++&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&gt;If the remote computer does not respond, a comment is added to the spreadsheet and additional information is provided in a log file.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else #if (($error.count -eq 0))&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; $computerSheet.cells.item($firstDataRow,1) = &amp;quot;Computer $computerName did not respond to WMI query.&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $computerSheet.cells.item($firstDataRow+1,1) = &amp;quot;See $($scriptPath)\Unresponsive computers for additional information&amp;quot;&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; $error.Clear()&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Test-Connection &lt;i&gt;-ComputerName&lt;/i&gt; $computerName &lt;i&gt;-Verbose&lt;/i&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Add-Content &lt;i&gt;-Path&lt;/i&gt; &amp;quot;$($scriptPath)\Unresponsive computers&amp;quot; &lt;i&gt;-Encoding&lt;/i&gt; Ascii `&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;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; -&lt;i&gt;Value&lt;/i&gt; &amp;quot;$computerName did not respond to win32_pingStatus&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Add-Content &lt;i&gt;-Path&lt;/i&gt; &amp;quot;$($scriptPath)\Unresponsive computers&amp;quot; &lt;i&gt;-Encoding&lt;/i&gt; Ascii `&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;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; -&lt;i&gt;Value&lt;/i&gt; $error[0]&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Add-Content &lt;i&gt;-Path&lt;/i&gt; &amp;quot;$($scriptPath)\Unresponsive computers&amp;quot; &lt;i&gt;-Encoding&lt;/i&gt; Ascii `&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;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; -&lt;i&gt;Value&lt;/i&gt; &amp;quot;----------------------------------------------------&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write-Host &amp;quot;Computer $computerName is not responding. Moving to next computer in the list.&amp;quot; `&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;i&gt;-ForegroundColor&lt;/i&gt; red&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } #if (($error.count -eq 0))&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } #forEach computer&lt;/p&gt;
&lt;p&gt;At this point, the script is almost done. The information sheet needs to be updated with our stats, and a few things need to be formatted and cleaned up before exiting.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$exceptionsSheet.usedRange.entireColumn.autoFit() | Out-Null&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$infoSheet.cells.item(2,1).value2 = &amp;quot;Nb of responding computers:&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$infoSheet.cells.item(2,2).value2 = $respondingComputers&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$infoSheet.cells.item(2,2).horizontalAlignment = -4131 #$xlLeft&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$infoSheet.usedRange.entireColumn.autoFit() | Out-Null&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$workBook.saveAs(&amp;quot;$($scriptPath)\services.xlsx&amp;quot;)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$workBook.close() | Out-Null&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$excel.quit()&lt;/p&gt;
&lt;p&gt;Com objects require special attention; otherwise, they remain in memory and do not release the calling program. Some coders keep track of all the objects that they create, and release them one by one. I prefer to use a generic approach such as:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Remove all com related variables&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-Variable &lt;i&gt;-Scope&lt;/i&gt; script `&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; | Where-Object {$_.Value.pstypenames -contains &amp;#39;System.__ComObject&amp;#39;} `&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; | Remove-Variable &lt;i&gt;-Verbose&lt;/i&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;[GC]::Collect() #.net garbage collection&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;[GC]::WaitForPendingFinalizers() #more .net garbage collection&lt;/p&gt;
&lt;p&gt;Now that the script is done, let us see how long it takes to run. I always do benchmarks with a limited number of computers, and then estimate how long it will take to gather data from all the targeted computers.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$endTime = get-date&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;&amp;quot; #blank line&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-Host &amp;quot;-------------------------------------------------&amp;quot; &lt;i&gt;-ForegroundColor&lt;/i&gt; Green&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-Host &amp;quot;Script started at:&amp;nbsp;&amp;nbsp; $startTime&amp;quot; -&lt;i&gt;ForegroundColor&lt;/i&gt; Green&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-Host &amp;quot;Script completed at: $endTime&amp;quot; -&lt;i&gt;ForegroundColor&lt;/i&gt; Green&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-Host &amp;quot;Script took $($endTime - $startTime)&amp;quot; -&lt;i&gt;ForegroundColor&lt;/i&gt; Green&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-Host &amp;quot;-------------------------------------------------&amp;quot; &lt;i&gt;-ForegroundColor&lt;/i&gt; Green&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;&amp;quot; #blank line&lt;/p&gt;
&lt;p&gt;A test run in my home lab gathered data from 50 computers in 90 minutes. That is less than two minutes per computer. Not bad, considering we have a nice Excel spreadsheet as a final report.&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/5861.hsg_2D00_1_2D00_31_2D00_12_2D00_3.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/5861.hsg_2D00_1_2D00_31_2D00_12_2D00_3.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Having an inventory is the first step in closing one of the barn doors.&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/1538.hsg_2D00_1_2D00_31_2D00_12_2D00_4.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/450x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1538.hsg_2D00_1_2D00_31_2D00_12_2D00_4.jpg" alt="Image of barn" title="Image of barn" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The next screen capture shows all the services that are using nonstandard service accounts.&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/4341.hsg_2D00_1_2D00_31_2D00_12_2D00_5.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/4341.hsg_2D00_1_2D00_31_2D00_12_2D00_5.jpg" alt="Image of spreadsheet" title="Image of spreadsheet" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This information helps to evaluate the impact of changing the password on the SRVAccount and BobTheGreat before the auditors start asking. This is also a good opportunity to determine if that xyz service really needs to run as Administrator.&lt;/p&gt;
&lt;p&gt;I ran this script in some customer environments where it took more than 15 minutes per computer. This could be a serious limiting factor. Tomorrow, we will explore how the performance of this script can be dramatically improved from 90 minutes to less than three minutes.&lt;/p&gt;
&lt;p&gt;Remember, all the scripts and files for this and for the next three blogs in the series can be found in the &lt;a href="http://gallery.technet.microsoft.com/scriptcenter/Get-on-thousands-of-ef3175c7" target="_blank"&gt;Script Repository&lt;/a&gt;. Simply open the zip file.&lt;/p&gt;
&lt;p&gt;~Georges&lt;/p&gt;
&lt;p&gt;Thank you, Georges, for the first installment of an awesome week of Windows PowerShell goodness.&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;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3475906" width="1" height="1" alt="" /&gt;</description></item><item><title>PowerShell Community and the Windows System Administration Tool</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2012/01/06/powershell-community-and-the-windows-system-administration-tool.aspx</link><pubDate>Fri, 06 Jan 2012 06:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:13902</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;: See how guest blogger, Rich Prescott, leveraged the Windows PowerShell community as he built his popular ArPosh Client System Administration tool.&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. We are really starting the new year off correctly. We have another very strong guest blogger today. Rich Prescott, is currently working as an infrastructure architect and Windows engineer at a large media company, with his main areas of focus on automation and Active Directory.&amp;nbsp;The automation responsibilities allow him to work with a wide-range of technologies including virtualization, storage, and monitoring.&amp;nbsp;He started learning Windows PowerShell in 2009 while he was working as a desktop engineer, and he is the lead scripting guy for his organization.&amp;nbsp;He is also a moderator on the &lt;a href="http://social.technet.microsoft.com/Forums/en-US/ITCG/threads" target="_blank"&gt;Official Scripting Guys Forum&lt;/a&gt;&lt;span style="text-decoration:underline;"&gt;,&lt;/span&gt; and was recently rewarded as a Microsoft Community Contributor.&lt;/p&gt;
&lt;p&gt;Blog: &lt;a href="http://blogs.technet.com/controlpanel/blogs/posteditor.aspx/blog.RichPrescott.com"&gt;Engineering Efficiency: Scripts, Tools, and Software New in the IT World&lt;/a&gt;&amp;nbsp;&lt;br /&gt; Twitter: &lt;a href="http://mce_host/controlpanel/blogs/posteditor.aspx/@Rich_Prescott"&gt;@Rich_Prescott&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Take it away Rich&amp;hellip;&lt;/p&gt;
&lt;p&gt;When I first joined the IT world, I was working at the Help desk for a large company. Being new to IT and troubleshooting, I always wondered why there was no single tool for troubleshooting remote computers. I would receive a call about a computer being slow, and I would have to go through four tools to try to diagnose the issue. I began searching for an easy solution, and that is when a coworker introduced me to Windows PowerShell. After reading blog posts from &lt;a href="http://www.scriptingguys.com/blog" target="_blank"&gt;Hey, Scripting Guy!&lt;/a&gt; and the &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/tags/scripting+wife/" target="_blank"&gt;Scripting Wife&lt;/a&gt;, I was writing basic scripts to gather the information that I needed for troubleshooting. This is an example of a basic script I wrote back then.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$PC = &amp;ldquo;PC01&amp;rdquo;&lt;br /&gt; Get-WmiObject Win32_OperatingSystem &amp;ndash;ComputerName $PC&lt;br /&gt; Get-WmiObject Win32_StartupCommand &amp;ndash;ComputerName $PC&lt;br /&gt; Get-WmiObject Win32_Process &amp;ndash;ComputerName $PC&lt;/p&gt;
&lt;p&gt;After the underlying issue was targeted, I needed a way to remediate the issue, such as removing a hung process. This was possible remotely by querying the Win32_Process class on a remote computer, filtering for the process that was causing an issue, and invoking the &lt;b&gt;Terminate&lt;/b&gt; method. Here is an example of using the &lt;b&gt;Terminate&lt;/b&gt; method to stop a process on a remote computer.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;(Get-WmiObject Win32_Process &amp;ndash;ComputerName $PC |&lt;br /&gt; Where-Object {$_.Name &amp;ndash;eq &amp;ldquo;HungProcessName&amp;rdquo;}).Terminate()&lt;/p&gt;
&lt;p&gt;At last, I was able to efficiently troubleshoot issues remotely and even resolve some of them without ever having to leave my desk. As I became more familiar with Windows PowerShell, I thought, &amp;ldquo;Wouldn&amp;rsquo;t it be cool if I could share the efficacy of Windows PowerShell with others, even if they don&amp;rsquo;t know any scripting?&amp;rdquo; After a few months of researching, scripting, and testing GUI creation with Windows PowerShell, the &lt;a href="http://gallery.technet.microsoft.com/a5aff367-7b47-4b50-a2ef-20dcb4bb6d64" target="_blank"&gt;Arposh Client System Administration tool&lt;/a&gt; (ACSA) was released.&lt;/p&gt;
&lt;p&gt;As with any technology that you learn rapidly, when you look back on what you were doing a year ago, you think to yourself, &amp;ldquo;What was I thinking when I wrote that? I could write that in half the code and make it twice as fast.&amp;rdquo; So I set out to find resources to help me rebuild the script from scratch, and I used this opportunity to remove some of the prerequisites, make it compatible with servers, and improve the overall user experience.&lt;/p&gt;
&lt;h3&gt;PowerShellGroup - #PowerShell chat room&lt;/h3&gt;
&lt;p&gt;&lt;br /&gt; One of the advantages of using Internet Relay Chat (IRC) is that there are chat rooms for almost any topic you can think of and when you are learning a new technology, having a live discussion can be really helpful. While revamping the ACSA tool, one of the user-experience features that I wanted to add was to give the user the ability to decide which feature sets to use through a configuration file.&lt;/p&gt;
&lt;p&gt;I joined the #PowerShell chat room on &lt;a href="http://powershellgroup.org/virtual/live" target="_blank"&gt;PowerShellGroup.org&lt;/a&gt;, and I asked about an easy way to give users configuration options. Jaykul, a Windows PowerShell MVP, responded with a way to read settings from an XML file. By using the following XML code and three lines of Windows PowerShell, a user is able to set a default domain to connect to when using the GUI. To have the GUI use the current domain of the logged on user, simply update the &lt;b&gt;Enabled&lt;/b&gt; option of the default domain to &amp;ldquo;False&amp;rdquo; in the XML configuration file.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;lt;Domain Default=&amp;quot;LDAP://DC=RU,DC=lab&amp;quot; Enabled=&amp;quot;True&amp;quot;/&amp;gt;&lt;/p&gt;
&lt;p&gt;In the first line of code, we use &lt;b&gt;Get-Content&lt;/b&gt; on the XML configuration file and specify that it is XML code by using [XML]. We then check to see if the default domain option is enabled, and if so, we set the &lt;b&gt;Domain&lt;/b&gt; variable to what is specified in the XML. If the option is disabled, the GUI sets the &lt;b&gt;Domain&lt;/b&gt; variable to the currently logged on domain.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;[XML]$XML = Get-Content &amp;ldquo;AWSA.Options.xml&amp;rdquo;&lt;br /&gt; &amp;nbsp;if($XML.Domain.Enabled &amp;ndash;eq $True){$Domain = $XML.Domain.Default}&lt;br /&gt; &amp;nbsp;else{$Domain = ([DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).Name}&lt;/p&gt;
&lt;h3&gt;TechNet Wiki&lt;/h3&gt;
&lt;p&gt;My next task was to make the GUI easy to use, and this meant removing any unnecessary pre-requisites included in the original release. My first stop was the &lt;a href="http://social.technet.microsoft.com/wiki/" target="_blank"&gt;TechNet Wiki&lt;/a&gt; to find a way to query Active Directory for computers without the need to import a Windows PowerShell module that was not freely available on all systems. After a quick search, I landed on a wiki contribution from Richard Mueller, another MVP, for &lt;a href="http://social.technet.microsoft.com/wiki/contents/articles/5392.aspx" target="_blank"&gt;ADSI searches&lt;/a&gt;, which showed me the syntax necessary to build my custom function.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;function Get-RPADComputer{&lt;br /&gt; &amp;nbsp; if($ComputerName -match &amp;quot;.&amp;quot;){$ComputerName = $ComputerName.Split(&amp;#39;.&amp;#39;)[0]}&lt;br /&gt; &amp;nbsp; $searcher=[adsisearcher]&amp;quot;(&amp;amp;(objectClass=computer)(name=$ComputerName*))&amp;quot;&lt;br /&gt; &amp;nbsp; $Properties = $XML.Options.Search.Property&lt;br /&gt; &amp;nbsp; $searcher.PropertiesToLoad.AddRange($Properties) &lt;br /&gt; &amp;nbsp;&amp;nbsp;$searcher.FindAll()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt; &amp;nbsp;}&lt;/p&gt;
&lt;p&gt;This function checks the &lt;i&gt;$ComputerName &lt;/i&gt;parameter that is specified in the textbox of the GUI, and if a fully qualified domain name (FQDN) is specified, it translates it to a short name. It then creates a query that will search for any computers that match the new &lt;i&gt;$ComputerName&lt;/i&gt; variable. The third line reads a list of properties that the user specifies in the XML settings file and adds them to the list of properties to load. The final line of the function executes the query and returns the results.&lt;/p&gt;
&lt;h3&gt;TechNet forums&lt;/h3&gt;
&lt;p&gt;&lt;br /&gt; After adding in the ability to set a default domain when launching the GUI, the user needed a way to change domains without having to edit the XML file and relaunch the script. I was not familiar enough with the ADSI scripting techniques that I found on the TechNet Wiki, and I decided to head over to the &lt;a href="http://social.technet.microsoft.com/Forums/en-us/ITCG/threads" target="_blank"&gt;Official Scripting Guys Forum&lt;/a&gt; on the &lt;a href="http://social.technet.microsoft.com/Forums/en-us/categories/" target="_blank"&gt;TechNet Forums&lt;/a&gt; and ask for some assistance.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://social.technet.microsoft.com/Forums/en-US/ITCG/thread/5ff7b8c0-9c32-44a3-8cc9-8859cd3dc691/" target="_blank"&gt;I posted my question&lt;/a&gt; with some examples of the input and output that I wanted, and within four hours, I received multiple responses from the community. And what do you know&amp;mdash;Richard Mueller again came to the rescue with a way to prompt for a domain and then convert the response into the LDAP path for that domain. By slightly tweaking his code, I was able to add the ability to search alternate domains to my custom Active Directory computer search function.&lt;/p&gt;
&lt;h3&gt;TechNet ScriptCenter&lt;/h3&gt;
&lt;p&gt;&lt;br /&gt; There are many new features in this update of the GUI, but I want to highlight one that many administrators will find very useful and sigh at the mention of: local administrator rights. Every system administrator has received a request along the lines of, &amp;ldquo;I need to install XYZ software right now!&amp;rdquo; or &amp;ldquo;I am using VPN from home, and I need to add a local printer.&amp;rdquo; One way to get around this (not always the best way) is to grant the user temporary local administrator rights. To find out how to do this the Windows PowerShell way, I headed over to the &lt;a href="http://gallery.technet.microsoft.com/scriptcenter/" target="_blank"&gt;TechNet ScriptCenter Repository&lt;/a&gt; to search for some examples.&lt;/p&gt;
&lt;p&gt;Using the &lt;b&gt;Categories&lt;/b&gt; listing in the left pane, I drilled down into &lt;b&gt;Local Account Management&lt;/b&gt;, and I immediately saw what I was looking for: &lt;a href="http://gallery.technet.microsoft.com/scriptcenter/f75801e7-169a-4737-952c-1341abea5823" target="_blank"&gt;Local User Management Module&lt;/a&gt;. I clicked through to the details page and looked through the included functions. I was in luck! By using ADSI code in the &lt;b&gt;Set-LocalGroup&lt;/b&gt; function, I morphed it into my own function as shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;Function Add-LocalAdmin {&lt;br /&gt; &amp;nbsp;&amp;nbsp;[System.Reflection.Assembly]::LoadWithPartialName(&amp;#39;Microsoft.VisualBasic&amp;#39;) | Out-Null&lt;br /&gt; &amp;nbsp;&amp;nbsp;$Input = [Microsoft.VisualBasic.Interaction]::InputBox(&amp;quot;Enter a username to add (Domain\Username)&amp;quot;, &amp;quot;Add Local Admin&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt; &amp;nbsp;&amp;nbsp;$Group = [ADSI](&amp;quot;WinNT://&amp;quot; + $ComputerName + &amp;quot;/Administrators, group&amp;quot;)&lt;br /&gt; &amp;nbsp;&amp;nbsp;$Group.Add(&amp;quot;WinNT://&amp;quot; +$Input.Replace(&amp;lsquo;\&amp;rsquo;,&amp;rsquo;/&amp;rsquo;)&lt;br /&gt; &amp;nbsp;}&lt;/p&gt;
&lt;p&gt;The first line of the function loads the Visual Basic assembly; this allows me to create a custom input box, which prompts the user for the username to add to the local administrators group and then stores it in the &lt;b&gt;$Input&lt;/b&gt; variable. The function then binds to the Administrators group on the remote computer using ADSI. Now we call the &lt;b&gt;Add&lt;/b&gt; method of ADSI to add the desired user account to the administrators group. But there is a snag, the username is specified as Domain\Username, whereas ADSI requires a forward slash. To get around this, we use the &lt;b&gt;Replace&lt;/b&gt; method to turn the back slash into a forward slash.&lt;/p&gt;
&lt;h3&gt;Arposh Windows System Administration tool&lt;/h3&gt;
&lt;p&gt;&lt;br /&gt; Whether you are new to Windows PowerShell and only need a simple script to get you going or you are a Windows PowerShell guru and need a nudge in the right direction, there are numerous resources for everyone. Thanks to all of these resources, I was able to take a simple GUI that I created for myself to make tasks easier and improve it enough to where the Windows PowerShell community would also find it useful. Without further ado, here is the &lt;a href="http://gallery.technet.microsoft.com/Arposh-Windows-System-a1beb102" target="_blank"&gt;Arposh Windows System Administration tool&lt;/a&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/3666.hsg_2D00_1_2D00_6_2D00_12_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/3666.hsg_2D00_1_2D00_6_2D00_12_2D00_1.jpg" alt="Image of Arposh" title="Image of Arposh" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;~Rich&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=3473467" width="1" height="1" alt="" /&gt;</description></item><item><title>Use a PowerShell Script to Start Non-Running Automatic Services</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2011/12/12/use-a-powershell-script-to-start-non-running-automatic-services.aspx</link><pubDate>Mon, 12 Dec 2011 06:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:13598</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;: Guest blogger, Karl Mitschke, discusses a Windows PowerShell script to start non-running services that are set to start automatically.&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. Our guest blogger today is Karl Mitschke, one of the authors of the &lt;a href="http://www.amazon.com/Windows-PowerShell-2-0-Bible-Thomas/dp/1118021983" target="_blank"&gt;Windows PowerShell 2.0 Bible&lt;/a&gt;. Here is a little bit about Karl.&lt;/p&gt;
&lt;p&gt;Karl Mitschke is an IT veteran with over 20 years of experience. He has specialized in messaging since the early 1990s. Karl has been automating tasks with script since moving to Microsoft Exchange 5.0, starting with WinBatch. He started using Windows PowerShell in 2007 when he moved to Exchange Server&amp;nbsp;2007. When he&amp;rsquo;s not writing Windows PowerShell scripts, or writing about &amp;nbsp;Windows PowerShell scripts, Karl enjoys spending time with his bride, Sherry, and their two dogs.&lt;br /&gt; Blog: &lt;a href="http://unlockpowershell.wordpress.com/" target="_blank"&gt;Unlock-PowerShell&lt;/a&gt;&lt;br /&gt; &lt;a href="http://www.wiley.com/WileyCDA/WileyTitle/productCd-1118021983.html" target="_blank"&gt;Windows PowerShell 2.0 Bible&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Starting services on remote servers&lt;/h2&gt;
&lt;p&gt;In the &amp;ldquo;Performing Advanced Server Management&amp;rdquo; chapter in the &lt;a href="http://www.amazon.com/Windows-PowerShell-2-0-Bible-Thomas/dp/1118021983" target="_blank"&gt;Windows PowerShell 2.0 Bible&lt;/a&gt;, I presented a script that would start services on remote servers that are set to start automatically and were not started. Due to the constraints of the book, the script was severely limited. That script is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$Computers = &amp;ldquo;FileServer01&amp;rdquo;,&amp;rdquo;FileServer02&amp;rdquo;&lt;br /&gt; $WmiObject = @{&lt;br /&gt; Class = &amp;ldquo;Win32_Service&amp;rdquo;&lt;br /&gt; Filter = &amp;ldquo;StartMode=&amp;rsquo;Auto&amp;rsquo; and State!=&amp;rsquo;Running&amp;rsquo;&amp;rdquo;&lt;br /&gt; }&lt;br /&gt; foreach ($Computer in $Computers)&lt;br /&gt; {&lt;br /&gt; foreach ($Svc in Get-WmiObject @WmiObject -ComputerName $Computer)&lt;br /&gt; {&lt;br /&gt; Write-Host &amp;ldquo;Starting the&amp;rdquo; $Svc.DisplayName &amp;ldquo;service on $Computer&amp;rdquo;&lt;br /&gt; $Svc.StartService() | Out-Null&lt;br /&gt; }&lt;br /&gt; }&lt;/p&gt;
&lt;p&gt;This was fine, but the script could really use some improvement. For one thing, you needed to hard code the server names. In addition, it did not accept credentials, you could not simulate the action, and there was no Help.&lt;/p&gt;
&lt;p&gt;The concept was sound, however, so I decided to extend the script to put it into production at work, where I use it to verify that services are running after performing updates on our Exchange Server infrastructure. Unfortunately, extending the script makes it too long for the book and too long for this blog. The complete script is available in the &lt;a href="http://gallery.technet.microsoft.com/Starts-automatic-on-remote-26ddd199" target="_blank"&gt;Scripting Guys Script Repository&lt;/a&gt;, but I will discuss highlights of the script in this blog post.&lt;/p&gt;
&lt;h2&gt;Extending the script with Help&lt;/h2&gt;
&lt;p&gt;The first several objections are easy to overcome with advanced parameters. The final objection is overcome with comment-based Help. Windows PowerShell even includes a method to add Help. I am referring to the built in &lt;b&gt;Get-Help&lt;/b&gt; cmdlet. In fact, you can potentially get more Help than you will ever need by typing the following script into your Windows PowerShell console:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-Help -Name functions_advanced_parameters&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-Help -Name about_comment_based_help&lt;/p&gt;
&lt;p&gt;The Help about advanced parameters is too verbose to summarize, so I would suggest that you read it and familiarize yourself with the content.&lt;/p&gt;
&lt;p&gt;The Help for comment-based Help shows that for script-based Help, comment-based Help can appear in two locations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;At the beginning of the script file&lt;/b&gt;. Script Help can be preceded in the script only by comments and blank lines. If the first item in the script body (after the Help) is a function declaration, there must be at least two blank lines between the end of the script Help and the function declaration. Otherwise, the Help is interpreted as being Help for the function, not Help for the script.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;At the end of the script file&lt;/b&gt;. If the script is signed, place comment-based Help at the beginning of the script file. The end of the script file is occupied by the signature block.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As I sign the scripts that I use at work, I include comment-based Help at the beginning of the file.&lt;/p&gt;
&lt;p&gt;I also choose to use the comment-block syntax as opposed to using the comment character (#) in front of each line, because I find it to be more readable. An example of the comment-block syntax is shown here.&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;Invoke-StartService - Start all essential services that are not running.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;.DESCRIPTION&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;This script finds services that are set to start automatically, and starts them.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#&amp;gt;&lt;/p&gt;
&lt;p&gt;Therefore, Help is out of the way with the comment-based Help. Next, I tackle the parameters.&lt;/p&gt;
&lt;h2&gt;Adding arguments&lt;/h2&gt;
&lt;p&gt;I wanted to allow the script to accept server names from the command line or from a pipeline, so I used the &lt;b&gt;ValueFromPipeline&lt;/b&gt; argument when I declare the &lt;i&gt;ComputerName&lt;/i&gt; parameter for the script. I also want to allow the script to target multiple computers, so I declared the &lt;i&gt;ComputerName&lt;/i&gt; parameter as an array of strings as shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;[Parameter(&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Position = 0,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;ValueFromPipeline=$true,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Mandatory = $false,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;HelpMessage = &amp;quot;The computer to start services on&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;)]&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;[string[]]$ComputerName = $env:ComputerName&lt;/p&gt;
&lt;p&gt;As you can see, I set the &lt;i&gt;ComputerName &lt;/i&gt;parameter to not be required by using the local computer name if it is not specified. I also set the parameter to be positional&amp;mdash;that means that you do not need to use the name of the parameter as long as the computer name(s) are specified as the first-passed parameter to the script.&lt;/p&gt;
&lt;p&gt;I wanted the script to accept credentials so that I could start my Windows PowerShell session with a non-administrator account. I added the optional parameter &lt;i&gt;Credential&lt;/i&gt; to handle these credentials.&lt;/p&gt;
&lt;p&gt;Finally, I wanted to emulate the WhatIf functionality in so many of my favorite cmdlets, so I added the optional switch parameter &lt;i&gt;WhatIf&lt;/i&gt;.&amp;nbsp;The entire parameter declaration is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;param (&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;[Parameter(&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Position = 0,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;ValueFromPipeline=$true,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Mandatory = $false&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;)]&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;[string[]]$ComputerName = $env:ComputerName,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;[Parameter(&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Position = 1,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Mandatory = $false&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;)]&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$Credential,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;[Parameter(&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Mandatory = $false&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;)]&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;[switch]$WhatIf&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;)&lt;/p&gt;
&lt;h2&gt;Using $PSBoundParameters&lt;/h2&gt;
&lt;p&gt;I wanted to avoid If statements as much as possible, so I take advantage of the automatic variable &lt;b&gt;$PSBoundParameters&lt;/b&gt;, which is a hash table of the parameter names and values that are passed to the script.&lt;/p&gt;
&lt;p&gt;You can pass the &lt;b&gt;$PSBoundParameters&lt;/b&gt; to the &lt;b&gt;Get-WmiObject&lt;/b&gt; cmdlet as a splatted hash table as shown here:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WmiObject -Class Win32_Service @PSBoundParameters&lt;/p&gt;
&lt;p&gt;The parameters &lt;i&gt;ComputerName&lt;/i&gt; and &lt;i&gt;Credential&lt;/i&gt; can be passed directly to the &lt;b&gt;Get-WmiObject&lt;/b&gt; cmdlet. However, that cmdlet does not accept the &lt;i&gt;WhatIf&lt;/i&gt; parameter, if present, which would cause the error message 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/5314.hsg_2D00_12_2D00_12_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/5314.hsg_2D00_12_2D00_12_2D00_11_2D00_1.jpg" alt="Image of error message" title="Image of error message" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This can be resolved by using the &lt;b&gt;Remove()&lt;/b&gt; method of the hash table. You can check for the existence of the parameters with an If statement, or you can pass the command to the &lt;b&gt;Out-Null&lt;/b&gt; cmdlet to avoid the If statement as shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$PSBoundParameters.Remove(&amp;quot;WhatIf&amp;quot;) | Out-Null&lt;/p&gt;
&lt;p&gt;I also have to handle the two methods of passing credentials to the script. The parameter &lt;i&gt;Credential&lt;/i&gt; is not typed, so it accepts a string or a credential object as shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$cred = Get-Credential -Credential &amp;quot;mitschke\karlm&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;.\Invoke-StartService.ps1 -Credential $cred&lt;/p&gt;
&lt;p&gt;When it is supplied like that, the &lt;b&gt;$PSBoundParameters&lt;/b&gt; hash table passes a credential object to the &lt;b&gt;Get-WmiObject&lt;/b&gt; cmdlet. However, if you supply the &lt;i&gt;Credential&lt;/i&gt; parameter with a string, allowing the script to prompt for a password, the &lt;b&gt;$PSBoundParameters&lt;/b&gt; hash table passes the string to the &lt;b&gt;Get-WmiObject&lt;/b&gt; cmdlet and prompts for a password on every service that needs starting.&lt;/p&gt;
&lt;p&gt;This is resolved by once again using the &lt;b&gt;Remove()&lt;/b&gt; method of the hash table, and then using the &lt;b&gt;Add()&lt;/b&gt; method to add the valid credential object to the &lt;b&gt;$PSBoundParameters&lt;/b&gt; hash table as shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;if ($Credential -ne $null -and $Credential.GetType().Name -eq &amp;quot;String&amp;quot;)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;{&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$PSBoundParameters.Remove(&amp;quot;Credential&amp;quot;) | Out-Null&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$PSBoundParameters.Add(&amp;quot;Credential&amp;quot;, (Get-Credential -Credential $Credential))&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p&gt;I modified the &lt;i&gt;Filter&lt;/i&gt; parameter for the &lt;b&gt;Get-WmiObject&lt;/b&gt; cmdlet to find only the services that I was interested in. Specifically, I am not interested in starting the Microsoft .NET Framework Runtime Optimization Services, which may be set to start automatically. The service would start and then stop because it finds that no action is needed. It is not really a problem starting these services, I just wanted to avoid the time it takes to start them, and avoid event log entries that show they had started and stopped.&lt;/p&gt;
&lt;p&gt;These services have a service name starting with clr_optimization_. The filter I use is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Filter &amp;quot;startmode=&amp;#39;auto&amp;#39; and state=&amp;#39;stopped&amp;#39; and (name &amp;gt; &amp;#39;clra&amp;#39; or name &amp;lt; &amp;#39;clr&amp;#39;)&amp;quot;&lt;/p&gt;
&lt;p&gt;The filter isn&amp;rsquo;t perfect&amp;mdash;I suppose there could be a service with a name that starts with clra, but I have not seen one, so the filter serves my purposes. A better filter could use the grave accent character (`). The grave accent character is also the escape character for Windows PowerShell, so you would need to use two grave accents as &amp;ldquo;name &amp;gt; &amp;#39;clr``&amp;rsquo;&amp;rdquo;. You could also use a client-side filter by using the &lt;b&gt;Where-Object&lt;/b&gt; cmdlet as shown here:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WmiObject -Class Win32_Service | Where-Object -FilterScript {$_.Name -notmatch &amp;quot;clr_*&amp;quot; -and $_.StartMode -eq &amp;quot;Auto&amp;quot; -And $_.State -ne &amp;quot;Running&amp;quot;}&lt;/p&gt;
&lt;p&gt;That is perfectly valid; however, using the &lt;i&gt;Filter&lt;/i&gt; parameter of the &lt;b&gt;Get-WmiObject&lt;/b&gt; cmdlet performs server-side filtering, which should be quicker because only the objects we are interested in are passed back to the client. The complete server-side filtering example is shown here:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WmiObject -Class Win32_Service &amp;ndash;Filter &amp;quot;startmode=&amp;#39;auto&amp;#39; and state=&amp;#39;stopped&amp;#39; and (name &amp;gt; &amp;#39;clra&amp;#39; or name &amp;lt; &amp;#39;clr&amp;#39;)&amp;quot;&lt;/p&gt;
&lt;p&gt;So now we have a working filter, working parameters, and working Help. It is now time to test the parameters with the &lt;i&gt;WhatIf &lt;/i&gt;switch. The command line and its associated output are 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/3173.hsg_2D00_12_2D00_12_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/3173.hsg_2D00_12_2D00_12_2D00_11_2D00_2.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When I see what the script will do, I run the script without the &lt;i&gt;WhatIf &lt;/i&gt;parameter. The output from the command appears in the following image.&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/4477.hsg_2D00_12_2D00_12_2D00_11_2D00_3.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/4477.hsg_2D00_12_2D00_12_2D00_11_2D00_3.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As mentioned, the entire script is available in the &lt;a href="http://gallery.technet.microsoft.com/Starts-automatic-on-remote-26ddd199" target="_blank"&gt;Scripting Guys Script Repository&lt;/a&gt;. The output of the script follows the script. I believe the script is pretty well written; but as always, I am open to suggestions. You can reach me at:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;-join (&amp;quot;6B61726C6D69747363686B65406D742E6E6574&amp;quot;-split&amp;quot;(?&amp;lt;=\G.{2})&amp;quot;,19|%{[char][int]&amp;quot;0x$_&amp;quot;})&lt;/p&gt;
&lt;p&gt;Thank you Karl, for a very useful and interesting blog post. Join me tomorrow for more Windows PowerShell goodness.&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=3469599" width="1" height="1" alt="" /&gt;</description></item><item><title>Expert Solution for the 2011 Scripting Games Beginner Event 4: Use PowerShell to Identify Non-Standard Windows Service Accounts</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2011/04/21/expert-solution-for-the-2011-scripting-games-beginner-event-4-use-powershell-to-identify-non-standard-windows-service-accounts.aspx</link><pubDate>Thu, 21 Apr 2011 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:10074</guid><dc:creator>Anonymous</dc:creator><description>Summary : Microsoft Windows PowerShell MVP Tobias Weltner solves 2011 Scripting Games Beginner Event 4 and finds nonstandard Windows service accounts. Microsoft Scripting Guy, Ed Wilson, here. Our expert commentator for Beginner Event 4 is Dr. Tobias...(&lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2011/04/21/expert-solution-for-the-2011-scripting-games-beginner-event-4-use-powershell-to-identify-non-standard-windows-service-accounts.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3419833" width="1" height="1" alt="" /&gt;</description></item><item><title>Expert Solution for 2011 Scripting Games Advanced Event 4: Use PowerShell to Find Services Hiding in the SvcHost Process</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2011/04/21/expert-solution-for-2011-scripting-games-advanced-event-4-use-powershell-to-find-services-hiding-in-the-svchost-process.aspx</link><pubDate>Thu, 21 Apr 2011 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:10075</guid><dc:creator>Anonymous</dc:creator><description>Summary : Microsoft research software developer, Chris O&amp;#39;Prey, solves Windows PowerShell 2011 Scripting Games Advanced Event 4 and finds services that are running in the SvcHost process. Microsoft Scripting Guy, Ed Wilson, here. With us today with his...(&lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2011/04/21/expert-solution-for-2011-scripting-games-advanced-event-4-use-powershell-to-find-services-hiding-in-the-svchost-process.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3419911" width="1" height="1" alt="" /&gt;</description></item></channel></rss>