<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>PowerShell Pro! &#187; PowerShell Scripting</title>
	<atom:link href="http://www.powershellpro.com/category/powershell-scripts/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.powershellpro.com</link>
	<description>Sharing the Experience</description>
	<lastBuildDate>Fri, 26 Jun 2009 16:26:47 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>A funny thing happened on my way to the remote registry&#8230;</title>
		<link>http://www.powershellpro.com/a-funny-thing-happen-on-my-way-to-the-remote-registry/663/</link>
		<comments>http://www.powershellpro.com/a-funny-thing-happen-on-my-way-to-the-remote-registry/663/#comments</comments>
		<pubDate>Wed, 17 Jun 2009 22:10:01 +0000</pubDate>
		<dc:creator>Jesse Hamrick</dc:creator>
				<category><![CDATA[PowerShell Scripting]]></category>

		<guid isPermaLink="false">http://www.powershellpro.com/?p=663</guid>
		<description><![CDATA[I became an evil hacker who was preying on I.T. managers!!! At least that&#8217;s what the initial reaction was. I was caught off guard, the big boss called me in his office and had asked why I had accessed his PC along with other (high level) managers? The CEO also wanted to know what business [...]]]></description>
			<content:encoded><![CDATA[<p>I became an evil hacker who was preying on I.T. managers!!! At least that&#8217;s what the initial reaction was. I was caught off guard, the big boss called me in his office and had asked why I had accessed his PC along with other (high level) managers? The CEO also wanted to know what business I had accessing his machine? I had NO idea what they were talking about, but I had to find out what was going on&#8230;<br />
<span id="more-663"></span><br />
<script type="text/javascript"><!--
google_ad_client = "pub-7768408415611863";
google_ad_slot = "2118646901";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
<br />
<strong>FYI &#8211; This can and may have already happened to you!</strong><br />
Scenario: Got a call from our help desk, users were having issues with their PC&#8217;s. Troubleshooting the issue revealed vendor supported systems where the time synchronization configuration was not set up to use our domain. Fixed the issue, thought that was the last I heard of that&#8230; I was wrong. The big boss came to me and said, &#8220;I want a report of time synchronization settings for every computer in the domain!&#8221; I said&#8230; &#8220;No Problem.&#8221;</p>
<p>I wrote a script to check the remote registry time server parameters:<br />
(System\CurrentControlSet\Services\W32TIME\Parameters)<br />
Started the script around 5:00PM and went home. I wasn&#8217;t going to wait around for 5000+ machines to be enumerated. In the morning my results were completed and I shipped the Excel report to the boss.</p>
<p>Couple of days later is when I was asked what I was doing on his machine. I said, &#8220;show me what you are talking about.&#8221; He opened documents and settings and there was my profile. It had a modified date of (pick a date)  at 7:00PM. I put two-an-two together and realized that the mod date stamp reflected the same time I ran the script. I had him delete the profile and I re-ran the script pointing to his machine. Sure enough, my profile appeared again. I had no idea that running a script that connects to the remote registry will create a user profile on the remote machine. So that got me out of hot water but know I have a profile on every machine in the company, oh boy!</p>
<p>I have not done any research on why this happens, thought I would warn you that it can happen, and am curious to know why? &#8211; If anyone wants to chime in&#8230;</p>
<p><a href="http://www.powershellpro.com/wp-content/uploads/TimeSrvChk.txt">Here is the link to the script file I used</a></p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-7768408415611863";
google_ad_slot = "2118646901";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
<br />
Note: There is an email link embedded within this post, please visit this post to email it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.powershellpro.com/a-funny-thing-happen-on-my-way-to-the-remote-registry/663/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>How to find a needle in the Array stack</title>
		<link>http://www.powershellpro.com/how-to-find-a-needle-in-the-array-stack/658/</link>
		<comments>http://www.powershellpro.com/how-to-find-a-needle-in-the-array-stack/658/#comments</comments>
		<pubDate>Tue, 16 Jun 2009 23:14:24 +0000</pubDate>
		<dc:creator>Jesse Hamrick</dc:creator>
				<category><![CDATA[PowerShell Scripting]]></category>
		<category><![CDATA[compare arrays]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[PowerShell Scipting]]></category>

		<guid isPermaLink="false">http://www.powershellpro.com/?p=658</guid>
		<description><![CDATA[I finally had a reason to use Ying Li&#8217;s script that compares two arrays and I must tell you it worked beautifully&#8230; What a time saver!!! The big boss comes to me (as I&#8217;ve become his go-to-guy when he needs something done quick) and asks if I could create an email distribution list which contains [...]]]></description>
			<content:encoded><![CDATA[<p>I finally had a reason to use Ying Li&#8217;s script that compares two arrays and I must tell you it worked beautifully&#8230; What a time saver!!! The big boss comes to me (as I&#8217;ve become his go-to-guy when he needs something done quick) and asks if I could create an email distribution list which contains 1000 users. I said &#8220;no problem&#8221; do you have the list of users? He presented me the list and told me it is of the utmost importance that everyone on this list receives an email that will be distributed at the end of the week. Again we say, &#8220;NO Problem!!!&#8221;</p>
<p><span id="more-658"></span></p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-7768408415611863";
google_ad_slot = "2118646901";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
<p>This list was in excel format and contained columns for Last name, First name, and email address. Since I required a property that would be unique to each user, I extracted the email addresses to a text file calledDistEmails.txt. My first step was to write a script that would locate each user in Active Directory and add them as a member to the Distribution list.</p>
<div class="codesnip-container" ># Search AD using email addresses to get Disgtinguished Name (DN)<br />
$ColEmail = Get-Content &#8220;C:\MyScripts\DistEmails.txt&#8221;<br />
$Search = New-Object DirectoryServices.DirectorySearcher([ADSI]&#8220;&#8221;)</p>
<p>foreach ($objEmail in $ColEmail){</p>
<p>$Search.Filter=&#8221;(&amp;(objectClass=User)(proxyAddresses=smtp:$objEmail))&#8221;<br />
$objUsers = $Search.FindAll()<br />
foreach ($objUser in $objUsers){$ADPath = $objUser.Path.Remove(0,7)}<br />
foreach($Item in $ADPath)<br />
{<br />
$Mgroup=[ADSI]&#8220;LDAP://CN=DistGroup,DC=Domain,DC=Com&#8221;<br />
$Mgroup.Member.add($Item)<br />
$Mgroup.setinfo()<br />
}<br />
}</p></div>
<p>The code above takes my list of email addresses, uses an LDAP filter to get the DN of each user, then adds each user to the Distribution Group. So here is when the fun began, remember what the boss said? Of utmostimportance that each person receives the email. First, I verified that the list did have 1000 user entries in it (counted excel spread sheet rows). Second, I needed to verify that there are 1000 members in the Distribution Group. How did I do this???</p>
<p>Wrote a script of course&#8230;</p>
<div class="codesnip-container" >$Search = New-Object DirectoryServices.DirectorySearcher([ADSI]&#8220;&#8221;)<br />
$Search.Filter=&#8221;(memberOf=CN=DistGroup,DC=Domain,DC=com)&#8221;<br />
$objUsers = $Search.FindAll()<br />
$ObjUsers.Count</div>
<p>Code uses an LDAP filter to search for members of the Distribution Group, saves the results to the $objUsers array, then I just use the count property for the number of entries in the array. <em><strong>Note: the array count starts with 0 not 1.</strong></em></p>
<p>If my count property would have came out to 999 then I would have been home free, nothing is easy as my count was 989. Oh boy! How to I find Ten needles in a hay stack of 1000 users? Any thought of doing this manually by referencing the excel file and &#8216;Active Directory Users and Computers&#8217; is out-of-the-question.</p>
<p>I remembered posting one of Ying Li scripts in the script library that should do the trick. All I needed where two files to do a comparison on. One file I already had which was the DistEmails.txt file I used in the script to add group membership. The second file had to be a list of the email addresses of the current 990 members of the Distribution list. Time for some more code&#8230;</p>
<div class="codesnip-container" >$Search = New-Object DirectoryServices.DirectorySearcher([ADSI]&#8220;&#8221;)<br />
$Search.Filter=&#8221;(memberOf=CN=DistGroup,DC=Domain,DC=com)&#8221;<br />
$objUsers = $Search.FindAll()<br />
foreach ($objUser in $objUsers){$colProps = $objUser.Properties<br />
foreach($objProp in $colProps){$Items = $objProp.proxyaddresses}<br />
$Items &gt;&gt; C:\MyScipts\GroupEmail.txt<br />
}</div>
<p>Now I have a text file Called GroupEmail.txt. The next step I had to do with the file was open it in WordPad and use &#8220;replace&#8221; to remove the &#8220;SMTP:&#8221; portion of the email address so that the entries match the addresses in the DistEmail.txt file.</p>
<p>Time to compare the files to see which email addresses are missing.</p>
<div class="codesnip-container" >$arrFirst = Get-Content &#8220;C:\MyScripts\DistEmails.txt&#8221;<br />
$arrSecond = Get-Content &#8220;C:\MyScripts\GroupEmail.txt&#8221;<br />
New-Item &#8220;C:\MyScripts\FirstInSecond.txt&#8221; -Type file<br />
New-Item &#8220;C:\MyScripts\FirstNOTinSecond.txt&#8221; -type file<br />
foreach($First in $arrFirst){<br />
if($arrSecond -contains $First)<br />
{Add-Content &#8220;C:\MyScripts\FirstInSecond.txt&#8221; $First}<br />
else<br />
{Add-Content &#8220;C:\MyScripts\FirstNOTinSecond.txt&#8221; $First}<br />
}</div>
<p>Each file is placed in an array. We then create two new text files. We compare the two arrays and depending on the result we write the array entry in either the FirstInSecond.txt or the FirstNOTinSecond.txt file. Opening the FirstNOTinSecond.txt yields the results of our ten missing email addresses. Investigating the issue I found that the user accounts were still valid, just their email address had changed format. I added the missing ten users to the distribution group (yes, I did it manually via ADUC) and provided the boss with a list of users that are members of the group, all 1000 of them&#8230;</p>
Note: There is an email link embedded within this post, please visit this post to email it.
<p><script type="text/javascript"><!--
google_ad_client = "pub-7768408415611863";
google_ad_slot = "2118646901";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
]]></content:encoded>
			<wfw:commentRss>http://www.powershellpro.com/how-to-find-a-needle-in-the-array-stack/658/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>How do I know if I&#8217;m missing MS Patches?</title>
		<link>http://www.powershellpro.com/how-do-i-know-if-im-missing-ms-patches/640/</link>
		<comments>http://www.powershellpro.com/how-do-i-know-if-im-missing-ms-patches/640/#comments</comments>
		<pubDate>Mon, 11 May 2009 23:51:59 +0000</pubDate>
		<dc:creator>Jesse Hamrick</dc:creator>
				<category><![CDATA[PowerShell Scripting]]></category>

		<guid isPermaLink="false">http://www.powershellpro.com/?p=640</guid>
		<description><![CDATA[During the Conficker storm I had released a script that would check for the installation of Hot Fix KB958644, which was to assists is thwarting off the worm. Many of you sent in messages asking if there is a way, with PowerShell, to detect which MS Patches are NOT installed on a machine. The answer [...]]]></description>
			<content:encoded><![CDATA[<p>During the Conficker storm I had released a script that would check for the installation of Hot Fix KB958644, which was to assists is thwarting off the worm. Many of you sent in messages asking if there is a way, with PowerShell, to detect which MS Patches are NOT installed on a machine. The answer is No! &#8230; but I&#8217;ll still show you how to get the information.<span id="more-640"></span></p>
<p>What makes scripting this a difficult task is that amount of variables that are present or not present:</p>
<ol>
<li>Different Operating Systems</li>
<li>Service Pack Levels</li>
<li>Not knowing what patches are available for each circumstance</li>
<li>The list can go on&#8230;</li>
</ol>
<p>Is PowerShell really the best tool for the job? Again my answer is no or not until someone builds a cmdlet that can do the job (it will happen). So, what is the best tool for the Job! Windows Update, SUS, MBSA, &#8230;? In my opinion it&#8217;s <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=F32921AF-9DBE-4DCE-889E-ECF997EB18E9&amp;displaylang=en" target="_blank">MBSA(Microsoft Baseline Security Analyzer)</a>.</p>
<p>The command line will give me all the information I need with regards to missing patches on workstations and servers. This simple command looks like this:</p>
<div class="codesnip-container" >mbsacli.exe /Target Domain\Computer</div>
<p>&#8216;Quick and dirty&#8217; and you have all the security information. If you want only the update information without all the other security information, you would modify the command as such:</p>
<div class="codesnip-container" >mbsacli.exe /Target Domain\Computer /n OS+SQL+IIS+Password</div>
<p>With the /n options you are telling MBSA NOT to gather OS, SQL, IIS, and Password security settings, the only thing left to gather is &#8220;Updates&#8221; which is what we want. Check out <strong>mbsacli /?</strong> for more help.</p>
<p>So what would PowerShell be used for? I use PowerShell to organize the data and to show you how to call .exe&#8217;s from a PowerShell Script. The code below gathers the Update information using MBSA, outputs the results to a temp file. PowerShell reads the temp file and strips out all the entries that match the term &#8220;missing&#8221; and places each entry into an Excel spreadsheet. Not rocket-surgery but you end up with a clean report.</p>
<p>To run the code below make sure your computer has Excel and MBSA installed. Also, MBSA synchronizes with Microsoft Update, so it can take a little time to find which updates are missing from the machine.  Be patient the results are worth it!</p>
<div class="codesnip-container" ># This script requires Excel and MBSA installed on your computer.</p>
<p>$strComputer = Read-Host &#8220;Enter Computer Name&#8221;<br />
$strDomain = Read-Host &#8220;Enter the Domain Name&#8221;</p>
<p># Default Install Path for MBSA 2.1. If your install path is<br />
# differen&#8217;t, change line below.<br />
$Path = &#8220;C:\Program Files\Microsoft Baseline Security Analyzer 2&#8243;</p>
<p># Create new com object Excel<br />
$Excel = New-Object -Com Excel.Application<br />
$Excel.visible = $True<br />
$Excel = $Excel.Workbooks.Add()</p>
<p># Assign each worksheet to a variable and<br />
# name the worksheet.<br />
$Sheet1 = $Excel.Worksheets.Item(1)<br />
$Sheet1.Name = &#8220;Patches&#8221;</p>
<p>#Create Heading for Anti-Virus Sheet<br />
$Sheet1.Cells.Item(1,1) = &#8220;Computer Name&#8221;<br />
$Sheet1.Cells.Item(1,2) = &#8220;Patch Information&#8221;</p>
<p>$intRow = 2<br />
$WorkBook = $sheet1.UsedRange<br />
$WorkBook.Interior.ColorIndex = 20<br />
$WorkBook.Font.ColorIndex = 11<br />
$WorkBook.Font.Bold = $True</p>
<p>Set-Location $Path<br />
$cmd = &#8220;cmd /c mbsacli.exe /Target $strDomain\$strComputer /n OS+SQL+IIS+Password &gt;C:\MBSA$strComputer.txt&#8221;<br />
Invoke-Expression $cmd</p>
<p>$logResults = (Get-Content &#8220;C:\MBSA$strComputer.txt&#8221;) -match &#8220;Missing&#8221;<br />
foreach($Item in $logResults){<br />
$Sheet1.Cells.Item($intRow, 1) = $strComputer<br />
$Sheet1.Cells.Item($intRow, 2) = $Item<br />
$intRow = $intRow + 1<br />
}</p>
<p>#Auto Fit all sheets in the Workbook<br />
#$WorkBook = $colorItem.UsedRange<br />
$WorkBook.EntireColumn.AutoFit()<br />
clear</p>
<p>#delete Temp File<br />
Remove-Item &#8220;C:\MBSA$strComputer.txt&#8221;</p></div>
<p>There is one formating issues with the code above, the line:<br />
<em>$cmd = &#8220;cmd /c mbsacli.exe /Target $strDomain\$strComputer /n OS+SQL+IIS+Password &gt;C:\MBSA$strComputer.txt&#8221;<br />
</em>Should be one continuous line, if you just copy the code into Notepad the formatting will be correct.</p>
<p>Also, notice in the line I am using <strong>cmd /c mbsacli.exe</strong> to run a Windows Command Prompt as a child of the PowerShell comand prompt. I do this regularly when I need to run command line utililities from a PowerShell script. To get more information on how to run a Windows Command Prompt from within a PowerShell session just type <strong>cmd /? </strong>at the PowerShell command prompt.</p>
<p>Happy scripting&#8230;</p>
Note: There is an email link embedded within this post, please visit this post to email it.
]]></content:encoded>
			<wfw:commentRss>http://www.powershellpro.com/how-do-i-know-if-im-missing-ms-patches/640/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Why I no longer hate writing documentation&#8230;</title>
		<link>http://www.powershellpro.com/why-i-no-longer-hate-writing-documentation/614/</link>
		<comments>http://www.powershellpro.com/why-i-no-longer-hate-writing-documentation/614/#comments</comments>
		<pubDate>Tue, 21 Apr 2009 23:18:30 +0000</pubDate>
		<dc:creator>Jesse Hamrick</dc:creator>
				<category><![CDATA[PowerShell Scripting]]></category>

		<guid isPermaLink="false">http://www.powershellpro.com/?p=614</guid>
		<description><![CDATA[&#8230;it&#8217;s because I no longer have to! And you too will no longer document your computers and servers either. Why? Because PowerShell is going to do it for you and I&#8217;m going to share with you how I did it. Yes, it is going to be presented well, in Excel, and the Boss is going [...]]]></description>
			<content:encoded><![CDATA[<p>&#8230;it&#8217;s because I no longer have to! And you too will no longer document your computers and servers either. Why? Because PowerShell is going to do it for you and I&#8217;m going to share with you how I did it. Yes, it is going to be presented well, in Excel, and the Boss is going to think that you are the greatest thing since sliced bread.</p>
<p><span id="more-614"></span></p>
<p><strong>Computer Inventory</strong></p>
<p>I picked up a side job at the beginning of the year documenting the infrastructure for a company that will remain anonymous at this time. It doesn&#8217;t surprise me that many companies still do not maintain up-to-date documentation if any.  What is the &#8220;BIG DEAL&#8221; about documenting a system, is it really a &#8220;time factor&#8221; problem or &#8220;lack of resources&#8221; to do the job? I, like many of my peers, just think documenting SUCKS!!! So I set out to make my life and hopefully yours a little easier.</p>
<p>The Computer Inventory Script enumerates Hardware, OS, System, Processor, Memory, Disk, and Network information and neatly organizes it in an Excel file. I&#8217;ve provided Version 2 of the script that allows you to choose a number of computer resources; all computers in the domain, all servers in the domain, computers from a list maintained in a text file, and the ability manually pick a computer. Version 2 of the PowerShell script also allows you to send credential information should you wish to logon the remote computer with an alternative user account. This is helpful for DMZ servers as well as stand alone servers that are not members of your domain.</p>
<p>Please feel free to customize this script to fit your environment. I&#8217;m not going into any detail about the script as I am reserving that information for a new PowerShell tutorial that I am writing about COM objects. So check the tutorial section to for more information.</p>
<p><a title="Computer Inventory Script" href="http://www.powershellpro.com/wp-content/uploads/CompInv_v2.zip" target="_blank">Download Script file here.</a></p>
<p>Here is the code so that you can view it before downloading. I would suggest downloading this file as format issues with copying the code below may occur.</p>
<p><a href="http://www.powershellpro.com/wp-content/uploads/CompInv_v2.ps1" target="_blank">View Script code here.</a></p>
Note: There is an email link embedded within this post, please visit this post to email it.
]]></content:encoded>
			<wfw:commentRss>http://www.powershellpro.com/why-i-no-longer-hate-writing-documentation/614/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Conficker Worm Detection</title>
		<link>http://www.powershellpro.com/conficker-worm-detection/605/</link>
		<comments>http://www.powershellpro.com/conficker-worm-detection/605/#comments</comments>
		<pubDate>Wed, 01 Apr 2009 17:20:01 +0000</pubDate>
		<dc:creator>Jesse Hamrick</dc:creator>
				<category><![CDATA[PowerShell Scripting]]></category>

		<guid isPermaLink="false">http://www.powershellpro.com/?p=605</guid>
		<description><![CDATA[McAfee has posted a Confiker Detection tool that scans IP ranges for infected machines. You can download the tool here.
The two ways to protect your systems are to make sure that you have the Microsoft Hot Fix KB958644 from Microsoft Security Bulletin MS08-067 installed on your systems and to update your virus definitions.
I was asked [...]]]></description>
			<content:encoded><![CDATA[<p>McAfee has posted a Confiker Detection tool that scans IP ranges for infected machines. <a href="http://www.mcafee.com/us/enterprise/confickertest.html" target="_blank">You can download the tool here.</a></p>
<p>The two ways to protect your systems are to make sure that you have the Microsoft Hot Fix KB958644 from <a href="http://www.microsoft.com/technet/security/bulletin/MS08-067.mspx" target="_blank">Microsoft Security Bulletin MS08-067</a> installed on your systems and to update your virus definitions.</p>
<p>I was asked to write a PowerShell script that would check all machines on the domain for the installation of the hot fix. I am sharing the code with you in hopes that this will assist in your defenses against the Confiker worm.</p>
<p><span id="more-605"></span></p>
<p>Take note of the filter section. You can choose to enumerate all computers (workstations and servers) or just servers by commenting out code. By default I have the filter set to enumerate all computers in the domain.<br />
<strong># Uncomment to search all computers<br />
$objSearcher.Filter = (&#8220;(objectCategory=$strCategory)&#8221;)<br />
# Uncomment to seach only Servers<br />
# $objSearcher.Filter = (&#8220;(&amp;(objectCategory=$strCategory)(OperatingSystem=$strOS))&#8221;)</strong></p>
<p>Code:</p>
<div class="codesnip-container" ># ======================================================<br />
# Microsoft PowerShell Source File<br />
#<br />
# NAME: HotFixInfo.ps1<br />
#<br />
# AUTHOR: Jesse N. Hamrick<br />
# WEB    : www.PowerShellPro.com<br />
# DATE  : 04/01/2009<br />
#<br />
# COMMENT:     Script file enumerates hot fixes on all computers<br />
#            in AD.<br />
#            Sends the reuslts to an Excel spreadsheet.<br />
#            Script filters for KB958644 (confiker defense)<br />
#             Excel must be installed on the computer running<br />
#             the script.<br />
# ======================================================</p>
<p># ======================================================<br />
# Fucntion Section<br />
# ======================================================<br />
# Fuction Name &#8216;Excel&#8217; &#8211; Creates a spreadsheet and places<br />
# resutls.<br />
# Uses WMIObject Win32_QuickFixEngineering to gather hotfix<br />
# info.<br />
# ======================================================<br />
Function Excel {</p>
<p>$Excel = New-Object -Com Excel.Application<br />
$Excel.visible = $True<br />
$Excel = $Excel.Workbooks.Add()<br />
$Sheet = $Excel.Worksheets.Item(1)<br />
$Sheet.Cells.Item(1,1) = &#8220;Computer Name&#8221;<br />
$Sheet.Cells.Item(1,2) = &#8220;Q Article&#8221;<br />
$Sheet.Cells.Item(1,3) = &#8220;Installer&#8221;<br />
$Sheet.Cells.Item(1,4) = &#8220;Install Date&#8221;<br />
$Sheet.Cells.Item(1,5) = &#8220;Description&#8221;</p>
<p>$intRow = 2<br />
$WorkBook = $Sheet.UsedRange<br />
$WorkBook.Interior.ColorIndex = 19<br />
$WorkBook.Font.ColorIndex = 11<br />
$WorkBook.Font.Bold = $True</p>
<p>foreach ($StrComputer in $colComputers){<br />
$reply = gwmi win32_PingStatus -Filter &#8220;Address=&#8217;$strComputer&#8217;&#8221;<br />
if ($reply.statusCode -eq &#8220;0&#8243;){<br />
$Sheet.Cells.Item($intRow, 1) = $StrComputer<br />
$SheetcolItems = gwmi Win32_quickFixEngineering -Comp $StrComputer<br />
foreach ($objItem in $SheetcolItems){<br />
If ($objItem.HotFixID -eq &#8220;KB958644&#8243;){<br />
$Sheet.Cells.Item($intRow, 2) = &#8220;KB958644 Installed&#8221;<br />
$Sheet.Cells.Item($intRow, 3) = $objItem.InstalledBy<br />
$Sheet.Cells.Item($intRow, 4) = $objItem.InstalledOn<br />
$Sheet.Cells.Item($intRow, 5) = $objItem.Description<br />
$intRow = $intRow + 1}<br />
}<br />
}<br />
}<br />
$WorkBook.EntireColumn.AutoFit()<br />
clear</p>
<p>}<br />
# END OF Excel function</p>
<p># ========================================================<br />
# Function Name &#8216;ListComputers&#8217; &#8211; Enumerates computer objects<br />
# ========================================================<br />
Function ListComputers {<br />
$strCategory = &#8220;computer&#8221;<br />
$strOS = &#8220;Windows*Server*&#8221;</p>
<p>$objDomain = New-Object System.DirectoryServices.DirectoryEntry</p>
<p>$objSearcher = New-Object System.DirectoryServices.DirectorySearcher<br />
$objSearcher.SearchRoot = $objDomain</p>
<p># Uncomment to search all computers<br />
# $objSearcher.Filter = (&#8220;(objectCategory=$strCategory)&#8221;)<br />
# Uncomment to seach only Servers<br />
$objSearcher.Filter = (&#8220;(&amp;(objectCategory=$strCategory)(OperatingSystem=$strOS))&#8221;)</p>
<p>$colProplist = &#8220;name&#8221;<br />
foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)}</p>
<p>$colResults = $objSearcher.FindAll()</p>
<p>foreach ($objResult in $colResults)<br />
{$objComputer = $objResult.Properties; $objComputer.name}<br />
}<br />
#END OF FUNCTION</p>
<p># ========================================================<br />
# Script Body<br />
# ========================================================<br />
$erroractionpreference = &#8220;SilentlyContinue&#8221;</p>
<p># Call the ListComputers Function and save results to<br />
# an array called $colComputer. Results are sorted alphabetically.<br />
$colComputers = ListComputers | Sort-Object</p>
<p># Call the Excel Function, which will use the $colComputers<br />
# array to enumerate hotfix info for each computer in the domain.<br />
Excel</p>
<p>#END OF SCRIPT ===============================================</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.powershellpro.com/conficker-worm-detection/605/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Enumerate The Remote Event Log with .NET</title>
		<link>http://www.powershellpro.com/enumerate-the-remote-event-log-with-net/280/</link>
		<comments>http://www.powershellpro.com/enumerate-the-remote-event-log-with-net/280/#comments</comments>
		<pubDate>Fri, 07 Nov 2008 21:28:26 +0000</pubDate>
		<dc:creator>Jesse Hamrick</dc:creator>
				<category><![CDATA[PowerShell Scripting]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[cmdlets]]></category>
		<category><![CDATA[Email Alerts]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Scipting]]></category>

		<guid isPermaLink="false">http://www.powershellpro.com/?p=280</guid>
		<description><![CDATA[
One of my favorite things to do as an administrator is to open Domain Controller Security Event Logs and manually thumb through them looking for evil doers&#8230; NOT! Opening, filtering, and sorting entries is as exciting as watching paint dry, well actually paint dries quicker&#8230;
PowerShell introduced a cool cmdlet called Get-EventLog&#8230; Hold on I know [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.powershellpro.com/wp-content/uploads/topsecretl1.jpg"><img src="http://www.powershellpro.com/wp-content/uploads/topsecretl1-300x199.jpg" border="0" alt="" width="160" height="107" align="left" /></a></p>
<p>One of my favorite things to do as an administrator is to open Domain Controller Security Event Logs and manually thumb through them looking for evil doers&#8230; NOT! Opening, filtering, and sorting entries is as exciting as watching paint dry, well actually paint dries quicker&#8230;</p>
<p>PowerShell introduced a cool cmdlet called Get-EventLog&#8230; Hold on I know what you are thinking! You&#8217;ve used Get-EventLog and it only gathers information from the local computer, and your right! Because of this limitation some of you have opted to use WMI to connect to remote logs. Since PowerShell utilizes .NET, how do we use .NET to gather Event log info from a remote computer? If you would like to learn how to use PowerShell and .NET to remotely connect to your Domain Controller and gather information from the security log keep reading on&#8230;</p>
<p><span id="more-280"></span> <strong>Discover the .NET Class</strong></p>
<p>First thing we want to do is discover which .NET class we will be working with. This is a simple step that you can do the &#8220;Get-Member&#8221; cmdlet.</p>
<div class="codesnip-container" >Get-EventLog -LogName Security | Get-Member</div>
<p>The command above produces and table of Methods and Properties. Just above the table you should see an entry called <strong>TypeName : </strong>This is the .NET object we will be working with. In this example the .NET object is <strong>System.Diagnostics.EventLog</strong>.</p>
<p><strong>Connecting to a remote computer using the .NET class</strong></p>
<div class="codesnip-container" >[System.Diagnostics.EventLog]::GetEventLogs(&#8220;YourComputerNameHere&#8221;)</div>
<p>Run the command above, don&#8217;t forget to place your computer name within the quotes (string). Your output should be similar to this, a listing of all the Event Logs on the remote computer.</p>
<p><img src="http://www.powershellpro.com/wp-content/uploads/EvtLogOut.JPG" border="0" alt="" width="471" height="138" align="top" /></p>
<p>If you havent worked with .NET and PowerShell you may be wondering where I got the command above? There is no magic bullet for learning .NET. The best way is to download the Microsoft .NET Framework 2.0 SDK and go through the .NET Class Library documentation. What I did was look up<span style="font-weight: bold"> Systems.Diagnostics -&gt; EventLog Class.</span> I found a method called<span style="font-weight: bold"> GetEventLogs </span>which &#8220;searches for all event logs on the <em>given computer</em> and creates an array of Event Log objects.&#8221;</p>
<p>Now that I know that i am working will an array I am going to run the command above and save the array to a variable called $Logs.</p>
<div class="codesnip-container" >$logs = [System.Diagnostics.EventLog]::GetEventLogs(&#8216;YourComputerNameHere&#8217;)</div>
<p>Verify the array entries in the $logs variable</p>
<div class="codesnip-container" >$logs</div>
<p>Further investigating the <strong>System.Diagnostics.EventLog</strong> there is a property called <strong>Entries</strong> which &#8220;Gets the contents of the event log.&#8221;</p>
<p><strong>Note: </strong><span style="font-style: italic">Here is the trick, we are working with an array, arrays index items begining with 0 (Zero). Remember that and the next example on which log to enumerate will make sense.</span></p>
<p>In the example I posted, my array index values would look like this:</p>
<p>0 &#8211; Application<br />
1 &#8211; Directory Services<br />
2 &#8211; DNS Server<br />
3 &#8211; File Replication Service<br />
4 &#8211; Internet Explorer<br />
5 &#8211; Security<br />
6 &#8211; System</p>
<p>Knowing that I want to work with the security log I use the following code to get <span style="font-weight: bold">all </span>Security Log entries.</p>
<div class="codesnip-container" >$logs[5].entries</div>
<p>If there are a lot of entries then you are currently starting at a PowerShell console with information whizzing by!!! Use &#8220;Ctrl + C&#8221; to stop the execution.</p>
<p>That is the gist of how to use .NET to connect to a remote computer and enumerate Event Log files. If you want to enumerate the System log just change the code to <strong>$logs[6].entries </strong>(6 being the index number for the System log).</p>
<p><strong>Script it and Filter it&#8230;</strong></p>
<p>So now that you have a big amount of data its sill an administrative nightmare. I&#8217;m going to share a script with you that uses the <em>foreach</em> loop and the <em>if</em> conditional statement to enumerate the security log and only output events of interest.</p>
<p>Remember to input your computer name within &#8220;YourComputerName&#8221;</p>
<div class="codesnip-container" ># ====================================<br />
#<br />
# Microsoft PowerShell Source File<br />
#<br />
# NAME: EvtLogReader.ps1<br />
#<br />
# AUTHOR: Jesse Hamrick<br />
# DATE  : 11/5/2008<br />
# Web    : www.powershellpro.com<br />
# COMMENT: Script enumerates Security Log and Outputs Requested Results<br />
#<br />
# ======================================</p>
<p># Enumerate Domain Controller Security Logs for the following entries<br />
# Event ID 608 &#8211; User Right Assigned<br />
# Event ID 609 &#8211; User Right Removed<br />
# Event ID 626 &#8211; User Account Enabled<br />
# Event ID 627 &#8211; Change Pass Attempt<br />
# Event ID 628 &#8211; User Account Pass set<br />
# Event ID 630 &#8211; User Account Delete<br />
# Event ID 631 &#8211; Global Group Created<br />
# Event ID 632 &#8211; Global Group Member Added<br />
# Event ID 633 &#8211; Global Group Member Removed<br />
# Event ID 634 &#8211; Global Group Deleted<br />
# Event ID 635 &#8211; Local Group Created<br />
# Event ID 636 &#8211; Local Group Member Added<br />
# Event ID 637 &#8211; Local Group Member Removed<br />
# Event ID 638 &#8211; Local Group Member Deleted<br />
# Event ID 639 &#8211; Local Group Changed<br />
# Event ID 641 &#8211; Global Group Changed<br />
# Event ID 642 &#8211; User Account Changed</p>
<p>#Connect to Security Event Log.</p>
<p>$logs = [System.Diagnostics.EventLog]::GetEventLogs(&#8220;YourComputerName&#8221;)<br />
$colItems = $logs[5].entries</p>
<p>foreach ($item in $colItems){<br />
if(($item.EventID -eq 608)-or($item.EventID -eq 609)-or`<br />
($item.EventID -eq 626)-or($item.EventID -eq 627)-or`<br />
($item.EventID -eq 628)-or($item.EventID -eq 630)-or`<br />
($item.EventID -eq 631)-or($item.EventID -eq 632)-or`<br />
($item.EventID -eq 633)-or($item.EventID -eq 634)-or`<br />
($item.EventID -eq 635)-or($item.EventID -eq 636)-or`<br />
($item.EventID -eq 637)-or($item.EventID -eq 638)-or`<br />
($item.EventID -eq 639)-or($item.EventID -eq 641)-or`<br />
($item.EventID -eq 642)-or($item.EventID -eq 517)){<br />
&#8220;DC Reporting : &#8221; + $item.MachineName<br />
&#8220;Event ID: &#8221; + $item.EventID<br />
&#8220;Time Written: &#8221; + $item.TimeWritten<br />
&#8220;Category: &#8221; + $item.Category<br />
&#8220;Entry Type: &#8221; + $item.EntryType<br />
&#8220;UserName: &#8221; + $item.UserName<br />
&#8220;Data: &#8221; + $item.Data<br />
&#8220;Source: &#8221; + $item.Source<br />
&#8220;Time Generated: &#8221; + $item.TimeGenerated<br />
&#8220;Message: &#8221; + $item.Message<br />
&#8220;====================================================&#8221;<br />
&#8221; &#8221;<br />
}<br />
}<br />
# ===================================================<br />
# End of script<br />
# ===================================================</p></div>
<p>Cool&#8230; now we only get the information we want. Experiment with different EventIDs or other properties. To find which properties you can use, enter the trusty Get-Member cmdlet. Here&#8217;s how I found the EventID property:</p>
<div class="codesnip-container" >$logs[5].entries | Get-Member</div>
<p><strong>Bonus Script (Email Results)</strong></p>
<p>Next&#8230; I&#8217;m going to take the script above and convert it to a function. Then I&#8217;m going to insert the function into the body section of the email template in introduced in another article called &#8220;How to Send Alters to Your Mailbox using .NET.&#8221;</p>
<p>How the script works:</p>
<ol>
<li>Converted  EvtLogReader.ps1 into a function called EvtReader.</li>
<li>Added an option to clear event log when completed $logs[].Clear(). This is an option, the comment needs to be removed to use it. I use it only on the security log due to its rapid growth. Clearing the log allows for faster run times when running the script again.</li>
<li>Call the function from the message body portion of the Email Template.</li>
</ol>
<p>Important things to do:</p>
<ol>
<li>Add Computer name you wish to enumerate</li>
<li>Make sure to verify array index numbers (basically make sure your getting the entries for the correct log).</li>
<li>Go through the Mail portion of the script and add appropriate entries</li>
</ol>
<p>Here is the script:</p>
<div class="codesnip-container" ># Template for SMTP mail using NET classes<br />
# uses authentication and full message.<br />
# easy to extend for use with HTTP.</p>
<p># EvtLogReader.ps1 script converted into a Function<br />
Function EvtReader {<br />
# ==================================================<br />
#<br />
# Microsoft PowerShell Source File<br />
#<br />
# NAME: EvtLogReader.ps1<br />
#<br />
# AUTHOR: Jesse Hamrick<br />
# DATE  : 11/5/2008<br />
# Web    : www.powershellpro.com<br />
#<br />
# ==================================================</p>
<p># Enumerate Computer Security Logs for the following entries<br />
# Event ID 608 &#8211; User Right Assigned<br />
# Event ID 609 &#8211; User Right Removed<br />
# Event ID 626 &#8211; User Account Enabled<br />
# Event ID 627 &#8211; Change Pass Attempt<br />
# Event ID 628 &#8211; User Account Pass set<br />
# Event ID 630 &#8211; User Account Delete<br />
# Event ID 631 &#8211; Global Group Created<br />
# Event ID 632 &#8211; Global Group Member Added<br />
# Event ID 633 &#8211; Global Group Member Removed<br />
# Event ID 634 &#8211; Global Group Deleted<br />
# Event ID 635 &#8211; Local Group Created<br />
# Event ID 636 &#8211; Local Group Member Added<br />
# Event ID 637 &#8211; Local Group Member Removed<br />
# Event ID 638 &#8211; Local Group Member Deleted<br />
# Event ID 639 &#8211; Local Group Changed<br />
# Event ID 641 &#8211; Global Group Changed<br />
# Event ID 642 &#8211; User Account Changed</p>
<p>#Connect to Computer Security Event Log.<br />
$logs = [System.Diagnostics.EventLog]::GetEventLogs(&#8216;ComputeName&#8217;)<br />
$colItems = $logs[5].entries</p>
<p>foreach ($item in $colItems){<br />
if(($item.EventID -eq 608)-or($item.EventID -eq 609)-or`<br />
($item.EventID -eq 626)-or($item.EventID -eq 627)-or`<br />
($item.EventID -eq 628)-or($item.EventID -eq 630)-or`<br />
($item.EventID -eq 631)-or($item.EventID -eq 632)-or`<br />
($item.EventID -eq 633)-or($item.EventID -eq 634)-or`<br />
($item.EventID -eq 635)-or($item.EventID -eq 636)-or`<br />
($item.EventID -eq 637)-or($item.EventID -eq 638)-or`<br />
($item.EventID -eq 639)-or($item.EventID -eq 641)-or`<br />
($item.EventID -eq 642)-or($item.EventID -eq 517)){<br />
&#8220;DC Reporting : &#8221; + $item.MachineName<br />
&#8220;Event ID: &#8221; + $item.EventID<br />
&#8220;Time Written: &#8221; + $item.TimeWritten<br />
&#8220;Category: &#8221; + $item.Category<br />
&#8220;Entry Type: &#8221; + $item.EntryType<br />
&#8220;UserName: &#8221; + $item.UserName<br />
&#8220;Data: &#8221; + $item.Data<br />
&#8220;Source: &#8221; + $item.Source<br />
&#8220;Time Generated: &#8221; + $item.TimeGenerated<br />
&#8220;Message: &#8221; + $item.Message<br />
&#8220;====================================================&#8221;<br />
&#8221; &#8221;<br />
}<br />
}<br />
#Clear the Security Log &#8211; Uncomment line below to enable<br />
# $logs[5].Clear()<br />
}<br />
# ====================================================<br />
# End of Function<br />
# ====================================================</p>
<p># ====================================================<br />
# Script Body<br />
# ====================================================</p>
<p># Create new .NET object and assign to variable<br />
$mail = New-Object System.Net.Mail.MailMessage</p>
<p># Set the addresses (FROM:)<br />
$mail.From = New-Object System.Net.Mail.MailAddress(&#8220;user@domain.com&#8221;);</p>
<p># Set the Recipient Address (TO:)<br />
$mail.To.Add(&#8220;user@domain.com&#8221;);</p>
<p># Email Subject<br />
$mail.Subject = &#8220;DC Security Logs&#8221;;</p>
<p># Message Body &#8211; Call Function Here<br />
$mail.Body = EvtReader;</p>
<p># Connect to your mail server<br />
$smtp = new-object System.Net.Mail.SmtpClient(&#8220;yourdomain.com&#8221;);</p>
<p># Uncomment line below if authentication is required<br />
# $smtp.Credentials = New-Object System.Net.NetworkCredential(&#8220;username&#8221;, &#8220;passwd&#8221;);</p>
<p># Send Mail<br />
$smtp.Send($mail);</p>
<p># ==========================================<br />
# End of Script<br />
# ==========================================</p></div>
<p>After configuring the script for you environment it will email the results. I use the script to send reports each hour. The email sizes are arount 7k (with the clear option enabled). To run the script every hour I use the Task Scheduler.</p>
<p>Happy Scripting&#8230;</p>
Note: There is an email link embedded within this post, please visit this post to email it.
<p><script type="text/javascript"><!--
google_ad_client = "pub-7768408415611863";
google_ad_slot = "2118646901";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
]]></content:encoded>
			<wfw:commentRss>http://www.powershellpro.com/enumerate-the-remote-event-log-with-net/280/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>PowerShell Big Hit at VMworld 2008</title>
		<link>http://www.powershellpro.com/powershell-big-hit-at-vmworld-2008/259/</link>
		<comments>http://www.powershellpro.com/powershell-big-hit-at-vmworld-2008/259/#comments</comments>
		<pubDate>Thu, 09 Oct 2008 18:00:25 +0000</pubDate>
		<dc:creator>Jesse Hamrick</dc:creator>
				<category><![CDATA[PowerShell Scripting]]></category>

		<guid isPermaLink="false">http://www.powershellpro.com/?p=259</guid>
		<description><![CDATA[I had perviously&#160;provided a&#160;download link&#160;for&#160;the VMware VI Toolkit within the &#34;PowerShell Downloads&#34; section on this site. To be quite honest the download statistics have been minimal at best. My thoughts were that since this site caters to those whom are learning PowerShell, the readers of this site&#160;may not yet have been exposed to virtulization technologies. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.powershellpro.com/wp-content/uploads/vmworld.jpg"><img class="size-medium wp-image-260" src="http://www.powershellpro.com/wp-content/uploads/vmworld-300x225.jpg" border="0" alt="Picture of VMworld Slide" title="Picture of VMworld Slide" vspace="1" width="300" height="225" align="left" style="width: 300px; height: 225px" /></a>I had perviously&nbsp;provided a&nbsp;download link&nbsp;for&nbsp;the <a href="http://www.powershellpro.com/category/powershell-downloads/">VMware VI Toolkit</a> within the &quot;PowerShell Downloads&quot; section on this site. To be quite honest the download statistics have been minimal at best. My thoughts were that since this site caters to those whom are learning PowerShell, the readers of this site&nbsp;may not yet have been exposed to virtulization technologies. The way the industry is heading you will&#8230; And <a href="http://vmware.com" target="_blank">VMware ESX</a>&nbsp;is most likley the product you will be working with.</p>
<p>While putting together my schedule for VMworld there it was, <em>&quot;Managing VMware with PowerShell.&quot;</em> I didn&#39;t know what to expect? How well is PowerShell being&nbsp;received as a management tool for VM? Seems kind of strange that a Microsoft technology is utilized to manage a non-Microsoft environment, but that is exactly what&#39;s happening here. I got to the break-out session early and was able to get a good seat. By the time the presentation&nbsp;began it was a packed house, they were turning folks away at the door. Clearly those working with VMware were interested in how PowerShell was going to make administration eaiser and I was one of them&#8230;<span id="more-259"></span></p>
<p>The presenters were:</p>
<ul>
<li>Carter Shanklin &#8211; Product Manager, VMware</li>
<li>Andrey Anastasov &#8211; PowerShell Architect, VMware</li>
<li>Dmitry Sotnikov &#8211; Manager and Microsoft MVP, Quest Software</li>
</ul>
<p><strong>Questions<br /> </strong>What is the VI Toolkit?<br /> <em>It is a scripting tool based on PowerShell. Since it&#39;s based on powershell there are over 125 cmdlets available, many useful actions that can be done at the command line(without scriting).</em></p>
<p>How much is it?<br /> <em>It&#39;s Free!</em></p>
<p>How does it make my life eaiser?<br /> <em>Save time by automating&nbsp;repetitive&nbsp;tasks and&nbsp;automating time consuming tasks.</em></p>
<p><strong>Examples<br /> </strong>Because VMotion doesn&#39;t support moving Virtual Machines that contain a snapshot, how do I find which VMs have a snapshot?</p>
<ul>
<li>Get-VM | Get-Snapshot</li>
</ul>
<p>Find all snapshots older than one month:</p>
<ul>
<li>Get-VM | Get-Snapshot | Where{$_.Created -lt (Get-Date).addMonths(-1)</li>
</ul>
<p>I&#39;m Migrating&nbsp;all VMs from Network A to Network B:</p>
<ul>
<li>Get-VM | Get-NetworkAdapter | Where{$_.NetworkName -eq &quot;Network A&quot;} |<br /> Set-NetworkAdapter -NetworkName B</li>
</ul>
<p>Ensure all VMs have at least 1GB of RAM:</p>
<ul>
<li>Get-VM | Where {$_.MemoryMB -lt 1024} | Set-VM -MemoryMB 1024</li>
</ul>
<p>Update VMware Tools on all VMs in the corporate datacenter:</p>
<ul>
<li>Get-Datacenter &quot;corporate&quot; | Get-VM | Update-Tools</li>
</ul>
<p>Restart an unresponsive VitrualCenter agent:</p>
<ul>
<li>Get-VMHost ESXProd1 | Get-VMHostService | Where {$_.key -eq &quot;vmware-vpxa&quot;} |<br /> Restart-VMHostService</li>
</ul>
<p>Every time you add new LUNS to your environment you have to scan each HBA on all ESX servers. Manually a PITA. Here is how to do it with the VI Toolkit:</p>
<ul>
<li>Get-VMHost | Get-VMHostStorage -RescanAllHba</li>
</ul>
<p><strong>Available Resources:</strong></p>
<p>The VI Toolkit Community, Vi Tookit FAQ, and the VI Tookit Blog are all <a href="http://vmware.com/go/powershell" target="_blank">available here.</a></p>
<p>The VI Toolkit Community Extensions:</p>
<ul>
<li>Modules that can be loaded into your scrpits</li>
<li>Open Source</li>
<li>Forums</li>
<li>Script contibutions</li>
</ul>
<p><a href="http://codeplex.com/vitoolkitextensions" target="_blank">Download it here</a>.</p>
<p><strong>Administrative Tasks made simple</strong></p>
<p>These are some of the tasks that I&#39;ve started using which has streamlined my job. I&#39;ve been able to change the VMware tools upgrade policy as every time I update ESX the tools become out-of-date. I&#39;ve used a number of cmdlets to create reports from Disk space usage to enumerating world wide names. I&#39;ve also executed scripts in response to VirtualCenter alarms. Check out the available resources above, there are so many ideas out there that will help you in managing your ESX environment using PowerShell.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.powershellpro.com/powershell-big-hit-at-vmworld-2008/259/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to Send Alerts to Your Mailbox using .NET</title>
		<link>http://www.powershellpro.com/powershell-email-alerts/210/</link>
		<comments>http://www.powershellpro.com/powershell-email-alerts/210/#comments</comments>
		<pubDate>Thu, 14 Aug 2008 18:11:13 +0000</pubDate>
		<dc:creator>Jesse Hamrick</dc:creator>
				<category><![CDATA[PowerShell Scripting]]></category>

		<guid isPermaLink="false">http://www.powershellpro.com/powershell-email-alerts/210/</guid>
		<description><![CDATA[I received a request from a colleague asking if I had a script that would poll a file and send him an email if a file&#39;s size became larger than 2k. Apparently they are using an application that was written by a friend-of-a-friend who is no longer in the Software Business so there is no [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.powershellpro.com/wp-content/uploads/mail.thumbnail.jpg" border="0" alt="Sending Email." title="Sending Email." align="left" />I received a request from a colleague asking if I had a script that would poll a file and send him an email if a file&#39;s size became larger than 2k. Apparently they are using an application that was written by a friend-of-a-friend who is no longer in the Software Business so there is no support for the product. How does this kind of stuff happen???</p>
<p>My reaction was wow! What happens when the file grows larger than 2k(yes you are reading this correctly, 2k)? My colleague replied, &quot;The app slows down, sometimes locks up, and users start to complain. Our course of action is to delete the file, the application regenerates it and we start all over again. Attempting to be pro-active, we periodically check the file size by manually browsing the file properties. Most of the time we are able to catch and fix the problem before the users are affected. It&#39;s just the times we miss all hell breaks loose.&quot; I said, &quot;I can help you with that issue&#8230;&quot;</p>
<p><span id="more-210"></span></p>
<p>Let&#39;s create an early warning system so that we are compliant with the famous buzz word &quot;Pro-Active!&quot;</p>
<p>First, the email template:</p>
<div class="codesnip-container" >
<p>#* =========================<br /> #* SMTP Mail Alert<br /> #* =========================</p>
<p>#* Create new .NET object and assign to variable<br /> $mail = New-Object System.Net.Mail.MailMessage</p>
<p>#* Sender Address<br /> $mail.From = New-Object System.Net.MailAddress(&quot;user@domain.com&quot;);</p>
<p>#* Recipient Address<br /> $mail.To.Add(&quot;user@domain.com&quot;);</p>
<p>#* Message Subject<br /> $mail.Subject = &quot;Place Subject of email here&quot;;</p>
<p>#* Message Body<br /> $mail.Body = &quot;Place body content here&quot;;</p>
<p>#* Connect to your mail server<br /> $smtp = New-Object System.Net.Mail.SmtpClient(&quot;yourdomain.com&quot;);</p>
<p>#* Uncomment line below if authentication is required<br /> #* $smtp.Credentials = New-Object System.Net.NetworkCredential(&quot;username&quot;, &quot;passwd&quot;);</p>
<p>#* Send Email<br /> $smtp.Send($mail);</p>
</div>
<p>Now that we have our template, let me explain how I provided a solution. Basically I created a script (shown below) that uses the email template as a function. When the script runs it enumerates the file size and based on the condition it either calls the mail function to send a warning or it does nothing. I set up a Windows task schedule to run the script every 15 minutes, times may vary depending on the situation.</p>
<p>AlertMe.ps1</p>
<div class="codesnip-container" >
<p>#* ======================<br /> #* Alert Me Script<br /> #* ======================<br /> #* Create Email Function<br /> #* ======================<br /> function sendEmail {</p>
<p>#* Create new .NET object and assign to variable<br /> $mail = New-Object System.Net.Mail.MailMessage</p>
<p>#* Sender Address<br /> $mail.From = New-Object System.Net.MailAddress(&quot;user@domain.com&quot;);</p>
<p>#* Recipient Address<br /> $mail.To.Add(&quot;user@domain.com&quot;);</p>
<p>#* Message Subject<br /> $mail.Subject = &quot;Place Subject of email here&quot;;</p>
<p>#* Message Body<br /> $mail.Body = &quot;Place body content here&quot;;</p>
<p>#* Connect to your mail server<br /> $smtp = New-Object System.Net.Mail.SmtpClient(&quot;yourdomain.com&quot;);</p>
<p>#* Uncomment line below if authentication is required<br /> #* $smtp.Credentials = New-Object System.Net.NetworkCredential(&quot;username&quot;, &quot;passwd&quot;);</p>
<p>#* Send Email<br /> $smtp.Send($mail);</p>
<p>}</p>
<p>#* =====================<br /> #* Script Body<br /> #* =====================</p>
<p>#* Connect to file. You can connect to a local file or a remote file via UNC.<br /> #* In this example I connect to a remote share<br /> $File = Get-ChildItem &quot;\\ServerName\ShareName\Path\File.txt&quot;</p>
<p>#* Check File size and take action based on condition.<br /> if ($File.Length -gt 2000)<br /> #* If condition is TRUE call sendEmail function<br /> {sendEmail}</p>
<p>#* If condition is FALSE script does nothing</p>
</div>
<p>The template can also be used to send warnings for: </p>
<ul>
<li>Disk Space Issues</li>
<li>CPU usage</li>
<li>Memory consumption</li>
<li>Runaway processes</li>
<li>Event Log monitoring</li>
</ul>
<p>Just to name a few, the possibilities are limitless&#8230;</p>
<p>Note: There is an email link embedded within this post, please visit this post to email it.&nbsp;</p>
<p> <script type="text/javascript"><!--
google_ad_client = "pub-7768408415611863";
google_ad_slot = "2413336635";
google_ad_width = 468;
google_ad_height = 15;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
]]></content:encoded>
			<wfw:commentRss>http://www.powershellpro.com/powershell-email-alerts/210/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Want a Free PowerShell Editor? No, Really it&#8217;s Free&#8230;</title>
		<link>http://www.powershellpro.com/powershell-tools-editor/202/</link>
		<comments>http://www.powershellpro.com/powershell-tools-editor/202/#comments</comments>
		<pubDate>Tue, 08 Jul 2008 18:44:25 +0000</pubDate>
		<dc:creator>Jesse Hamrick</dc:creator>
				<category><![CDATA[PowerShell Scripting]]></category>

		<guid isPermaLink="false">http://www.powershellpro.com/powershell-tools-editor/202/</guid>
		<description><![CDATA[I&#8217;ve been searching for a PowerShell editor to free me from writing my code in notepad. I&#8217;ve tried a number of them on the market, Primal Script by far was the best! Yet, my 45-day trial was over and my boss is dragging his feet with a purchase. So where do I turn?
Shell Tools was [...]]]></description>
			<content:encoded><![CDATA[<div class="wp-caption alignnone" style="width: 450px"><img style="border: 0pt none; margin: 2px;" title="PowerShell Tools PowerGui" src="http://www.powershellpro.com/wp-content/uploads/powergui.png" border="0" alt="PowerShell Tools PowerGui" width="440" height="330" align="right" /><p class="wp-caption-text">PowerShell Tools PowerGui</p></div>
<p>I&#8217;ve been searching for a PowerShell editor to free me from writing my code in notepad. I&#8217;ve tried a number of them on the market, Primal Script by far was the best! Yet, my 45-day trial was over and my boss is dragging his feet with a purchase. So where do I turn?</p>
<p>Shell Tools was nice, yet another 45-day trial (they extended it another 45-days) yet eventually leading to a purchase. Don&#8217;t get me wrong I&#8217;m not a tight-wad I&#8217;m a Tech (o.k. same thing&#8230;). I just wanted a simple editor which I found in the last place I thought I would ever look&#8230; A GUI Tool for PowerShell.</p>
<p>PowerShell Pro! adopted the philosophy of &#8220;teach an <span style="text-decoration: line-through;">man</span> person to fish&#8230;&#8221; so you would think that promoting a tool that &#8220;does the work for you&#8221; would be sacrilegious. Not being close minded, I ventured a download and began working with the tool. There were two major findings that prompted me to write this article&#8230;</p>
<p><span id="more-202"></span></p>
<p><strong>1. A Free PowerShell Script Editor</strong></p>
<p>This was actually found by mistake. I started exploring the PowerGUI interface and under the &#8220;Tools&#8221; menu there it was! It may not be as elegant as PrimalScript or other script editors designed for PowerShell but, it sure beats the heck out of notepad. Did I mention the cost? Free, nill, nada, null, zero, etc&#8230;</p>
<p><img style="border: 0pt none;" title="PowerShell PowerGui Editor" src="http://www.powershellpro.com/wp-content/uploads/pguiedit.JPG" border="0" alt="PowerShell PowerGui Editor" width="453" height="323" /></p>
<p>Some of the feature of the PowerGUI Script Editor:</p>
<ul>
<li>Debug code</li>
<li>Run code without debugging</li>
<li>Execute selected code</li>
<li>Run code to cursor</li>
</ul>
<p><strong>2. PowerGUI is a great learning Tool</strong></p>
<p>Don&#8217;t get me wrong, I love GUI tools but I don&#8217;t like to introduce them to those who are beginning to learn PowerShell. I prefer that you get your hands dirty under the hood, which PowerGUI allows you to do. Sure it writes code for you, it also enables you to view the script code written. This is a great way to study code; how it&#8217;s written and what it&#8217;s accomplishing.</p>
<p><img style="border: 0pt none;" src="http://www.powershellpro.com/wp-content/uploads/powerguitool.JPG" border="0" alt="PowerShell PowerGui Tool" width="452" height="402" /></p>
<p>There is actually another good reason to add PowerGUI to your PowerShell Scripting Tool set. The tool is free, no need to register, no 45-day trial period, and a library of functions you can download to extend PowerGUI&#8217;s capabilities.</p>
<p><a href="http://powergui.org" target="_blank">You can check it all out here.</a></p>
<p>Something to take note of:<br />
I have gotten a lot a flack about the article and tutorial I wrote regarding &#8220;Organizing Script Code&#8221; using modular scripting. The geeks flamed me for teaching the method of maintaining a Function Library and pasting the functions into a script file. They are all about Dot-Sourcing (which I am too&#8230;); for the right situation! Since the PowerGUI tools create one script based on your choices, notice that the code is built using the Modular approach that I taught&#8230;</p>
Note: There is an email link embedded within this post, please visit this post to email it.
<p><script type="text/javascript"><!--
google_ad_client = "pub-7768408415611863";
google_ad_slot = "2413336635";
google_ad_width = 468;
google_ad_height = 15;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</p>
]]></content:encoded>
			<wfw:commentRss>http://www.powershellpro.com/powershell-tools-editor/202/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>How to become a DIMM-wit!</title>
		<link>http://www.powershellpro.com/dimm-witt/200/</link>
		<comments>http://www.powershellpro.com/dimm-witt/200/#comments</comments>
		<pubDate>Wed, 18 Jun 2008 01:54:03 +0000</pubDate>
		<dc:creator>Jesse Hamrick</dc:creator>
				<category><![CDATA[PowerShell Scripting]]></category>

		<guid isPermaLink="false">http://www.powershellpro.com/dimm-witt/200/</guid>
		<description><![CDATA[
I was going through the mail-bag the other day and noticed the same question kept popping up. &#34;How do I know how much memory is in my system?&#34; I thought to myself, that question is too easy to answer and the PowerShell solution has to be available on at least a few thousand websites. But, [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.powershellpro.com/wp-content/uploads/ram.thumbnail.jpg" border="0" alt="PowerShell DIMM Sockets" title="PowerShell DIMM Sockets" align="left" />
<p>I was going through the mail-bag the other day and noticed the same question kept popping up. &quot;How do I know how much memory is in my system?&quot; I thought to myself, that question is too easy to answer and the PowerShell solution has to be available on at least a few thousand websites. But, in my haste to get through the mail the actual question was not sinking into my thick skull&#8230;</p>
<p>I was reading &quot;How much memory&quot; not &quot;How much memory is installed in my system and how many DIMM slots do I have available?&quot; Great question! Wouldn&#39;t it be nice to run a PowerShell Script that would give you the amount of RAM installed and the available slots in the system. How many of you still shut the server down, open the box, and inventory the DIMM count? Well those days are over&#8230;</p>
<p><span id="more-200"></span></p>
<p>Here is a simple script that will Inventory the total number of physical memory slots, the slots populated, and the size of each DIMM installed:</p>
<div class="codesnip-container" >
<p>$strComputer = Read-Host &quot;Enter Computer Name&quot;<br /> $colSlots = Get-WmiObject -Class &quot;win32_PhysicalMemoryArray&quot; -namespace &quot;root\CIMV2&quot; `<br /> -computerName $strComputer<br /> $colRAM = Get-WmiObject -Class &quot;win32_PhysicalMemory&quot; -namespace &quot;root\CIMV2&quot; `<br /> -computerName $strComputer</p>
<p> Foreach ($objSlot In $colSlots){<br /> &nbsp;&nbsp; &nbsp;&quot;Total Number of DIMM Slots: &quot; + $objSlot.MemoryDevices<br /> }<br /> Foreach ($objRAM In $colRAM) {<br /> &nbsp;&nbsp; &nbsp;&quot;Memory Installed: &quot; + $objRAM.DeviceLocator<br /> &nbsp;&nbsp; &nbsp;&quot;Memory Size: &quot; + ($objRAM.Capacity / 1GB) + &quot; GB&quot;<br /> }</p>
</div>
<p>Use this simple little script to check under the hood without actually shutting down the server to open the hood.</p>
<p>-Enjoy</p>
<p>Note: There is an email link embedded within this post, please visit this post to email it.&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.powershellpro.com/dimm-witt/200/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
