<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.whatsupduck.net/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" gd:etag="W/&quot;CUICRXg4eyp7ImA9WhFSFE8.&quot;"><id>tag:blogger.com,1999:blog-7728225756528319729</id><updated>2013-06-16T17:59:24.633-05:00</updated><category term="wcf" /><category term="apache" /><category term="net40" /><category term="iis" /><category term="authentication" /><category term="vmware" /><category term="security" /><category term="sdelete" /><category term="icinga-web" /><category term="icinga" /><category term="hacking" /><category term="memory" /><category term="msbuild" /><category term="Java" /><category term="access denied" /><category term="impersonation" /><category term="patches" /><category term="delegation" /><category term="ie" /><category term="binary" /><category term="sysinternals" /><category term="rest" /><category term="Tomcat" /><category term="ePO" /><category term="sharepoint" /><category term="sid" /><category term="sql" /><category term="powershell" /><category term="DRM" /><category term="Certificate" /><category term="source control" /><category term="Hang" /><category term="wds" /><category term="SSL" /><category term="esx" /><category term="dotnet" /><category term="exchange" /><category term="wsman" /><category term="timeout" /><category term="kerberos" /><category term="Silverlight" /><category term="windows deployment server" /><title>What's Up Duck</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blog.whatsupduck.net/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://blog.whatsupduck.net/" /><author><name>Chris Duck</name><uri>https://plus.google.com/111921112014612222144</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-hxGXvYzzwjM/AAAAAAAAAAI/AAAAAAAABZ4/NJmNBRF_ALc/s512-c/photo.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>19</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="whatsupduckblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.whatsupduck.net/WhatsUpDuckBlog" /><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.whatsupduck.net%2FWhatsUpDuckBlog" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.whatsupduck.net%2FWhatsUpDuckBlog" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.whatsupduck.net%2FWhatsUpDuckBlog" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.bloglines.com/sub/http://feeds.whatsupduck.net/WhatsUpDuckBlog" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.whatsupduck.net%2FWhatsUpDuckBlog" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.whatsupduck.net%2FWhatsUpDuckBlog" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.whatsupduck.net%2FWhatsUpDuckBlog" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.plusmo.com/add?url=http%3A%2F%2Ffeeds.whatsupduck.net%2FWhatsUpDuckBlog" src="http://plusmo.com/res/graphics/fbplusmo.gif">Subscribe with Plusmo</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.thefreedictionary.com/_/hp/AddRSS.aspx?http%3A%2F%2Ffeeds.whatsupduck.net%2FWhatsUpDuckBlog" src="http://img.tfd.com/hp/addToTheFreeDictionary.gif">Subscribe with The Free Dictionary</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.bitty.com/manual/?contenttype=rssfeed&amp;contentvalue=http%3A%2F%2Ffeeds.whatsupduck.net%2FWhatsUpDuckBlog" src="http://www.bitty.com/img/bittychicklet_91x17.gif">Subscribe with Bitty Browser</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.live.com/?add=http%3A%2F%2Ffeeds.whatsupduck.net%2FWhatsUpDuckBlog" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://mix.excite.eu/add?feedurl=http%3A%2F%2Ffeeds.whatsupduck.net%2FWhatsUpDuckBlog" src="http://image.excite.co.uk/mix/addtomix.gif">Subscribe with Excite MIX</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.webwag.com/wwgthis.php?url=http%3A%2F%2Ffeeds.whatsupduck.net%2FWhatsUpDuckBlog" src="http://www.webwag.com/images/wwgthis.gif">Subscribe with Webwag</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.podcastready.com/oneclick_bookmark.php?url=http%3A%2F%2Ffeeds.whatsupduck.net%2FWhatsUpDuckBlog" src="http://www.podcastready.com/images/podcastready_button.gif">Subscribe with Podcast Ready</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.wikio.com/subscribe?url=http%3A%2F%2Ffeeds.whatsupduck.net%2FWhatsUpDuckBlog" src="http://www.wikio.com/shared/img/add2wikio.gif">Subscribe with Wikio</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.dailyrotation.com/index.php?feed=http%3A%2F%2Ffeeds.whatsupduck.net%2FWhatsUpDuckBlog" src="http://www.dailyrotation.com/rss-dr2.gif">Subscribe with Daily Rotation</feedburner:feedFlare><entry gd:etag="W/&quot;CkQARXo7fCp7ImA9WhBbGU0.&quot;"><id>tag:blogger.com,1999:blog-7728225756528319729.post-4795088445066515581</id><published>2013-05-18T11:30:00.000-05:00</published><updated>2013-05-18T13:05:44.404-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-05-18T13:05:44.404-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="powershell" /><category scheme="http://www.blogger.com/atom/ns#" term="hacking" /><category scheme="http://www.blogger.com/atom/ns#" term="dotnet" /><title>Hacking ValidateSet</title><content type="html">&lt;p&gt;I guess I should start off this post by saying what I'm doing is a dirty hack, in no way supported, and in general a terrible idea.  But it's also really awesome.&lt;/p&gt;
&lt;p&gt;Occasionally I find it would be nice to be able to dynamically generate the values used in a &lt;span class='code'&gt;ValidateSet&lt;/span&gt; attribute on a function parameter.  Joel Bennett wrote a post a while back explaining how to build a &lt;a href="http://huddledmasses.org/better-error-messages-for-powershell-validatepattern/"&gt;custom validation attribute&lt;/a&gt; that could be written to include the ability to update the set list dynamically. Or you could even use his technique of using &lt;span class='code'&gt;ValidateScript&lt;/span&gt; and throwing a custom error message to generate the set dynamically.&lt;/p&gt;
&lt;p&gt;The problem with these other techniques is that &lt;span class='code'&gt;ValidateSet&lt;/span&gt; &lt;a href="http://blogs.msdn.com/b/powershell/archive/2006/05/10/594175.aspx"&gt;comes with magic&lt;/a&gt; that they don't include.  This magic provides tab-completion, error messages, and a listing of valid values in help, all for free.  I actually started off my experiment by following Joel's post and implementing my own &lt;span class='code'&gt;ValidateDynamicSetAttribute&lt;/span&gt; class that provided &lt;span class='code'&gt;Add()&lt;/span&gt; and &lt;span class='code'&gt;Remove()&lt;/span&gt; methods so the values could be changed on the fly.&lt;/p&gt;
&lt;p&gt;But that class wouldn't have come with the magic of &lt;span class='code'&gt;ValidateSet&lt;/span&gt;, and while I was using ILSpy to learn how &lt;span class='code'&gt;ValidateSet&lt;/span&gt; was implemented, I discovered that it was based on a private string array and it turns out I had just learned how to access private members while I was at the PowerShell Summit 2013 (thanks Adam!).&lt;/p&gt;
&lt;p&gt;The result is the following function that takes a FunctionInfo object (use &lt;span class='code'&gt;Get-Command&lt;/span&gt;), the name of the parameter that is using &lt;span class='code'&gt;ValidateSet&lt;/span&gt;, and the new set of valid inputs.  It hacks its way into the command, locates the correct parameter, locates all the &lt;span class='code'&gt;ValidateSet&lt;/span&gt; attributes on it, and rips into the heart of each one and replaces the private &lt;span class='code'&gt;validValues&lt;/span&gt; array with the one provided in the &lt;span class='code'&gt;-NewSet&lt;/span&gt; parameter.&lt;/p&gt;
&lt;!--Start Script--&gt;
&lt;div class="embedded-code-wrapper"&gt;
&lt;table border="0" cellpadding="5" cellspacing="0"&gt; 
&lt;tbody&gt;
&lt;tr&gt; 
    &lt;td valign="Top"&gt;&lt;div class="line-no-column"&gt;
001&lt;br /&gt;002&lt;br /&gt;003&lt;br /&gt;004&lt;br /&gt;005&lt;br /&gt;006&lt;br /&gt;007&lt;br /&gt;008&lt;br /&gt;009&lt;br /&gt;010&lt;br /&gt;011&lt;br /&gt;012&lt;br /&gt;013&lt;br /&gt;014&lt;br /&gt;015&lt;br /&gt;016&lt;br /&gt;017&lt;br /&gt;018&lt;br /&gt;019&lt;br /&gt;020&lt;br /&gt;021&lt;br /&gt;022&lt;br /&gt;023&lt;br /&gt;024&lt;br /&gt;025&lt;br /&gt;026&lt;br /&gt;027&lt;br /&gt;028&lt;br /&gt;029&lt;br /&gt;030&lt;br /&gt;031&lt;br /&gt;032&lt;br /&gt;033&lt;br /&gt;034&lt;br /&gt;035&lt;br /&gt;036&lt;br /&gt;037&lt;br /&gt;038&lt;br /&gt;039&lt;br /&gt;040&lt;br /&gt;041&lt;br /&gt;042&lt;br /&gt;043&lt;br /&gt;044&lt;br /&gt;045&lt;br /&gt;046&lt;br /&gt;047&lt;br /&gt;048&lt;br /&gt;049&lt;br /&gt;050&lt;br /&gt;051&lt;br /&gt;052&lt;br /&gt;053&lt;br /&gt;054&lt;br /&gt;055&lt;br /&gt;056&lt;br /&gt;057&lt;br /&gt;058&lt;br /&gt;059&lt;br /&gt;060&lt;br /&gt;061&lt;br /&gt;062&lt;br /&gt;063&lt;br /&gt;064&lt;br /&gt;065&lt;br /&gt;066&lt;br /&gt;067&lt;br /&gt;068&lt;br /&gt;069&lt;br /&gt;070&lt;br /&gt;071&lt;br /&gt;072&lt;br /&gt;073&lt;br /&gt;074&lt;br /&gt;075&lt;br /&gt;076&lt;br /&gt;077&lt;br /&gt;078&lt;br /&gt;079&lt;br /&gt;080&lt;br /&gt;081&lt;br /&gt;082&lt;br /&gt;083&lt;br /&gt;084&lt;br /&gt;085&lt;br /&gt;
&lt;/div&gt;
&lt;/td&gt; 
    &lt;td nowrap="NOWRAP" valign="Top"&gt;&lt;div class="embedded-code-body"&gt;&lt;span class="psComment"&gt;&amp;lt;#
&amp;nbsp;&amp;nbsp;.SYNOPSIS
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Replace the set of valid values on a funciton parameter that was defined
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;using ValidateSet.

&amp;nbsp;&amp;nbsp;.DESCRIPTION
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Replace the set of valid values on a funciton parameter that was defined
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;using ValidateSet.

&amp;nbsp;&amp;nbsp;.PARAMETER  Command
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;A FunctionInfo object for the command that has the parameter validation to
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;be updated.  Get this using:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Get-Command -Name YourCommandName

&amp;nbsp;&amp;nbsp;.PARAMETER  ParameterName
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;The name of the parameter that is using ValidateSet.
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;.PARAMETER  NewSet
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;The new set of valid values to use for parameter validation.

&amp;nbsp;&amp;nbsp;.EXAMPLE
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Define a test function:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PS&amp;gt; Function Test-Function {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;param(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[ValidateSet("one")]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$P
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PS&amp;gt; Update-ValidateSet -Command (Get-Command Test-Function) -ParameterName "P" -NewSet @("one","two")
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;After running Update-ValidateSet, Test-Function will accept the values "one"
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;and "two" as valid input for the -P parameter.

&amp;nbsp;&amp;nbsp;.OUTPUTS
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Nothing

&amp;nbsp;&amp;nbsp;.NOTES
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;This function is updating a private member of ValidateSetAttribute and is
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;thus not following the rules of .Net and could break at any time.  Use at
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;your own risk!
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Author : Chris Duck

&amp;nbsp;&amp;nbsp;.LINK
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;http://blog.whatsupduck.net/2013/05/hacking-validateset.html
#&amp;gt;&lt;/span&gt;
&lt;span class="psKeyword"&gt;function&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psCommandArgument"&gt;Update-ValidateSet&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psGroupStart"&gt;{&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psOperator"&gt;[&lt;/span&gt;&lt;span class="psAttribute"&gt;CmdletBinding&lt;/span&gt;&lt;span class="psGroupStart"&gt;(&lt;/span&gt;&lt;span class="psMember"&gt;SupportsShouldProcess&lt;/span&gt;&lt;span class="psOperator"&gt;=&lt;/span&gt;&lt;span class="psVariable"&gt;$true&lt;/span&gt;&lt;span class="psGroupEnd"&gt;)&lt;/span&gt;&lt;span class="psOperator"&gt;]&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psKeyword"&gt;param&lt;/span&gt;&lt;span class="psGroupStart"&gt;(&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psOperator"&gt;[&lt;/span&gt;&lt;span class="psAttribute"&gt;Parameter&lt;/span&gt;&lt;span class="psGroupStart"&gt;(&lt;/span&gt;&lt;span class="psMember"&gt;Mandatory&lt;/span&gt;&lt;span class="psOperator"&gt;=&lt;/span&gt;&lt;span class="psVariable"&gt;$true&lt;/span&gt;&lt;span class="psGroupEnd"&gt;)&lt;/span&gt;&lt;span class="psOperator"&gt;]&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psOperator"&gt;[&lt;/span&gt;&lt;span class="psAttribute"&gt;ValidateNotNullOrEmpty&lt;/span&gt;&lt;span class="psGroupStart"&gt;(&lt;/span&gt;&lt;span class="psGroupEnd"&gt;)&lt;/span&gt;&lt;span class="psOperator"&gt;]&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psType"&gt;[System.Management.Automation.FunctionInfo]&lt;/span&gt;&lt;span class="psVariable"&gt;$Command&lt;/span&gt;&lt;span class="psOperator"&gt;,&lt;/span&gt;

&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psOperator"&gt;[&lt;/span&gt;&lt;span class="psAttribute"&gt;Parameter&lt;/span&gt;&lt;span class="psGroupStart"&gt;(&lt;/span&gt;&lt;span class="psMember"&gt;Mandatory&lt;/span&gt;&lt;span class="psOperator"&gt;=&lt;/span&gt;&lt;span class="psVariable"&gt;$true&lt;/span&gt;&lt;span class="psGroupEnd"&gt;)&lt;/span&gt;&lt;span class="psOperator"&gt;]&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psOperator"&gt;[&lt;/span&gt;&lt;span class="psAttribute"&gt;ValidateNotNullOrEmpty&lt;/span&gt;&lt;span class="psGroupStart"&gt;(&lt;/span&gt;&lt;span class="psGroupEnd"&gt;)&lt;/span&gt;&lt;span class="psOperator"&gt;]&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psType"&gt;[string]&lt;/span&gt;&lt;span class="psVariable"&gt;$ParameterName&lt;/span&gt;&lt;span class="psOperator"&gt;,&lt;/span&gt;

&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psOperator"&gt;[&lt;/span&gt;&lt;span class="psAttribute"&gt;Parameter&lt;/span&gt;&lt;span class="psGroupStart"&gt;(&lt;/span&gt;&lt;span class="psMember"&gt;Mandatory&lt;/span&gt;&lt;span class="psOperator"&gt;=&lt;/span&gt;&lt;span class="psVariable"&gt;$true&lt;/span&gt;&lt;span class="psGroupEnd"&gt;)&lt;/span&gt;&lt;span class="psOperator"&gt;]&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psOperator"&gt;[&lt;/span&gt;&lt;span class="psAttribute"&gt;ValidateNotNullOrEmpty&lt;/span&gt;&lt;span class="psGroupStart"&gt;(&lt;/span&gt;&lt;span class="psGroupEnd"&gt;)&lt;/span&gt;&lt;span class="psOperator"&gt;]&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psType"&gt;[String[]]&lt;/span&gt;&lt;span class="psVariable"&gt;$NewSet&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psGroupEnd"&gt;)&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psComment"&gt;#Find the parameter on the command object&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psVariable"&gt;$Parameter&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psOperator"&gt;=&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psVariable"&gt;$Command&lt;/span&gt;&lt;span class="psOperator"&gt;.&lt;/span&gt;&lt;span class="psMember"&gt;Parameters&lt;/span&gt;&lt;span class="psOperator"&gt;[&lt;/span&gt;&lt;span class="psVariable"&gt;$ParameterName&lt;/span&gt;&lt;span class="psOperator"&gt;]&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psKeyword"&gt;if&lt;/span&gt;&lt;span class="psGroupStart"&gt;(&lt;/span&gt;&lt;span class="psVariable"&gt;$Parameter&lt;/span&gt;&lt;span class="psGroupEnd"&gt;)&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psGroupStart"&gt;{&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psComment"&gt;#Find all of the ValidateSet attributes on the parameter&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psVariable"&gt;$ValidateSetAttributes&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psOperator"&gt;=&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psGroupStart"&gt;@(&lt;/span&gt;&lt;span class="psVariable"&gt;$Parameter&lt;/span&gt;&lt;span class="psOperator"&gt;.&lt;/span&gt;&lt;span class="psMember"&gt;Attributes&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psOperator"&gt;|&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psCommand"&gt;Where-Object&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psGroupStart"&gt;{&lt;/span&gt;&lt;span class="psVariable"&gt;$_&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psOperator"&gt;-is&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psType"&gt;[System.Management.Automation.ValidateSetAttribute]&lt;/span&gt;&lt;span class="psGroupEnd"&gt;}&lt;/span&gt;&lt;span class="psGroupEnd"&gt;)&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psKeyword"&gt;if&lt;/span&gt;&lt;span class="psGroupStart"&gt;(&lt;/span&gt;&lt;span class="psVariable"&gt;$ValidateSetAttributes&lt;/span&gt;&lt;span class="psGroupEnd"&gt;)&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psGroupStart"&gt;{&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psVariable"&gt;$ValidateSetAttributes&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psOperator"&gt;|&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psCommand"&gt;ForEach-Object&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psGroupStart"&gt;{&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psComment"&gt;#Get the validValues private member of the ValidateSetAttribute class&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psVariable"&gt;$ValidValuesField&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psOperator"&gt;=&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psType"&gt;[System.Management.Automation.ValidateSetAttribute]&lt;/span&gt;&lt;span class="psOperator"&gt;.&lt;/span&gt;&lt;span class="psMember"&gt;GetField&lt;/span&gt;&lt;span class="psGroupStart"&gt;(&lt;/span&gt;&lt;span class="psString"&gt;"validValues"&lt;/span&gt;&lt;span class="psOperator"&gt;,&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psType"&gt;[System.Reflection.BindingFlags]&lt;/span&gt;&lt;span class="psOperator"&gt;::&lt;/span&gt;&lt;span class="psMember"&gt;NonPublic&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psOperator"&gt;-bor&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psType"&gt;[System.Reflection.BindingFlags]&lt;/span&gt;&lt;span class="psOperator"&gt;::&lt;/span&gt;&lt;span class="psMember"&gt;Instance&lt;/span&gt;&lt;span class="psGroupEnd"&gt;)&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psKeyword"&gt;if&lt;/span&gt;&lt;span class="psGroupStart"&gt;(&lt;/span&gt;&lt;span class="psVariable"&gt;$PsCmdlet&lt;/span&gt;&lt;span class="psOperator"&gt;.&lt;/span&gt;&lt;span class="psMember"&gt;ShouldProcess&lt;/span&gt;&lt;span class="psGroupStart"&gt;(&lt;/span&gt;&lt;span class="psString"&gt;"$Command -$ParameterName"&lt;/span&gt;&lt;span class="psOperator"&gt;,&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psString"&gt;"Set valid set to: $($NewSet -join ', ')"&lt;/span&gt;&lt;span class="psGroupEnd"&gt;)&lt;/span&gt;&lt;span class="psGroupEnd"&gt;)&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psGroupStart"&gt;{&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psComment"&gt;#Update the validValues array on each instance of ValidateSetAttribute&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psVariable"&gt;$ValidValuesField&lt;/span&gt;&lt;span class="psOperator"&gt;.&lt;/span&gt;&lt;span class="psMember"&gt;SetValue&lt;/span&gt;&lt;span class="psGroupStart"&gt;(&lt;/span&gt;&lt;span class="psVariable"&gt;$_&lt;/span&gt;&lt;span class="psOperator"&gt;,&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psVariable"&gt;$NewSet&lt;/span&gt;&lt;span class="psGroupEnd"&gt;)&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psGroupEnd"&gt;}&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psGroupEnd"&gt;}&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psGroupEnd"&gt;}&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psKeyword"&gt;else&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psGroupStart"&gt;{&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psCommand"&gt;Write-Error&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psCommandParameter"&gt;-Message&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psString"&gt;"Parameter $ParameterName in command $Command doesn't use [ValidateSet()]"&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psGroupEnd"&gt;}&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psGroupEnd"&gt;}&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psKeyword"&gt;else&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psGroupStart"&gt;{&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psCommand"&gt;Write-Error&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psCommandParameter"&gt;-Message&lt;/span&gt;&lt;span class="psUnknown"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="psString"&gt;"Parameter $ParameterName was not found in command $Command"&lt;/span&gt;
&lt;span class="psUnknown"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="psGroupEnd"&gt;}&lt;/span&gt;
&lt;span class="psGroupEnd"&gt;}&lt;/span&gt; 
&lt;/div&gt;
&lt;/td&gt; 
&lt;/tr&gt;
&lt;/tbody&gt; 
&lt;/table&gt;
&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=0wwNTvACcc4:VcgiJaTrWx8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=0wwNTvACcc4:VcgiJaTrWx8:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=0wwNTvACcc4:VcgiJaTrWx8:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=0wwNTvACcc4:VcgiJaTrWx8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=0wwNTvACcc4:VcgiJaTrWx8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=0wwNTvACcc4:VcgiJaTrWx8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=0wwNTvACcc4:VcgiJaTrWx8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=0wwNTvACcc4:VcgiJaTrWx8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatsUpDuckBlog/~4/0wwNTvACcc4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.whatsupduck.net/feeds/4795088445066515581/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.whatsupduck.net/2013/05/hacking-validateset.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/4795088445066515581?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/4795088445066515581?v=2" /><link rel="alternate" type="text/html" href="http://blog.whatsupduck.net/2013/05/hacking-validateset.html" title="Hacking ValidateSet" /><author><name>Chris Duck</name><uri>https://plus.google.com/111921112014612222144</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-hxGXvYzzwjM/AAAAAAAAAAI/AAAAAAAABZ4/NJmNBRF_ALc/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DkcBQngyfSp7ImA9WhBREEw.&quot;"><id>tag:blogger.com,1999:blog-7728225756528319729.post-96141830321789996</id><published>2013-02-21T23:00:00.000-06:00</published><updated>2013-02-27T19:14:13.695-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-27T19:14:13.695-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="powershell" /><category scheme="http://www.blogger.com/atom/ns#" term="sharepoint" /><title>SharePoint 2007 Wiki Pages Broken</title><content type="html">&lt;p&gt;One of our SharePoint wiki libraries got in a state where we couldn't edit any of the pages.  When we clicked "Edit" we would get the document properties page instead of the wiki editor page.  I believe the root cause was someone moving a page from another wiki and the page ended up in the library as a "document" instead of a "wiki page".&lt;/p&gt;
&lt;p&gt;I found a solution &lt;a href="http://social.technet.microsoft.com/forums/en-US/sharepointgenerallegacy/thread/99b145bb-2c31-4bdd-8f52-060936ec5b97"&gt;here&lt;/a&gt;, but it required installing SharePoint Manager 2007 in order to change the &lt;span class="code"&gt;ContentTypesEnabled&lt;/span&gt; property on the list.  I wasn't really wanting to install any additional software, so I set out to determine if there was a way to modify the property using the SharePoint API, and it turns out there is.&lt;/p&gt;
&lt;p&gt;The following script uses the SharePoint API to modify your list properties to enable the content types UI elements in your list settings in order to clean up your wiki content types.  I ran it from a SharePoint server in my farm, I assume it's possible to run remotely but have no idea how that would be done.&lt;/p&gt;
&lt;!--Start Script--&gt;
&lt;div class='embedded-code-wrapper'&gt;
&lt;TABLE BORDER='0' cellpadding='5' cellspacing='0'&gt; 
&lt;TR&gt; 
    &lt;TD VALIGN='Top'&gt;&lt;div class='line-no-column'&gt;001&lt;BR /&gt;002&lt;BR /&gt;003&lt;BR /&gt;004&lt;BR /&gt;005&lt;BR /&gt;006&lt;BR /&gt;
&lt;/DIV&gt; 
    &lt;/TD&gt; 
    &lt;TD VALIGN='Top' NOWRAP='NOWRAP'&gt;&lt;div class='embedded-code-body'&gt;&lt;span class='psType'&gt;[reflection.assembly]&lt;/span&gt;&lt;span class='psOperator'&gt;::&lt;/span&gt;&lt;span class='psMember'&gt;LoadWithPartialName&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;Microsoft.SharePoint&amp;quot;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psVariable'&gt;$Site&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psType'&gt;[Microsoft.SharePoint.SPSite]&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;http://site.com&amp;quot;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psVariable'&gt;$Web&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$Site&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;OpenWeb&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;pat/to/web&amp;quot;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psVariable'&gt;$WikiList&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$Web&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Lists&lt;/span&gt;&lt;span class='psOperator'&gt;[&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;WikiListName&amp;quot;&lt;/span&gt;&lt;span class='psOperator'&gt;]&lt;/span&gt;
&lt;span class='psVariable'&gt;$WikiList&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;ContentTypesEnabled&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$true&lt;/span&gt;
&lt;span class='psVariable'&gt;$WikiList&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Update&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt; 
&lt;/DIV&gt; 
    &lt;/TD&gt; 
&lt;/TR&gt; 
&lt;/TBODY&gt; 
&lt;/TABLE&gt; 
&lt;/DIV&gt;
&lt;!--End Script--&gt;
&lt;p&gt;With this script, you can follow the instructions linked above to fix the content types on your existing documents, using the script instead of SharePoint Manager to enable editing the content types on your wiki library.  Then you can delete the "Document" content type from your library.&lt;/p&gt;
&lt;p&gt;After you have everything cleaned up, you can run the following script to return your wiki library to the default configuration.&lt;/p&gt;
&lt;!--Start Script--&gt;
&lt;div class='embedded-code-wrapper'&gt;
&lt;TABLE BORDER='0' cellpadding='5' cellspacing='0'&gt; 
&lt;TR&gt; 
    &lt;TD VALIGN='Top'&gt;&lt;div class='line-no-column'&gt;001&lt;BR /&gt;002&lt;BR /&gt;003&lt;BR /&gt;004&lt;BR /&gt;005&lt;BR /&gt;006&lt;BR /&gt;
&lt;/DIV&gt; 
    &lt;/TD&gt; 
    &lt;TD VALIGN='Top' NOWRAP='NOWRAP'&gt;&lt;div class='embedded-code-body'&gt;&lt;span class='psType'&gt;[reflection.assembly]&lt;/span&gt;&lt;span class='psOperator'&gt;::&lt;/span&gt;&lt;span class='psMember'&gt;LoadWithPartialName&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;Microsoft.SharePoint&amp;quot;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psVariable'&gt;$Site&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psType'&gt;[Microsoft.SharePoint.SPSite]&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;http://site.com&amp;quot;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psVariable'&gt;$Web&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$Site&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;OpenWeb&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;pat/to/web&amp;quot;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psVariable'&gt;$WikiList&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$Web&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Lists&lt;/span&gt;&lt;span class='psOperator'&gt;[&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;WikiListName&amp;quot;&lt;/span&gt;&lt;span class='psOperator'&gt;]&lt;/span&gt;
&lt;span class='psVariable'&gt;$WikiList&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;ContentTypesEnabled&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$false&lt;/span&gt;
&lt;span class='psVariable'&gt;$WikiList&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Update&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt; 
&lt;/DIV&gt; 
    &lt;/TD&gt; 
&lt;/TR&gt; 
&lt;/TBODY&gt; 
&lt;/TABLE&gt; 
&lt;/DIV&gt;
&lt;!--End Script--&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=bnMc4mV8KtM:yO5eSo1uy38:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=bnMc4mV8KtM:yO5eSo1uy38:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=bnMc4mV8KtM:yO5eSo1uy38:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=bnMc4mV8KtM:yO5eSo1uy38:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=bnMc4mV8KtM:yO5eSo1uy38:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=bnMc4mV8KtM:yO5eSo1uy38:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=bnMc4mV8KtM:yO5eSo1uy38:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=bnMc4mV8KtM:yO5eSo1uy38:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatsUpDuckBlog/~4/bnMc4mV8KtM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.whatsupduck.net/feeds/96141830321789996/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.whatsupduck.net/2013/02/sharepoint-2007-wiki-pages-broken.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/96141830321789996?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/96141830321789996?v=2" /><link rel="alternate" type="text/html" href="http://blog.whatsupduck.net/2013/02/sharepoint-2007-wiki-pages-broken.html" title="SharePoint 2007 Wiki Pages Broken" /><author><name>Chris Duck</name><uri>https://plus.google.com/111921112014612222144</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-hxGXvYzzwjM/AAAAAAAAAAI/AAAAAAAABZ4/NJmNBRF_ALc/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CU4HQHg5eSp7ImA9WhJUFkU.&quot;"><id>tag:blogger.com,1999:blog-7728225756528319729.post-6765965384449565529</id><published>2012-04-05T17:38:00.000-05:00</published><updated>2012-09-14T23:38:51.621-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-09-14T23:38:51.621-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="wds" /><category scheme="http://www.blogger.com/atom/ns#" term="windows deployment server" /><title>Deploying WDS Across Domain Forests</title><content type="html">&lt;p&gt;I'm not going to cover how to setup your unattend file, or how to customize a PE image... there are plenty of people out there who have covered those topics.  What I do want to cover here is how to edit your PE image so that you can force it to connect to a specific WDS server.  This will help solve the problem where you want to deploy computers into two domains on the same subnet, but WDS only looks for prestaged computers objects on the domain it is joined to.&lt;/p&gt;
&lt;p&gt;This process does require two WDS servers, one joined to each domain you want to deploy computers into.  I'm going to refer to them as WDSPrimary and WDSSecondary.  I'm assuming you have either WDSPrimary configured to listen to broadcast requests, or your DHCP server options 66 and 67 pointed at WDSPrimary and boot\x64\wdsnbp.com respectively.  The challenge is to be able to add a boot image on WDSPrimary that tells setup.exe to contact WDSSecondary to deploy the image.&lt;/p&gt;
&lt;h3&gt;Extract Your Existing Boot Image&lt;/h3&gt;
&lt;p&gt;Assuming you already have a boot image customized for deploying to WDSPrimary, export that image to a work folder using the Windows Deployment Services management console.  For this example, I'm going to use c:\PEBoot\SecondaryBoot.wim as the extracted file name.&lt;/p&gt;
&lt;h3&gt;Mount the Image&lt;/h3&gt;
&lt;p&gt;Using Windows 7 or Server 2008 R2, first create a mount folder to mount the wim image to.  I'll use c:\PEBoot\mount.  Then run the following command to mount the image (remember to launch your shell as Administrator)&lt;/p&gt;
&lt;div style="overflow-x: auto; white-space: nowrap;"&gt;&lt;span class="code" &gt;dism /mount-wim /mountdir:c:\PEBoot\mount /wimfile:c:\PEBoot\SecondaryBoot.wim /index:2&lt;/span&gt;&lt;/div&gt;
&lt;h3&gt;Configure the PE Image&lt;/h3&gt;
&lt;p&gt;Window PE includes a file called &lt;a href="http://technet.microsoft.com/en-us/library/dd744560(WS.10).aspx"&gt;winpeshl.ini&lt;/a&gt; (&lt;a href="http://technet.microsoft.com/en-us/library/hh825046.aspx"&gt;Win 8/2012 version&lt;/a&gt;) that you can use to specify custom applications to run instead of starting setup.exe automatically.  We will use this file to start &lt;a href="http://technet.microsoft.com/en-us/library/dd799264(WS.10).aspx"&gt;setup.exe with custom options&lt;/a&gt; that will tell it to connect to WDSSecondary instead of defaulting to the WDS server that it booted from (WDSPrimary).&lt;/p&gt;
&lt;p&gt;Open notepad and create a new file with the following contents&lt;/p&gt;
&lt;span class="code" style="white-space: nowrap;"&gt;[LaunchApps]&lt;br /&gt;
%SYSTEMDRIVE%\windows\system32\wpeinit.exe&lt;br /&gt;
%SYSTEMDRIVE%\setup.exe, "/wds /wdsdiscover /wdsserver:WDSSecondary.contoso.com"&lt;br /&gt;
&lt;/span&gt;
&lt;p&gt;Make sure you enclose multiple command-line parameters in double quotes when you specify them in winpeshl.ini or they will not be properly passed to the command.&lt;/p&gt;
&lt;h3&gt;Unmount the PE Image and Import it into WDS&lt;/h3&gt;
&lt;p&gt;Now we need to unmount the wim file and commit our changes.  This is accomplished using the following command.&lt;/p&gt;
&lt;div style="overflow-x: auto; white-space: nowrap;"&gt;&lt;span class="code"&gt;dism /unmount-wim /mountdir:c:\PEBoot\mount /commit&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;Now all that is left is to import the new boot image into the primary WDS server that all clients boot to.  In this case, you would go to WDSPrimary and right click "Boot Images" and select "Add Boot Image".  Now when you PXE boot, you will have an option to boot to the customized image that connects to WDSSecondary to deploy the operating system.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=lVQk5uo8DnM:AsFPvlmi3C0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=lVQk5uo8DnM:AsFPvlmi3C0:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=lVQk5uo8DnM:AsFPvlmi3C0:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=lVQk5uo8DnM:AsFPvlmi3C0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=lVQk5uo8DnM:AsFPvlmi3C0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=lVQk5uo8DnM:AsFPvlmi3C0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=lVQk5uo8DnM:AsFPvlmi3C0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=lVQk5uo8DnM:AsFPvlmi3C0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatsUpDuckBlog/~4/lVQk5uo8DnM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.whatsupduck.net/feeds/6765965384449565529/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.whatsupduck.net/2012/04/deploying-wds-across-domain-forests.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/6765965384449565529?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/6765965384449565529?v=2" /><link rel="alternate" type="text/html" href="http://blog.whatsupduck.net/2012/04/deploying-wds-across-domain-forests.html" title="Deploying WDS Across Domain Forests" /><author><name>Chris Duck</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;A0YFQ3g8cSp7ImA9WhBREE0.&quot;"><id>tag:blogger.com,1999:blog-7728225756528319729.post-8449471903141399299</id><published>2012-03-23T01:01:00.000-05:00</published><updated>2013-02-27T17:51:52.679-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-27T17:51:52.679-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="powershell" /><title>Re: Zero out Free Disk Space</title><content type="html">&lt;p&gt;We've been having weekly script club meetings at work where anyone who is interested gets together in a conference room and we all work on scripts together so we all have a chance to learn new techniques while solving our real-world problems at the same time.  This week I developed a script to mimic the behavior of the SysInternals utility SDelete.  The script will be used to reclaim thin-provisioned space from our SAN, and I wanted to develop it during script club to use as an example of how to use the classes in the System.IO namespace to get better IO performance from PowerShell.&lt;/p&gt;
&lt;p&gt;One of my co-workers shared the script from the meeting with Don Jones and he was nice enough to post it on &lt;a href="http://powershell.com/cs/blogs/donjones/archive/2012/03/22/zero-out-free-disk-space.aspx"&gt;his blog&lt;/a&gt; along with a few comments about the script.&lt;/p&gt;
&lt;p&gt;Don's blog doesn't seem to support public comments, so I wanted to take a few minutes to respond to his comments here.  I've reproduced his comments (in italics below) along with my responses:&lt;/p&gt;
&lt;dl&gt;
  &lt;dt&gt;&lt;i&gt;I wish the comment-based help was a bit more complete, but I love that they're using it!&lt;/i&gt;&lt;/dt&gt;
  &lt;dd&gt;This script was written in a "class" setting and I was focusing more on solving the task at hand than producing a share-able script.  The parameter block and help content were actually thrown in at the very end of the session just as a quick "finishing touch" and were never even run.  I agree that well documented scripts are important and I try to write more complete help on my scripts when I don't have an audience watching me code :)&lt;/dd&gt;
  &lt;dt&gt;&lt;i&gt;They're overriding $PercentFree to always be 0.5 - not sure if that's on purpose&lt;/i&gt;&lt;/dt&gt;
  &lt;dd&gt;This is a bug due to the way I'm trying to teach programming at work.  I've been encouraging people to use variables for things even when they are just starting a script and are still in "explore" mode, with the idea that this makes it easy to turn the script into a function just by deleting the explicit variable declarations and moving them up to a parameter block.&lt;/dd&gt;
  &lt;dt&gt;&lt;i&gt;Yay! Error handling!&lt;/i&gt;&lt;/dt&gt;
  &lt;dd&gt;I really wanted to take the opportunity to highlight the proper way to deal with external resources (ie file handles, network ports, etc) for my team.  I see a lot of people who either don't bother to close things or don't put the close statements in a finally block and end up leaking resources.&lt;/dd&gt;
  &lt;dt&gt;&lt;i&gt;Yay! Variable-replacement-within-double-quotes instead of concatenation!&lt;/i&gt;&lt;/dt&gt;
  &lt;dt&gt;&lt;i&gt;Really brilliant technique of creating an empty file and then deleting it - clever thinking.&lt;/i&gt;&lt;/dt&gt;
  &lt;dd&gt;Can't really take credit for this one, just replicating the way sdelete works :)&lt;/dd&gt;
  &lt;dt&gt;&lt;i&gt;Kind of a lot of variables. Like, why put 64KB into $ArraySize, and then only use it once? Why not use use the literal 64KB? Doing so would make the script a bit more concise and possibly easier to read.&lt;/i&gt;&lt;/dt&gt;
  &lt;dd&gt;This again comes from my programming style.  At the time I thought there was potential we might want to make $ArraySize a parameter so I built it from the start so that it would be easy to convert down the line if we decided to go that way.  Also I wanted to make it very easy to modify so we could do some performance testing to determine what the optimal block size to write was. In general I try to avoid hard coding any values into the meat of my scripts to make them easier to modify if the needs change down the road.&lt;/dd&gt;
&lt;/dl&gt;
&lt;h3&gt;After Further Review&lt;/h3&gt;
&lt;p&gt;The script that Don was kind enough to review was written live during class and I never even got to the point of saving the script to a file in my editor, much less cleaning it up to make it "enterprise class" or "share worthy".  Some other rough areas I have noticed in it after having time to review it are:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;It should probably test to make sure the file doesn't exist already so it doesn't clobber existing data&lt;/li&gt;
  &lt;li&gt;It should test to make sure the $Root path/volume exists&lt;/li&gt;
  &lt;li&gt;It should validate that $PercentFree is between 0 and 1&lt;/li&gt;
  &lt;li&gt;The delete command should probably be moved up into the finally block to ensure the file gets deleted&lt;/li&gt;
  &lt;li&gt;I also would consider putting the whole thing in a process block, adding a "Name" alias to $Root, and enabling "ValueFromPipelineByPropertyName" so you could do:&lt;br /&gt;&lt;br /&gt;
    &lt;span class="code"&gt;gwmi Win32_Volume | Write-ZeroesToFreeSpace&lt;/span&gt;
  &lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;The "Real" Script&lt;/h3&gt;
&lt;p&gt;I've sort of posted these last two blog entries in reverse order, as my &lt;a href="http://blog.whatsupduck.net/2012/03/powershell-alternative-to-sdelete.html"&gt;previous post&lt;/a&gt; is the cleaned up version of the script that addresses Don's comments as well as my additional comments posted above.&lt;/p&gt;
&lt;p&gt;Thanks again Don for taking the time to review our little script and give us the opportunity to share a little bit of our development process with the community!&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=V2udPTS-6ns:tF8bWbS75O8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=V2udPTS-6ns:tF8bWbS75O8:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=V2udPTS-6ns:tF8bWbS75O8:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=V2udPTS-6ns:tF8bWbS75O8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=V2udPTS-6ns:tF8bWbS75O8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=V2udPTS-6ns:tF8bWbS75O8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=V2udPTS-6ns:tF8bWbS75O8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=V2udPTS-6ns:tF8bWbS75O8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatsUpDuckBlog/~4/V2udPTS-6ns" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.whatsupduck.net/feeds/8449471903141399299/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.whatsupduck.net/2012/03/re-zero-out-free-disk-space.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/8449471903141399299?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/8449471903141399299?v=2" /><link rel="alternate" type="text/html" href="http://blog.whatsupduck.net/2012/03/re-zero-out-free-disk-space.html" title="Re: Zero out Free Disk Space" /><author><name>Chris Duck</name><uri>https://plus.google.com/111921112014612222144</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-hxGXvYzzwjM/AAAAAAAAAAI/AAAAAAAABZ4/NJmNBRF_ALc/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DkIEQXkycCp7ImA9WhBREEw.&quot;"><id>tag:blogger.com,1999:blog-7728225756528319729.post-3543832759434963257</id><published>2012-03-23T00:03:00.001-05:00</published><updated>2013-02-27T19:21:40.798-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-27T19:21:40.798-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="sdelete" /><category scheme="http://www.blogger.com/atom/ns#" term="powershell" /><category scheme="http://www.blogger.com/atom/ns#" term="sysinternals" /><title>A PowerShell Alternative to SDelete</title><content type="html">&lt;h3&gt;Problem Background&lt;/h3&gt;
&lt;p&gt;Many storage appliances support thin provisioning by not storing large blocks of zeros on disk, thus saving expensive physical disks for actual data.  One of the challenges of this feature is that Windows (or most file systems really) does not zero out space that was used by files that have been deleted.  This means that over time as files are written an deleted, the amount of physical disk that is saved by thin provisioning grows smaller.&lt;/p&gt;
&lt;p&gt;One popular solution (really the only one we've been able to find) is to use the SysInternals utility &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb897443"&gt;SDelete&lt;/a&gt;'s &lt;span class="code"&gt;-z&lt;/span&gt; switch to write zeros to all the free space, thus allowing the storage appliance to use all that empty space for something else.  The challenge with sdelete is that it only supports volumes mounted as drive letters, not volumes that are mounted to folders.  Another concern with SDelete is that it appears to fill up the entire disk, if only for that brief second between finishing writing the file out and deleting the file.  We were concerned with using this tool at work on a workload like SQL that might not take kindly to a disk filling up.&lt;/p&gt;
&lt;p&gt;Our storage administrator tried to solve this problem using the standard PowerShell techniques of redirecting null strings to files and found the performance to be somewhat lacking.  I don't want to get into a detailed analysis of PowerShell IO characteristics (mostly because I haven't spent much time researching how PowerShell does IO), but instead just post that the solution is to turn to the System.IO .Net namespace and perform the IO operations the "hard way".&lt;/p&gt;
&lt;h3&gt;The Script&lt;/h3&gt;
&lt;p&gt;Here is the script I came up with using a FileStream to write out the zero file.  We informally compared a couple of runs between this script and sdelete and saw roughly the same performance.&lt;/p&gt;
&lt;h2&gt;Write-ZeroesToFreeSpace.ps1&lt;/h2&gt;
&lt;!--Start Script--&gt;
&lt;div class='embedded-code-wrapper'&gt;
&lt;TABLE BORDER='0' cellpadding='5' cellspacing='0'&gt; 
&lt;TR&gt; 
    &lt;TD VALIGN='Top'&gt;&lt;div class='line-no-column'&gt;001&lt;BR /&gt;002&lt;BR /&gt;003&lt;BR /&gt;004&lt;BR /&gt;005&lt;BR /&gt;006&lt;BR /&gt;007&lt;BR /&gt;008&lt;BR /&gt;009&lt;BR /&gt;010&lt;BR /&gt;011&lt;BR /&gt;012&lt;BR /&gt;013&lt;BR /&gt;014&lt;BR /&gt;015&lt;BR /&gt;016&lt;BR /&gt;017&lt;BR /&gt;018&lt;BR /&gt;019&lt;BR /&gt;020&lt;BR /&gt;021&lt;BR /&gt;022&lt;BR /&gt;023&lt;BR /&gt;024&lt;BR /&gt;025&lt;BR /&gt;026&lt;BR /&gt;027&lt;BR /&gt;028&lt;BR /&gt;029&lt;BR /&gt;030&lt;BR /&gt;031&lt;BR /&gt;032&lt;BR /&gt;033&lt;BR /&gt;034&lt;BR /&gt;035&lt;BR /&gt;036&lt;BR /&gt;037&lt;BR /&gt;038&lt;BR /&gt;039&lt;BR /&gt;040&lt;BR /&gt;041&lt;BR /&gt;042&lt;BR /&gt;043&lt;BR /&gt;044&lt;BR /&gt;045&lt;BR /&gt;046&lt;BR /&gt;047&lt;BR /&gt;048&lt;BR /&gt;049&lt;BR /&gt;050&lt;BR /&gt;051&lt;BR /&gt;052&lt;BR /&gt;053&lt;BR /&gt;054&lt;BR /&gt;055&lt;BR /&gt;056&lt;BR /&gt;057&lt;BR /&gt;058&lt;BR /&gt;059&lt;BR /&gt;060&lt;BR /&gt;061&lt;BR /&gt;062&lt;BR /&gt;063&lt;BR /&gt;064&lt;BR /&gt;065&lt;BR /&gt;066&lt;BR /&gt;067&lt;BR /&gt;068&lt;BR /&gt;069&lt;BR /&gt;070&lt;BR /&gt;071&lt;BR /&gt;072&lt;BR /&gt;073&lt;BR /&gt;074&lt;BR /&gt;075&lt;BR /&gt;076&lt;BR /&gt;077&lt;BR /&gt;078&lt;BR /&gt;079&lt;BR /&gt;080&lt;BR /&gt;081&lt;BR /&gt;082&lt;BR /&gt;083&lt;BR /&gt;084&lt;BR /&gt;085&lt;BR /&gt;086&lt;BR /&gt;087&lt;BR /&gt;088&lt;BR /&gt;089&lt;BR /&gt;090&lt;BR /&gt;091&lt;BR /&gt;092&lt;BR /&gt;093&lt;BR /&gt;094&lt;BR /&gt;095&lt;BR /&gt;096&lt;BR /&gt;097&lt;BR /&gt;098&lt;BR /&gt;099&lt;BR /&gt;100&lt;BR /&gt;101&lt;BR /&gt;102&lt;BR /&gt;
&lt;/DIV&gt; 
    &lt;/TD&gt; 
    &lt;TD VALIGN='Top' NOWRAP='NOWRAP'&gt;&lt;div class='embedded-code-body'&gt;&lt;span class='psComment'&gt;&amp;lt;#
.SYNOPSIS
&amp;nbsp;Writes a large file full of zeroes to a volume in order to allow a storage
&amp;nbsp;appliance to reclaim unused space.

.DESCRIPTION
&amp;nbsp;Creates a file called ThinSAN.tmp on the specified volume that fills the
&amp;nbsp;volume up to leave only the percent free value (default is 5%) with zeroes.
&amp;nbsp;This allows a storage appliance that is thin provisioned to mark that drive
&amp;nbsp;space as unused and reclaim the space on the physical disks.
&amp;nbsp;
.PARAMETER Root
&amp;nbsp;The folder to create the zeroed out file in.  This can be a drive root (c:\)
&amp;nbsp;or a mounted folder (m:\mounteddisk).  This must be the root of the mounted
&amp;nbsp;volume, it cannot be an arbitrary folder within a volume.
&amp;nbsp;
.PARAMETER PercentFree
&amp;nbsp;A float representing the percentage of total volume space to leave free.  The
&amp;nbsp;default is .05 (5%)

.EXAMPLE
&amp;nbsp;PS&amp;gt; Write-ZeroesToFreeSpace -Root &amp;quot;c:\&amp;quot;
&amp;nbsp;
&amp;nbsp;This will create a file of all zeroes called c:\ThinSAN.tmp that will fill the
&amp;nbsp;c drive up to 95% of its capacity.
&amp;nbsp;
.EXAMPLE
&amp;nbsp;PS&amp;gt; Write-ZeroesToFreeSpace -Root &amp;quot;c:\MountPoints\Volume1&amp;quot; -PercentFree .1
&amp;nbsp;
&amp;nbsp;This will create a file of all zeroes called
&amp;nbsp;c:\MountPoints\Volume1\ThinSAN.tmp that will fill up the volume that is
&amp;nbsp;mounted to c:\MountPoints\Volume1 to 90% of its capacity.

.EXAMPLE
&amp;nbsp;PS&amp;gt; Get-WmiObject Win32_Volume -filter &amp;quot;drivetype=3&amp;quot; | Write-ZeroesToFreeSpace
&amp;nbsp;
&amp;nbsp;This will get a list of all local disks (type=3) and fill each one up to 95%
&amp;nbsp;of their capacity with zeroes.
&amp;nbsp;
.NOTES
&amp;nbsp;You must be running as a user that has permissions to write to the root of the
&amp;nbsp;volume you are running this script against. This requires elevated privileges
&amp;nbsp;using the default Windows permissions on the C drive.
#&amp;gt;&lt;/span&gt;
&lt;span class='psKeyword'&gt;param&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;[&lt;/span&gt;&lt;span class='psAttribute'&gt;Parameter&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psMember'&gt;Mandatory&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psVariable'&gt;$true&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;&lt;span class='psMember'&gt;ValueFromPipelineByPropertyName&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psVariable'&gt;$true&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psOperator'&gt;]&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;[&lt;/span&gt;&lt;span class='psAttribute'&gt;ValidateNotNullOrEmpty&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psOperator'&gt;]&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;[&lt;/span&gt;&lt;span class='psAttribute'&gt;Alias&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psOperator'&gt;]&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$Root&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;[&lt;/span&gt;&lt;span class='psAttribute'&gt;Parameter&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psMember'&gt;Mandatory&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psVariable'&gt;$false&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psOperator'&gt;]&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;[&lt;/span&gt;&lt;span class='psAttribute'&gt;ValidateRange&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psNumber'&gt;0&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;&lt;span class='psNumber'&gt;1&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psOperator'&gt;]&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$PercentFree&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psNumber'&gt;.05&lt;/span&gt;
&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psKeyword'&gt;process&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psComment'&gt;#Convert the $Root value to a valid WMI filter string&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$FixedRoot&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;$Root&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Trim&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;\&amp;quot;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;-replace&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;\\&amp;quot;&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;\\&amp;quot;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;+&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;\\&amp;quot;&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$FileName&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;ThinSAN.tmp&amp;quot;&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$FilePath&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;Join-Path&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$Root&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$FileName&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psComment'&gt;#Check and make sure the file doesn&amp;#39;t already exist so we don&amp;#39;t clobber someone&amp;#39;s data&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;if&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psCommand'&gt;Test-Path&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$FilePath&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;Write-Error&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandParameter'&gt;-Message&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;The file $FilePath already exists, please delete the file and try again&amp;quot;&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;else&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psComment'&gt;#Get a reference to the volume so we can calculate the desired file size later&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$Volume&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;gwmi&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandArgument'&gt;win32_volume&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandParameter'&gt;-filter&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;name=&amp;#39;$FixedRoot&amp;#39;&amp;quot;&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;if&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;$Volume&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psComment'&gt;#I have not tested for the optimum IO size ($ArraySize), 64kb is what sdelete.exe uses&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$ArraySize&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psNumber'&gt;64kb&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psComment'&gt;#Calculate the amount of space to leave on the disk&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$SpaceToLeave&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$Volume&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Capacity&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;*&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$PercentFree&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psComment'&gt;#Calculate the file size needed to leave the desired amount of space&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$FileSize&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$Volume&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;FreeSpace&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;-&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$SpacetoLeave&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psComment'&gt;#Create an array of zeroes to write to disk&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$ZeroArray&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;new-object&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandArgument'&gt;byte[]&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;$ArraySize&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psComment'&gt;#Open a file stream to our file &lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$Stream&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psType'&gt;[io.File]&lt;/span&gt;&lt;span class='psOperator'&gt;::&lt;/span&gt;&lt;span class='psMember'&gt;OpenWrite&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;$FilePath&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psComment'&gt;#Start a try/finally block so we don&amp;#39;t leak file handles if any exceptions occur&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;try&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psComment'&gt;#Keep track of how much data we&amp;#39;ve written to the file&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$CurFileSize&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psNumber'&gt;0&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;while&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;$CurFileSize&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;-lt&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$FileSize&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psComment'&gt;#Write the entire zero array buffer out to the file stream&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$Stream&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Write&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;$ZeroArray&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;&lt;span class='psNumber'&gt;0&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$ZeroArray&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Length&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psComment'&gt;#Increment our file size by the amount of data written to disk&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$CurFileSize&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;+=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$ZeroArray&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Length&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;finally&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psComment'&gt;#always close our file stream, even if an exception occurred&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;if&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;$Stream&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$Stream&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Close&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psComment'&gt;#always delete the file if we created it, even if an exception occurred&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;if&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psCommand'&gt;Test-Path&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$FilePath&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;del&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$FilePath&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;else&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;Write-Error&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;Unable to locate a volume mounted at $Root&amp;quot;&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;
&lt;span class='psGroupEnd'&gt;}&lt;/span&gt; 
&lt;/DIV&gt; 
    &lt;/TD&gt; 
&lt;/TR&gt; 
&lt;/TBODY&gt; 
&lt;/TABLE&gt; 
&lt;/DIV&gt;
&lt;!--End Script--&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=jBTcnCWXn9k:LLjpWqzztIc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=jBTcnCWXn9k:LLjpWqzztIc:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=jBTcnCWXn9k:LLjpWqzztIc:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=jBTcnCWXn9k:LLjpWqzztIc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=jBTcnCWXn9k:LLjpWqzztIc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=jBTcnCWXn9k:LLjpWqzztIc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=jBTcnCWXn9k:LLjpWqzztIc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=jBTcnCWXn9k:LLjpWqzztIc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatsUpDuckBlog/~4/jBTcnCWXn9k" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.whatsupduck.net/feeds/3543832759434963257/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.whatsupduck.net/2012/03/powershell-alternative-to-sdelete.html#comment-form" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/3543832759434963257?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/3543832759434963257?v=2" /><link rel="alternate" type="text/html" href="http://blog.whatsupduck.net/2012/03/powershell-alternative-to-sdelete.html" title="A PowerShell Alternative to SDelete" /><author><name>Chris Duck</name><uri>https://plus.google.com/111921112014612222144</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-hxGXvYzzwjM/AAAAAAAAAAI/AAAAAAAABZ4/NJmNBRF_ALc/s512-c/photo.jpg" /></author><thr:total>8</thr:total></entry><entry gd:etag="W/&quot;DkEHRHo6eCp7ImA9WhBREEw.&quot;"><id>tag:blogger.com,1999:blog-7728225756528319729.post-8496473396608944593</id><published>2012-02-08T17:27:00.000-06:00</published><updated>2013-02-27T19:23:55.410-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-27T19:23:55.410-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="powershell" /><title>Powershell ValidateNotNullOrEmpty Bug</title><content type="html">&lt;p&gt;
I was showing a co-worker how easy it is to ensure that the parameters to his script were actually being set using the &lt;span class="code"&gt;[Parameter(Mandatory=$true)]&lt;/span&gt; and &lt;span class="code"&gt;[ValidateNotNullOrEmpty()]&lt;/span&gt; decorators on his parameter declaration block, and we encountered a bug where he was able to pass an empty string as a parameter to his function and the validation did not catch it.
&lt;/p&gt;

&lt;h3&gt;Reproduction Steps&lt;/h3&gt;
&lt;p&gt;
In our search to explain what was going on, we located a couple of forum posts which led us to 2 bugs filed on connect that I believe are related to the same problem: &lt;a href="http://connect.microsoft.com/PowerShell/feedback/details/610176/validatenotnullorempty-and-read-host-something-wierd"&gt;610176&lt;/a&gt; and &lt;a href="http://connect.microsoft.com/PowerShell/feedback/details/677559/-validatenotnullorempty-behavior-not-as-expected#details"&gt;677559&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Our steps mirrored &lt;a href="http://connect.microsoft.com/PowerShell/feedback/details/610176/validatenotnullorempty-and-read-host-something-wierd"&gt;610176&lt;/a&gt; almost exactly, so I'm going to copy the reproduction steps from that bug here, with a few changes.
&lt;/p&gt;
&lt;!--Start Script--&gt;
&lt;div class='embedded-code-wrapper'&gt;
&lt;TABLE BORDER='0' cellpadding='5' cellspacing='0'&gt; 
&lt;TR&gt; 
    &lt;TD VALIGN='Top'&gt;&lt;div class='line-no-column'&gt;001&lt;BR /&gt;002&lt;BR /&gt;003&lt;BR /&gt;004&lt;BR /&gt;005&lt;BR /&gt;006&lt;BR /&gt;007&lt;BR /&gt;008&lt;BR /&gt;009&lt;BR /&gt;010&lt;BR /&gt;
&lt;/DIV&gt; 
    &lt;/TD&gt; 
    &lt;TD VALIGN='Top' NOWRAP='NOWRAP'&gt;&lt;div class='embedded-code-body'&gt;&lt;span class='psKeyword'&gt;Function&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandArgument'&gt;test&lt;/span&gt;
&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;param&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psOperator'&gt;[&lt;/span&gt;&lt;span class='psAttribute'&gt;Parameter&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psMember'&gt;Mandatory&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psVariable'&gt;$true&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psOperator'&gt;]&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;[&lt;/span&gt;&lt;span class='psAttribute'&gt;ValidateNotNullOrEmpty&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psOperator'&gt;]&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$param&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$param&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;GetType&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;FullName&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;Entered: &amp;#39;$param&amp;#39;&amp;quot;&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psType'&gt;[string]&lt;/span&gt;&lt;span class='psOperator'&gt;::&lt;/span&gt;&lt;span class='psMember'&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;$param&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psGroupEnd'&gt;}&lt;/span&gt; 
&lt;/DIV&gt; 
    &lt;/TD&gt; 
&lt;/TR&gt; 
&lt;/TBODY&gt; 
&lt;/TABLE&gt; 
&lt;/DIV&gt;
&lt;!--End Script--&gt;&lt;p&gt;
The expected result when you pass an empty string would be an error stating that the parameter failed vaildation, no matter how you generated that string:
&lt;/p&gt;
&lt;pre&gt;
&lt;span class="code"&gt;PS&gt; test ""&lt;/span&gt;
&lt;span class="code" style="color: red; background: black;"&gt;test : Cannot validate argument on parameter 'param'. The argument is null or empty. Supply an argument that is not null or empty and then try the command again.&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;
However, when you call the function without any parameters, Powershell sees that you forgot a mandatory parameter and prompts you for a value.  If you just press &lt;enter&gt;, the empty string incorrectly passes validation and your function is executed:
&lt;/p&gt;
&lt;pre&gt;&lt;span class="code"&gt;PS&gt; test

cmdlet test at command pipeline position 1
Supply values for the following parameters:
param:&amp;lt;just press enter here&amp;gt;

System.String
Entered: ''
True&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, the parameter is a string and it is an empty string, which should never have passed validation.&lt;/p&gt;
&lt;h3&gt;Explanation&lt;/h3&gt;
&lt;p&gt;Using &lt;a href="http://www.reflector.net/"&gt;Reflector&lt;/a&gt;, I tracked down the ValidateNotNullOrEmptyAttribute class (load System.Management.Automation from the GAC and then drill down to the System.Management.Automation namespace and then the Validate method on the ValidateNotNullOrEmptyAttribute class) and discovered the following code:&lt;/p&gt;
&lt;pre&gt;&lt;span class="code"&gt;
    ... (tests the arguments variable for null)

    str = arguments as string;
    if (str != null)
    {
        if (string.IsNullOrEmpty(str))
        {
            throw new ValidationMetadataException("ArgumentIsEmpty", null, "Metadata", ValidateNotNullOrEmptyFailure", new object[0]);
        }
    }
    else
    {

    ... (continues on to handle special cases for enumerable objects)
&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;You can see they are using the &lt;a href="http://msdn.microsoft.com/en-us/library/cscsdfbt(VS.71).aspx"&gt;C# &lt;span class="code"&gt;as&lt;/span&gt; operator&lt;/a&gt; to attempt to convert the parameter into a &lt;span class="code"&gt;string&lt;/span&gt; object.  The problem is that Powershell uses an &lt;a href="http://blogs.msdn.com/b/powershell/archive/2006/11/24/what-s-up-with-psbase-psextended-psadapted-and-psobject.aspx"&gt;adaptive type system&lt;/a&gt; to work magic on some particularly annoying types (XML and WMI come to mind), and apparently the method that is reading the input when you forget to specify a mandatory parameter (and also the Read-Host cmdlet as demonstrated in &lt;a href="http://connect.microsoft.com/PowerShell/feedback/details/677559/-validatenotnullorempty-behavior-not-as-expected#details"&gt;677559&lt;/a&gt;) are returning Powershell objects that &lt;b&gt;&lt;i&gt;look&lt;/i&gt;&lt;/b&gt; like strings, but aren't actual .Net strings.&lt;/p&gt;
&lt;h3&gt;Go Vote&lt;/h3&gt;

&lt;p&gt;If you're not a fan of this behavior, go &lt;a href="http://connect.microsoft.com/PowerShell/feedback/details/610176/validatenotnullorempty-and-read-host-something-wierd"&gt;vote for the bug on Connect&lt;/a&gt;.  I've posted a comment with a link back to this post, so hopefully there is enough detail here to get the problem fixed in V3 :)
&lt;/p&gt;

&lt;h3&gt;Digging Deeper&lt;/h3&gt;
&lt;p&gt;
So I fired up Visual C# Express and wrote a little C# program that embeds a Powershell runspace and reproduces the problem, then extracts the variables and tests them in C# to see what types the objects really are.  While I was testing different scenarios with my co-worker, I discovered you can also convert a string object to a Powershell adapted object by just referencing &lt;span class="code"&gt;$MyString.PSBase&lt;/span&gt;, and this breaks ValidateNotNullOrEmpty just as badly as Read-Host, so I used this method in my C# application as it was easier to code than trying to work out how to get input from the C# console to the Powershell runtime properly.
&lt;/p&gt;
&lt;pre&gt;&lt;span class="code"&gt;
using System;
using System.Collections.Generic;
using System.Text;
using System.Management.Automation;
using System.Management.Automation.Runspaces;

namespace ConsoleApplication1
{
  public class Program
  {
    public static void Main(string[] args)
    {
      using (Runspace rs = RunspaceFactory.CreateRunspace())
      {
        rs.Open();
        using (Pipeline pl = rs.CreatePipeline())
        {
          pl.Commands.AddScript("$str = \"\"");
          pl.Commands.AddScript("$pso = \"\"");
          pl.Commands.AddScript("$pso.psbase");
          pl.Invoke();
          Object oStr = rs.SessionStateProxy.GetVariable("str");
          Object oPso = rs.SessionStateProxy.GetVariable("pso");
          Console.WriteLine(string.Format("oStr type = {0}", oStr.GetType().FullName));
          Console.WriteLine(string.Format("oPso type = {0}", oPso.GetType().FullName));
          string sStr = oStr as string;
          if (sStr != null)
          {
            Console.WriteLine(string.Format("sStr.IsNullOrEmpty = {0}", string.IsNullOrEmpty(sStr)));
          }
          else
          {
            Console.WriteLine("oStr is not a string");
          }
          string sPso = oPso as string;
          if (sPso != null)
          {
            Console.WriteLine(string.Format("sPso.IsNullOrEmpty = {0}", string.IsNullOrEmpty(sPso)));
          }
          else
          {
            Console.WriteLine("oPso is not a string");
          }
        }
      }
    }
  }
}
&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;The output is as follows:&lt;/p&gt;
&lt;pre&gt;&lt;span class="code"&gt;oStr type = System.String
oPso type = System.Management.Automation.PSObject
sStr.IsNullOrEmpty = True
oPso is not a string&lt;/pre&gt;&lt;/span&gt;
&lt;p&gt;As you can see, the string-&gt;string conversion was successful (oStr-&gt;sStr variables), while the PSObject-&gt;string conversion was not (oPso-&gt;sPso).  This results in the PSObject argument being treated as a regular object (which is not null) instead of a string, even though it is type-adapting a string object.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=uIm5n_lgSBc:Ov5ijghZ03c:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=uIm5n_lgSBc:Ov5ijghZ03c:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=uIm5n_lgSBc:Ov5ijghZ03c:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=uIm5n_lgSBc:Ov5ijghZ03c:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=uIm5n_lgSBc:Ov5ijghZ03c:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=uIm5n_lgSBc:Ov5ijghZ03c:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=uIm5n_lgSBc:Ov5ijghZ03c:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=uIm5n_lgSBc:Ov5ijghZ03c:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatsUpDuckBlog/~4/uIm5n_lgSBc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.whatsupduck.net/feeds/8496473396608944593/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.whatsupduck.net/2012/02/powershell-validatenotnullorempty-bug.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/8496473396608944593?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/8496473396608944593?v=2" /><link rel="alternate" type="text/html" href="http://blog.whatsupduck.net/2012/02/powershell-validatenotnullorempty-bug.html" title="Powershell ValidateNotNullOrEmpty Bug" /><author><name>Chris Duck</name><uri>https://plus.google.com/111921112014612222144</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-hxGXvYzzwjM/AAAAAAAAAAI/AAAAAAAABZ4/NJmNBRF_ALc/s512-c/photo.jpg" /></author><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;CEIMQHk5eCp7ImA9WhVRFEU.&quot;"><id>tag:blogger.com,1999:blog-7728225756528319729.post-6104716139670446225</id><published>2012-01-28T14:57:00.000-06:00</published><updated>2012-03-23T01:03:01.720-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-23T01:03:01.720-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="powershell" /><title>Casting Objects to Boolean in Powershell</title><content type="html">&lt;p&gt;
A question came up on the Powershell technet forum asking why an empty &lt;a href="http://msdn.microsoft.com/en-us/library/system.directoryservices.searchresultcollection.aspx"&gt;System.DirectoryServices.SearchResultCollection&lt;/a&gt; was evaluating to &lt;span class="code"&gt;$true&lt;/span&gt;.  The original post is &lt;a href="http://social.technet.microsoft.com/Forums/en-US/winserverpowershell/thread/44128f6f-3263-4263-a9cb-f855d84ee5b7#4bed26db-b865-45ec-afce-2c0c40c661b4"&gt;HERE&lt;/a&gt;, but the gist of the question is this:
&lt;/p&gt;

&lt;p&gt;&lt;blockquote&gt;Why does an empty &lt;a href="http://msdn.microsoft.com/en-us/library/system.directoryservices.searchresultcollection.aspx"&gt;System.DirectoryServices.SearchResultCollection&lt;/a&gt; object evaluate to &lt;span class="code"&gt;$true&lt;/span&gt; when used in an if statement (ie if($SearchResult)), but an empty &lt;a href="http://msdn.microsoft.com/en-us/library/system.array.aspx"&gt;System.Array&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/system.collections.arraylist.aspx"&gt;System.Collections.ArrayList&lt;/a&gt; both evaulate to &lt;span class="code"&gt;$false&lt;/span&gt;?&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;
I was aware that Powershell has some special rules for casting objects, but a search for exactly what those rule are only returned very generic terms for how collections were handled (ie &lt;a href="http://www.pavleck.net/powershell-cookbook/apa.html#booleans"&gt;this blog post&lt;/a&gt; and &lt;a href="http://books.google.com/books?id=wVYl6UKeb4wC&amp;pg=PA41&amp;lpg=PA41&amp;dq=powershell+rules+for+cast+to+bool&amp;source=bl&amp;ots=lOt-HD8Adv&amp;sig=WO-GvpUuRdGXFkg8RO52pIvZYxc&amp;hl=en&amp;sa=X&amp;ei=MjckT6rOHabMsQLU5vGMAg&amp;ved=0CGoQ6AEwCQ#v=onepage&amp;q=powershell%20rules%20for%20cast%20to%20bool&amp;f=false"&gt;this book&lt;/a&gt;).  Nothing specified exactly which types/interfaces were expanded as collections and which were not.
&lt;/p&gt;

&lt;p&gt;So I did a little digging and came up with the following...&lt;/p&gt;

&lt;p&gt;The reason a &lt;a href="http://msdn.microsoft.com/en-us/library/system.directoryservices.searchresultcollection.aspx"&gt;SearchResultCollection&lt;/a&gt; evaluates to true even when it is empty is because it does not implement the &lt;a href="http://msdn.microsoft.com/en-us/library/system.collections.ilist.aspx"&gt;IList&lt;/a&gt; interface:&lt;/p&gt;

&lt;p&gt;&lt;div class="code"&gt;&lt;pre&gt;
PS&amp;gt; [System.DirectoryServices.SearchResultCollection].GetInterfaces()

IsPublic IsSerial Name
-------- -------- ----
True     False    ICollection
True     False    IEnumerable
True     False    IDisposable


PS&amp;gt; [System.Array].GetInterfaces()

IsPublic IsSerial Name
-------- -------- ----
True     False    ICloneable
True     False    IList
True     False    ICollection
True     False    IEnumerable


PS&amp;gt; [System.Collections.ArrayList].GetInterfaces()

IsPublic IsSerial Name
-------- -------- ----
True     False    IList
True     False    ICollection
True     False    IEnumerable
True     False    ICloneable
&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;As you can see, both &lt;a href="http://msdn.microsoft.com/en-us/library/system.array.aspx"&gt;System.Array&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/system.collections.arraylist.aspx"&gt;System.Collections.ArrayList&lt;/a&gt; implement &lt;a href="http://msdn.microsoft.com/en-us/library/system.collections.ilist.aspx"&gt;IList&lt;/a&gt;. &amp;nbsp;This is apparently what Powershell uses to determine if it should "look inside" when it converts the object to a boolean.&lt;/p&gt;

&lt;p&gt;You can see (what I think is) the proof of this if you load up &lt;a href="http://www.reflector.net/"&gt;Reflector&lt;/a&gt; (&lt;a href="http://www.jetbrains.com/decompiler/"&gt;dotPeek&lt;/a&gt;, &lt;a href="http://wiki.sharpdevelop.net/ilspy.ashx"&gt;ILSpy&lt;/a&gt;, and &lt;a href="http://www.telerik.com/products/decompiler.aspx"&gt;JustDecompile&lt;/a&gt; are free alternatives)&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open System.Management.Automation from the GAC&lt;/li&gt;
&lt;li&gt;Expand the System.Management.Automation namespace&lt;/li&gt;
&lt;li&gt;Browse down to LanguagePrimitives&lt;/li&gt;
&lt;li&gt;Browse down to the IsTrue(object obj) method and decompile it&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In there you can see the algorithm (which I am assuming is being used in this case) that converts objects to boolean. &amp;nbsp;The basic logic is:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;If it is null, return &lt;span class="code"&gt;$false&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;If it is a boolean, return the boolean&lt;/li&gt;
  &lt;li&gt;If it is a string, return &lt;span class="code"&gt;$false&lt;/span&gt; if it is empty, else return &lt;span class="code"&gt;$true&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;If it is a number, return &lt;span class="code"&gt;$false&lt;/span&gt; if it is 0, else return &lt;span class="code"&gt;$true&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;If it is a SwitchParameter, call its own &lt;span class="code"&gt;ToBool()&lt;/span&gt; method&lt;/li&gt;
  &lt;li&gt;Convert it to an IList
    &lt;ol type="i"&gt;
      &lt;li&gt;If this conversion fails, return true (meaning it was an object that was not null, not any of the "special" things above, and not a list for PS to count)&lt;/li&gt;
      &lt;li&gt;If it is a list and has 0 elements, return &lt;span class="code"&gt;$false&lt;/span&gt;&lt;/li&gt;
      &lt;li&gt;If it is a list and has 1 element, return the &lt;span class="code"&gt;IsTrue(list[0])&lt;/span&gt; value (ie recurse on the one element and return its value&lt;/li&gt;
      &lt;li&gt;If it is a list with more than 1 thing in it, return &lt;span class="code"&gt;$true&lt;/span&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As you can see, the &lt;a href="http://msdn.microsoft.com/en-us/library/system.array.aspx"&gt;Array&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/system.collections.arraylist.aspx"&gt;ArrayList&lt;/a&gt; fall into rules 6.ii-6.iv because they implement &lt;a href="http://msdn.microsoft.com/en-us/library/system.collections.ilist.aspx"&gt;IList&lt;/a&gt;, whereas the &lt;a href="http://msdn.microsoft.com/en-us/library/system.directoryservices.searchresultcollection.aspx"&gt;SearchResultCollection&lt;/a&gt; falls into rule 6.i because it does not implement &lt;a href="http://msdn.microsoft.com/en-us/library/system.collections.ilist.aspx"&gt;IList&lt;/a&gt; so the conversion to a list fails, which means it was a plain old non-null object which evaluates to &lt;span class="code"&gt;$true&lt;/span&gt; in Powershell.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=AyKH2yTZ-jc:-j8y9ntFCWA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=AyKH2yTZ-jc:-j8y9ntFCWA:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=AyKH2yTZ-jc:-j8y9ntFCWA:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=AyKH2yTZ-jc:-j8y9ntFCWA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=AyKH2yTZ-jc:-j8y9ntFCWA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=AyKH2yTZ-jc:-j8y9ntFCWA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=AyKH2yTZ-jc:-j8y9ntFCWA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=AyKH2yTZ-jc:-j8y9ntFCWA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatsUpDuckBlog/~4/AyKH2yTZ-jc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.whatsupduck.net/feeds/6104716139670446225/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.whatsupduck.net/2012/01/casting-objects-to-boolean-in.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/6104716139670446225?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/6104716139670446225?v=2" /><link rel="alternate" type="text/html" href="http://blog.whatsupduck.net/2012/01/casting-objects-to-boolean-in.html" title="Casting Objects to Boolean in Powershell" /><author><name>Chris Duck</name><uri>https://plus.google.com/111921112014612222144</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-hxGXvYzzwjM/AAAAAAAAAAI/AAAAAAAABZ4/NJmNBRF_ALc/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CUMFR347eCp7ImA9WhdaEU8.&quot;"><id>tag:blogger.com,1999:blog-7728225756528319729.post-6839048431774008217</id><published>2011-10-17T13:00:00.001-05:00</published><updated>2011-10-20T10:10:16.000-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-20T10:10:16.000-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="icinga-web" /><category scheme="http://www.blogger.com/atom/ns#" term="timeout" /><category scheme="http://www.blogger.com/atom/ns#" term="icinga" /><title>Adjusting Icinga-Web Session Timeout Values</title><content type="html">Icinga-Web is a more modern interface to Icinga (as opposed to the Icinga Classic interface that seeks to mimic the traditional Nagios web interface).  A comparison of all three interfaces is provided at the Icinga site (https://www.icinga.org/nagios/webinterface/).&lt;br /&gt;
One thing you will quickly notice is that after 24 minutes, your session disappears and you are prompted to log in again.  From a quick glance through the code it appears they are using a very heavy handed garbage collection where they delete any sessions that are older than the php configuration variable session.gc_maxlifetime.  Out of the box (on our RedHat 5.7 distro) this is configured as 1440 (1440 seconds = 24 minutes).  This means that NO session can live past 24 minutes, no matter how frequently you are using it.&lt;br /&gt;
&lt;h3&gt;
How to Extend the Icinga-Web Session Timeout&lt;/h3&gt;
There are two pieces to the Icinga-Web session: PHP max session lifetime variable and the Icinga-Web session cookie lifetime variable.&lt;br /&gt;
&lt;h4&gt;
To adjust the PHP max session lifetime variable:&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Open &lt;span class="code"&gt;/etc/php.ini&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Change the &lt;span class="code"&gt;session.gc_maxlifetime&lt;/span&gt; value to something more appropriate&lt;/li&gt;
&lt;/ol&gt;
Setting the PHP max session lifetime to 0 will cause no sessions to be cleaned out of your database, which will eventually cause problems.  Icinga really needs to patch this so that accessing the Icinga-Web site updates the &lt;span class="code"&gt;session_modified&lt;/span&gt; value and then only do GC on stale sessions.&lt;br /&gt;
&lt;h4&gt;
To adjust the Icinga-Web session cookie lifetime variable:&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Open &lt;span class="code"&gt;/usr/local/icinga-web/app/config/factories.site.xml&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Adjust the &lt;span class="code"&gt;&amp;lt;ae:parameter name="session_cookie_lifetime"&amp;gt;&lt;/span&gt; parameter to a more appropriate value&lt;/li&gt;
&lt;/ol&gt;
This value sets the lifetime of the cookie in your browser.  Setting it to 0 will cause Icinga-Web to create a session cookie that will be valid for as long as your browser is open.  This is a reasonable setting for your browser, but you will still be subjected to the PHP max lifetime value, so you will still experience timeouts.&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=PGRFmnZr71g:_mooIgMGnWI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=PGRFmnZr71g:_mooIgMGnWI:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=PGRFmnZr71g:_mooIgMGnWI:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=PGRFmnZr71g:_mooIgMGnWI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=PGRFmnZr71g:_mooIgMGnWI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=PGRFmnZr71g:_mooIgMGnWI:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=PGRFmnZr71g:_mooIgMGnWI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=PGRFmnZr71g:_mooIgMGnWI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatsUpDuckBlog/~4/PGRFmnZr71g" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.whatsupduck.net/feeds/6839048431774008217/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.whatsupduck.net/2011/10/adjusting-icinga-web-session-timeout.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/6839048431774008217?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/6839048431774008217?v=2" /><link rel="alternate" type="text/html" href="http://blog.whatsupduck.net/2011/10/adjusting-icinga-web-session-timeout.html" title="Adjusting Icinga-Web Session Timeout Values" /><author><name>Chris Duck</name><uri>https://plus.google.com/111921112014612222144</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-hxGXvYzzwjM/AAAAAAAAAAI/AAAAAAAABZ4/NJmNBRF_ALc/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0ICRn08fSp7ImA9WhVRFUs.&quot;"><id>tag:blogger.com,1999:blog-7728225756528319729.post-6113087145179722029</id><published>2011-10-12T15:06:00.009-05:00</published><updated>2012-03-24T00:06:07.375-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-24T00:06:07.375-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="icinga" /><category scheme="http://www.blogger.com/atom/ns#" term="kerberos" /><category scheme="http://www.blogger.com/atom/ns#" term="authentication" /><category scheme="http://www.blogger.com/atom/ns#" term="apache" /><title>Configuring Icinga Classic for Active Directory Authentication via IWA</title><content type="html">&lt;p&gt;Out of the box, the Icinga Classic interface uses standard Apache .htaccess
files (&lt;a href="http://docs.icinga.org/1.5.0/en/cgiauth.html"&gt;http://docs.icinga.org/1.5.0/en/cgiauth.html&lt;/a&gt;)
to secure both the CGIs and the classic web interface.  Living in an Active
Directory world, I'm always looking for ways to integrate products with my
existing AD credentials so I don't have to log in again.  I decided our move
from Nagios to Icinga was a good opportunity to figure out how achieve
integrated Windows authentication (IWA) in Apache since we were having to
figure out how to configure everything anyway.&lt;/p&gt;
&lt;p&gt;To maintain my focus on this post, I'm not going to cover installing Icinga
or configuring Kerberos on your Linux box.  I'm also only covering instructions
for RedHat 5.7.  Most of my information was pulled from the Apache + Windows
Kerberos tutorial found here: &lt;a href="http://grolmsnet.de/kerbtut/"&gt;http://grolmsnet.de/kerbtut/&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Example Configuration&lt;/h3&gt;
&lt;p&gt;Throughout this example, I'm going to use the following hypothetical configuration:&lt;/p&gt;
&lt;p&gt;Icinga site = icinga.example.com&lt;br /&gt;
AD Domain FQDN = corp.example.com&lt;br /&gt;
AD Domain Netbios = ExampleCorp&lt;br /&gt;
icinga.example.com is an A record in DNS (important for IE spn building)&lt;br /&gt;
Apache Configuration = /etc/httpd/conf and /etc/httpd/conf.d&lt;br /&gt;
Apache User = apache&lt;br /&gt;
Apache Group = apache&lt;br /&gt;
My AD Credentials = ExampleCorp\cduck or cduck@corp.example.com
&lt;/p&gt;
&lt;h3&gt;Create an AD Account&lt;/h3&gt;
&lt;p&gt;The first step is to create an account in AD for the site to use to validate
credentials with.  In this example, I'm going to use apache_icinga.example.com.
The account is configured as follows in AD:
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Full name:&lt;/b&gt; apache_icinga.example.com&lt;br /&gt;
&lt;b&gt;User UPN logon:&lt;/b&gt; apache_icinga.example.com@corp.example.com&lt;br /&gt;
&lt;b&gt;User SamAccountName:&lt;/b&gt; ExampleCorp\apache_icinga.exampl&lt;br /&gt;
&lt;b&gt;Password Never Expires&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;Password:&lt;/b&gt; Pass1234
&lt;/p&gt;
&lt;h3&gt;Generate a Keytab for the AD Account&lt;/h3&gt;
&lt;p&gt;This step will use the Windows command-line utility ktpass to generate a keytab
file for the AD account so that the Linux server will have a valid private key
for the account.  This command was run on a Windows 2008 R2 server, alternate
commands are available in the original tutorial: &lt;a href="http://grolmsnet.de/kerbtut/"&gt;http://grolmsnet.de/kerbtut/&lt;/a&gt;.
Note that this command should all be run on one line.
&lt;/p&gt;
&lt;p&gt;&lt;span class="code"&gt;c:\ktpass -princ HTTP/icinga.example.com@CORP.EXAMPLE.COM -mapuser apache_icinga.example.com@CORP.EXAMPLE.COM -crypto RC4-HMAC-NT -ptype KRB5_NT_PRINCIPAL -pass Pass1234 -out c:\icinga.example.com.keytab -setupn&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The &lt;span class="code"&gt;-setupn&lt;/span&gt; option above is important to include
(and missing from the original tutorial) as it prevents ktpass from altering
the account's userPrincipalName attribute.  The remainder of this tutorial
assume that the userPrincipalName has been preserved as above and not
altered by ktpass.&lt;/p&gt;
&lt;p&gt;You now need to copy the keytab file created above to your Icinga server.
I recommend using PSCP (&lt;a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html"&gt;http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html&lt;/a&gt;),
but you can do this however you want.  I copied my keytab to &lt;span class="code"&gt;/etc/httpd/conf&lt;/span&gt; as
it will be referenced in the Apache.conf files that are living there.&lt;/p&gt;
&lt;p&gt;Now you need to change the owner and permissions for the keytab to the
apache user and group:&lt;/p&gt;
&lt;p&gt;&lt;span class="code"&gt;chown apache:apache /etc/httpd/conf/icinga.example.com.keytab&lt;br /&gt;
chmod 400 /etc/httpd/conf/icinga.example.com.keytab&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;Configure Apache to use Kerberos&lt;/h3&gt;
&lt;p&gt;Edit your icinga.conf apache file (mine is at /etc/httpd/conf.d/icinga.conf).
You need to add the kerberos authorization module
(&lt;a href="http://modauthkerb.sourceforge.net/"&gt;http://modauthkerb.sourceforge.net/&lt;/a&gt;)
and then configure the Icinga directories to use it for authentication.
Here is my icinga.conf with the changes &lt;span class="highlight-add"&gt;highlighted&lt;/span&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;span class="code"&gt;# SAMPLE CONFIG SNIPPETS FOR APACHE WEB SERVER&lt;br /&gt;
#&lt;br /&gt;
# This file contains examples of entries that need&lt;br /&gt;
# to be incorporated into your Apache web server&lt;br /&gt;
# configuration file.  Customize the paths, etc. as&lt;br /&gt;
# needed to fit your system.&lt;br /&gt;
&lt;span class="highlight-add"&gt;LoadModule auth_kerb_module modules/mod_auth_kerb.so&lt;/span&gt;&lt;br /&gt;
ScriptAlias /icinga/cgi-bin "/usr/lib64/icinga/cgi"&lt;br /&gt;
&amp;lt;Directory "/usr/lib64/icinga/cgi"&amp;gt;&lt;br /&gt;
#  SSLRequireSSL&lt;br /&gt;
   Options ExecCGI&lt;br /&gt;
   AllowOverride None&lt;br /&gt;
   Order allow,deny&lt;br /&gt;
   Allow from all&lt;br /&gt;
#  Order deny,allow&lt;br /&gt;
#  Deny from all&lt;br /&gt;
#  Allow from 127.0.0.1&lt;br /&gt;
   AuthName "Icinga Access"&lt;br /&gt;
&lt;span class="highlight-add"&gt;# AuthType Basic&lt;/span&gt;&lt;br /&gt;
&lt;span class="highlight-add"&gt;   AuthType Kerberos&lt;/span&gt;&lt;br /&gt;
&lt;span class="highlight-add"&gt;   KrbAuthRealms CORP.EXAMPLE.COM&lt;/span&gt;&lt;br /&gt;
&lt;span class="highlight-add"&gt;   KrbServiceName HTTP/icinga.example.com@CORP.EXAMPLE.COM&lt;/span&gt;&lt;br /&gt;
&lt;span class="highlight-add"&gt;   Krb5Keytab /etc/httpd/conf/icinga.example.com.keytab&lt;/span&gt;&lt;br /&gt;
&lt;span class="highlight-add"&gt;   KrbMethodNegotiate on&lt;/span&gt;&lt;br /&gt;
&lt;span class="highlight-add"&gt;   KrbMethodK5Passwd on&lt;/span&gt;&lt;br /&gt;
&lt;span class="highlight-add"&gt;#   AuthUserFile /etc/icinga/htpasswd.users&lt;/span&gt;&lt;br /&gt;
   Require valid-user&lt;br /&gt;
&lt;br /&gt;
Alias /icinga "/usr/share/icinga/"&lt;br /&gt;

&amp;lt;Directory "/usr/share/icinga/"&lt;br /&gt;
#  SSLRequireSSL&lt;br /&gt;
   Options None&lt;br /&gt;
   AllowOverride All&lt;br /&gt;
   Order allow,deny&lt;br /&gt;
   Allow from all&lt;br /&gt;
#  Order deny,allow&lt;br /&gt;
#  Deny from all&lt;br /&gt;
#  Allow from 127.0.0.1&lt;br /&gt;
   AuthName "Icinga Access"&lt;br /&gt;
&lt;span class="highlight-add"&gt;# AuthType Basic&lt;/span&gt;&lt;br /&gt;
&lt;span class="highlight-add"&gt;   AuthType Kerberos&lt;/span&gt;&lt;br /&gt;
&lt;span class="highlight-add"&gt;   KrbAuthRealms CORP.EXAMPLE.COM&lt;/span&gt;&lt;br /&gt;
&lt;span class="highlight-add"&gt;   KrbServiceName HTTP/icinga.example.com@CORP.EXAMPLE.COM&lt;/span&gt;&lt;br /&gt;
&lt;span class="highlight-add"&gt;   Krb5Keytab /etc/httpd/conf/icinga.example.com.keytab&lt;/span&gt;&lt;br /&gt;
&lt;span class="highlight-add"&gt;   KrbMethodNegotiate on&lt;/span&gt;&lt;br /&gt;
&lt;span class="highlight-add"&gt;   KrbMethodK5Passwd on&lt;/span&gt;&lt;br /&gt;
&lt;span class="highlight-add"&gt;#   AuthUserFile /etc/icinga/htpasswd.users&lt;/span&gt;&lt;br /&gt;
   Require valid-user
&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;Restart Apache (/etc/init.d/httpd restart) and you should be able to authenticate via IWA to your Icinga site.&lt;/p&gt;
&lt;h3&gt;Grant IWA Credentials Access to the Icinga CGIs&lt;/h3&gt;
&lt;p&gt;mod_auth_kerberos will set your username to your userPrincipalName from AD.
In my implementation, the entire userPrincipalName was converted to upper
case, even though it wasn't set that way in Active Directory.  So for this
example my username according to Icinga would be CDUCK@CORP.EXAMPLE.COM.  This
is the value that you need to use to grant permissions in the Icinga CGIs
(&lt;a href="http://docs.icinga.org/1.5.0/en/cgiauth.html"&gt;http://docs.icinga.org/1.5.0/en/cgiauth.html&lt;/a&gt;).
In my case, my Icinga CGI config file was at /etc/icinga/cgi.cfg and I edited
the following lines to grant my account access:&lt;/p&gt;
&lt;blockquote&gt;&lt;span class="code"&gt;authorized_for_system_information=CDUCK@CORP.EXAMPLE.COM&lt;br /&gt;
authorized_for_configuration_information=CDUCK@CORP.EXAMPLE.COM&lt;br /&gt;
authorized_for_system_commands=CDUCK@CORP.EXAMPLE.COM&lt;br /&gt;
authorized_for_all_service_commands=CDUCK@CORP.EXAMPLE.COM&lt;br /&gt;
authorized_for_all_host_commands=CDUCK@CORP.EXAMPLE.COM&lt;/span&gt;
&lt;/blockquote&gt;
&lt;/p&gt;&lt;p&gt;You'll want to read the Icinga documentation on the CGI authorization and determine what is appropriate for your environment.&lt;/p&gt;
&lt;p&gt;***** Updated 3-24-2012 - The crypto parameter for the ktpass utility should read "RC4-HMAC-NT" as pointed out by reader Stefan.  Thanks for the correction!&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=F8sOkrSReBw:kMITzAJtoLE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=F8sOkrSReBw:kMITzAJtoLE:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=F8sOkrSReBw:kMITzAJtoLE:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=F8sOkrSReBw:kMITzAJtoLE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=F8sOkrSReBw:kMITzAJtoLE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=F8sOkrSReBw:kMITzAJtoLE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=F8sOkrSReBw:kMITzAJtoLE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=F8sOkrSReBw:kMITzAJtoLE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatsUpDuckBlog/~4/F8sOkrSReBw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.whatsupduck.net/feeds/6113087145179722029/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.whatsupduck.net/2011/10/configuring-icinga-classic-for-active.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/6113087145179722029?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/6113087145179722029?v=2" /><link rel="alternate" type="text/html" href="http://blog.whatsupduck.net/2011/10/configuring-icinga-classic-for-active.html" title="Configuring Icinga Classic for Active Directory Authentication via IWA" /><author><name>Chris Duck</name><uri>https://plus.google.com/111921112014612222144</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh3.googleusercontent.com/-hxGXvYzzwjM/AAAAAAAAAAI/AAAAAAAABZ4/NJmNBRF_ALc/s512-c/photo.jpg" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;C0cERXcyeip7ImA9WhdbFEQ.&quot;"><id>tag:blogger.com,1999:blog-7728225756528319729.post-5795470142767204360</id><published>2011-05-02T18:42:00.000-05:00</published><updated>2011-10-13T02:30:04.992-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-13T02:30:04.992-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="access denied" /><category scheme="http://www.blogger.com/atom/ns#" term="rest" /><category scheme="http://www.blogger.com/atom/ns#" term="net40" /><category scheme="http://www.blogger.com/atom/ns#" term="wcf" /><title>WCF REST Services on IIS7</title><content type="html">&lt;p&gt;If you're using everything below:
&lt;ul&gt;
&lt;li&gt;A .svc file for activation,      hosted locally (not over UNC) with or without fixed credentails&lt;/li&gt;
&lt;li&gt;Windows Authentication&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;You will fall under the "NTFS ACL-based Authorization" rules in this document (&lt;a href="http://technet.microsoft.com/en-us/library/dd163543.aspx"&gt;http://technet.microsoft.com/en-us/library/dd163543.aspx&lt;/a&gt; ).&amp;nbsp; If that is the case and you are developing a REST service, you will probably experience an Access Denied error the first time you try and PUT a new object (assuming your application doesn't have write access to its own code).&lt;/p&gt;
&lt;p&gt;The NTFS ACL-based authorization is built in to the core of IIS 7 so there is no way to disable it, except for breaking one of the conditions that triggers it.&amp;nbsp; The solution for me was to eliminate the physical file that my service was mapping to (ie my ServiceName.svc file).&amp;nbsp; This is possible due to a new feature in .Net 4.0 called Configuration-Based Activation (CBA).&lt;/p&gt;
&lt;p&gt;You can read a little bit about CBA and see the basic configuration here: &lt;a href="http://blogs.msdn.com/b/rampo/archive/2009/10/27/activation-without-svc-files-config-based-activation-cba.aspx"&gt;http://blogs.msdn.com/b/rampo/archive/2009/10/27/activation-without-svc-files-config-based-activation-cba.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This site has a full example of a service along with the full configuration: &lt;a href="http://geekswithblogs.net/michelotti/archive/2010/08/21/restful-wcf-services-with-no-svc-file-and-no-config.aspx"&gt;http://geekswithblogs.net/michelotti/archive/2010/08/21/restful-wcf-services-with-no-svc-file-and-no-config.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Neither of these sites was enough to get my service working though.&amp;nbsp; I had a service that was telling me it could not work with Windows authentication turned on and that I needed to enable Anonymous.&amp;nbsp; The bit that I was missing from my config was this:&lt;/p&gt;
&lt;div class="tab code"&gt;&amp;lt;system.serviceModel&amp;gt;&lt;br /&gt;
  &lt;div class="tab code"&gt;&amp;lt;bindings&amp;gt;&lt;br /&gt;
    &lt;div class="tab code"&gt;&amp;lt;basicHttpBinding&amp;gt;&lt;br /&gt;
      &lt;div class="tab code"&gt;&amp;lt;binding&amp;gt;&lt;br /&gt;
        &lt;div class="tab code"&gt;&amp;lt;security mode="TransportCredentialOnly"&amp;gt;&lt;br /&gt;
          &lt;div class="tab code"&gt;&amp;lt;transport clientCredentialType="Windows" /&amp;gt;&lt;/div&gt;
        &amp;lt;/security&amp;gt;&lt;/div&gt;
      &amp;lt;/binding&amp;gt;&lt;/div&gt;
    &amp;lt;/basicHttpBinding&amp;gt;&lt;/div&gt;
  &amp;lt;/bindings&amp;gt;&lt;/div&gt;
&amp;lt;/system.serviceModel&amp;gt;&lt;/div&gt;
&lt;p&gt;Which I found here: &lt;a href="http://blogs.msdn.com/b/drnick/archive/2007/03/23/preventing-anonymous-access.aspx"&gt;http://blogs.msdn.com/b/drnick/archive/2007/03/23/preventing-anonymous-access.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;At this point, I stopped getting errors, but my service only returned blank pages, not any data.&amp;nbsp; The last piece was to configure my service activation element with the System.ServiceModel.Activation.WebServiceHostFactory like this:&lt;/p&gt;
&lt;div class="tab code"&gt;&amp;lt;system.serviceModel&amp;gt;&lt;br /&gt;
  &lt;div class="tab code"&gt;&amp;lt;serviceHostingEnvironment aspNetCompatibilityEnabled="true"&amp;gt;&lt;br /&gt;
    &lt;div class="tab code"&gt;&amp;lt;serviceActivations&amp;gt;&lt;br /&gt;
      &lt;div class="tab code"&gt;&amp;lt;add&lt;br /&gt;
        &lt;div class="tab code"&gt;&lt;span class="highlight-add"&gt;factory="System.ServiceModel.Activation.WebServiceHostFactory"&lt;/span&gt;&lt;br /&gt;
          relativeAddress="ServiceName.svc"&lt;br /&gt;
          service="Namespace.ServiceClass" /&amp;gt;&lt;/div&gt;&lt;/div&gt;
      &amp;lt;/serviceActivations&amp;gt;&lt;/div&gt;
    &amp;lt;/serviceHostingEnvironment&amp;gt;&lt;/div&gt;
&amp;lt;/system.serviceModel&amp;gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=K7i8y7kdbII:kBWHNENMlGE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=K7i8y7kdbII:kBWHNENMlGE:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=K7i8y7kdbII:kBWHNENMlGE:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=K7i8y7kdbII:kBWHNENMlGE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=K7i8y7kdbII:kBWHNENMlGE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=K7i8y7kdbII:kBWHNENMlGE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=K7i8y7kdbII:kBWHNENMlGE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=K7i8y7kdbII:kBWHNENMlGE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatsUpDuckBlog/~4/K7i8y7kdbII" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.whatsupduck.net/feeds/5795470142767204360/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.whatsupduck.net/2011/05/wcf-rest-services-on-iis7.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/5795470142767204360?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/5795470142767204360?v=2" /><link rel="alternate" type="text/html" href="http://blog.whatsupduck.net/2011/05/wcf-rest-services-on-iis7.html" title="WCF REST Services on IIS7" /><author><name>Chris Duck</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DkAMQH84fip7ImA9WhBREEw.&quot;"><id>tag:blogger.com,1999:blog-7728225756528319729.post-44790572143291642</id><published>2011-04-26T18:24:00.000-05:00</published><updated>2013-02-27T19:26:21.136-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-27T19:26:21.136-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="powershell" /><category scheme="http://www.blogger.com/atom/ns#" term="patches" /><category scheme="http://www.blogger.com/atom/ns#" term="exchange" /><title>April MS Patch Issue</title><content type="html">&lt;p&gt;After deploying our April patches we were having trouble with our Exchange servers, specifically our web mail servers were not responsive and we had high cpu utilization on all our Exchange (2010) boxes (sorry, I don't know exactly which process was going crazy with the CPU).  In our initial troubleshooting, it was discovered that other symptoms were Event Viewer and Powershell both crashed immediately upon loading.  This pointed us to &lt;a href="http://support.microsoft.com/kb/2540222"&gt;KB2540222&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The problem turns out to be an older patch (979744) and there is also an easy way to detect the problem before the new patches cause it and a new version of 979744 that can be installed to prevent the issue.&lt;/p&gt;
&lt;p&gt;I wrote the following quick script to check all servers on our network for the bad version of the patch so we could get them all updated during our maintenance window, even if we weren't experiencing a problem with them at the time. &amp;nbsp;This script queries your Active Directory to locate servers to check and then uses your current credentials to make a remote registry query to check the keys listed in the KB for the broken version of the patch. &amp;nbsp;It assumes that you only have server computer objects in your OU and that you aren't running IA-64 based servers (it only checks 2008 x86, 2008 x64, and 2008 R2 registry paths). &amp;nbsp;The script displays the computers with the broken patch on the screen as well as saving them to the $broken variable.&lt;/p&gt;
&lt;!--Start Script--&gt;
&lt;div class='embedded-code-wrapper'&gt;
&lt;TABLE BORDER='0' cellpadding='5' cellspacing='0'&gt; 
&lt;TR&gt; 
    &lt;TD VALIGN='Top'&gt;&lt;div class='line-no-column'&gt;001&lt;BR /&gt;002&lt;BR /&gt;003&lt;BR /&gt;004&lt;BR /&gt;005&lt;BR /&gt;006&lt;BR /&gt;007&lt;BR /&gt;008&lt;BR /&gt;009&lt;BR /&gt;010&lt;BR /&gt;011&lt;BR /&gt;012&lt;BR /&gt;013&lt;BR /&gt;014&lt;BR /&gt;015&lt;BR /&gt;016&lt;BR /&gt;017&lt;BR /&gt;018&lt;BR /&gt;019&lt;BR /&gt;020&lt;BR /&gt;021&lt;BR /&gt;022&lt;BR /&gt;023&lt;BR /&gt;024&lt;BR /&gt;025&lt;BR /&gt;026&lt;BR /&gt;027&lt;BR /&gt;028&lt;BR /&gt;029&lt;BR /&gt;030&lt;BR /&gt;
&lt;/DIV&gt; 
    &lt;/TD&gt; 
    &lt;TD VALIGN='Top' NOWRAP='NOWRAP'&gt;&lt;div class='embedded-code-body'&gt;&lt;span class='psVariable'&gt;$RootOU&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;ou=servers,dc=contoso,dc=com&amp;quot;&lt;/span&gt;
&lt;span class='psVariable'&gt;$Timeout&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psNumber'&gt;100&lt;/span&gt;

&lt;span class='psVariable'&gt;$x86&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages\Package_for_KB979744~31bf3856ad364e35~x86~~6.0.1.0&amp;quot;&lt;/span&gt;
&lt;span class='psVariable'&gt;$x64&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages\Package_for_KB979744~31bf3856ad364e35~amd64~~6.0.1.0&amp;quot;&lt;/span&gt;
&lt;span class='psVariable'&gt;$r2&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages\Package_for_KB979744~31bf3856ad364e35~amd64~~6.1.1.0&amp;quot;&lt;/span&gt;

&lt;span class='psVariable'&gt;$ds&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;new-object&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandArgument'&gt;DirectoryServices.DirectorySearcher&lt;/span&gt;
&lt;span class='psVariable'&gt;$ds&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;filter&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;(objectcategory=computer)&amp;quot;&lt;/span&gt;
&lt;span class='psVariable'&gt;$ds&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;searchroot&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psType'&gt;[adsi]&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;LDAP://$RootOU&amp;quot;&lt;/span&gt;
&lt;span class='psVariable'&gt;$computers&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$ds&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;findall&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;|&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;%&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$_&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;properties&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;cn&lt;/span&gt;&lt;span class='psOperator'&gt;[&lt;/span&gt;&lt;span class='psNumber'&gt;0&lt;/span&gt;&lt;span class='psOperator'&gt;]&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;

&lt;span class='psVariable'&gt;$ping&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;new-object&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandArgument'&gt;net.networkinformation.ping&lt;/span&gt;

&lt;span class='psVariable'&gt;$broken&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$computers&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;|&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;%&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$computer&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$_&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;if&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;$ping&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;send&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;$_&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$timeout&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;status&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;-eq&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;Success&amp;quot;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$hklm&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psType'&gt;[Microsoft.Win32.RegistryKey]&lt;/span&gt;&lt;span class='psOperator'&gt;::&lt;/span&gt;&lt;span class='psMember'&gt;OpenRemoteBaseKey&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psType'&gt;[Microsoft.Win32.RegistryHive]&lt;/span&gt;&lt;span class='psOperator'&gt;::&lt;/span&gt;&lt;span class='psMember'&gt;LocalMachine&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$computer&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$x86&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$x64&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$r2&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;|&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;%&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$key&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$hklm&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;opensubkey&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;$_&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;if&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;$key&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;if&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;$key&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;getValue&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;currentstate&amp;quot;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;-eq&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psNumber'&gt;7&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;Write-Host&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;$Computer is broken&amp;quot;&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$computer&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;
&lt;span class='psGroupEnd'&gt;}&lt;/span&gt; 
&lt;/DIV&gt; 
    &lt;/TD&gt; 
&lt;/TR&gt; 
&lt;/TBODY&gt; 
&lt;/TABLE&gt; 
&lt;/DIV&gt;
&lt;!--End Script--&gt;
&lt;p&gt;Once you have identified all the servers that need the new version of 979744, you can download it from the link above, making sure to grab the V2 version for your OS and architecture.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=xgJA4C9Oshw:6n3DKhtsFJc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=xgJA4C9Oshw:6n3DKhtsFJc:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=xgJA4C9Oshw:6n3DKhtsFJc:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=xgJA4C9Oshw:6n3DKhtsFJc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=xgJA4C9Oshw:6n3DKhtsFJc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=xgJA4C9Oshw:6n3DKhtsFJc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=xgJA4C9Oshw:6n3DKhtsFJc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=xgJA4C9Oshw:6n3DKhtsFJc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatsUpDuckBlog/~4/xgJA4C9Oshw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.whatsupduck.net/feeds/44790572143291642/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.whatsupduck.net/2011/04/april-ms-patch-issue.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/44790572143291642?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/44790572143291642?v=2" /><link rel="alternate" type="text/html" href="http://blog.whatsupduck.net/2011/04/april-ms-patch-issue.html" title="April MS Patch Issue" /><author><name>Chris Duck</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0YGQHw8cCp7ImA9WhBREEw.&quot;"><id>tag:blogger.com,1999:blog-7728225756528319729.post-6223456932434903569</id><published>2011-03-19T14:26:00.001-05:00</published><updated>2013-02-27T19:32:01.278-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-27T19:32:01.278-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="sql" /><category scheme="http://www.blogger.com/atom/ns#" term="powershell" /><category scheme="http://www.blogger.com/atom/ns#" term="binary" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><category scheme="http://www.blogger.com/atom/ns#" term="sid" /><title>Convert a Windows SID from Binary to SDDL Form</title><content type="html">&lt;p&gt;At work I had a problem that required me to decode a SID that was stored in a database in binary form in order to locate the user/group that it represented. It turns out this is fairly easy to do, but I&amp;nbsp;couldn't&amp;nbsp;find a Powershell solution online and the solutions in those "other" languages tended to be overly complicated.&lt;/p&gt;
&lt;h3&gt;Getting the Initial Data&lt;/h3&gt;
&lt;p&gt;The first task was to get from the binary data from SQL into an appropriate .Net object. &amp;nbsp;Browsing through MSDN, it looks like &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.principal.securityidentifier.aspx"&gt;System.Security.Principal.SecurityIdentifier&lt;/a&gt; would be a good choice :)&lt;/p&gt;
&lt;!--Start Script--&gt;
&lt;div class='embedded-code-wrapper'&gt;
&lt;TABLE BORDER='0' cellpadding='5' cellspacing='0'&gt; 
&lt;TR&gt; 
    &lt;TD VALIGN='Top'&gt;&lt;div class='line-no-column'&gt;001&lt;BR /&gt;002&lt;BR /&gt;003&lt;BR /&gt;004&lt;BR /&gt;
&lt;/DIV&gt; 
    &lt;/TD&gt; 
    &lt;TD VALIGN='Top' NOWRAP='NOWRAP'&gt;&lt;div class='embedded-code-body'&gt;&lt;span class='psCommand'&gt;Add-PSSnapin&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandArgument'&gt;SqlServerCmdletSnapin100&lt;/span&gt;

&lt;span class='psVariable'&gt;$binsid&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psCommand'&gt;Invoke-SQLCmd&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;SELECT operators_sid FROM [FIMDatabase].[mms_server_configuration]&amp;quot;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;operators_sid&lt;/span&gt;
&lt;span class='psVariable'&gt;$sid&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;new-object&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandArgument'&gt;security.principal.securityidentifier&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;$binsid&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psNumber'&gt;0&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt; 
&lt;/DIV&gt; 
    &lt;/TD&gt; 
&lt;/TR&gt; 
&lt;/TBODY&gt; 
&lt;/TABLE&gt; 
&lt;/DIV&gt;
&lt;!--End Script--&gt;
&lt;h3&gt;Converting From a SID to a Principal&lt;/h3&gt;
&lt;p&gt;Now that we have a SID object we can use that to convert the binary SID to a string and then use the string value to search either our local SAM database or an Active Directory Domain to locate the account the SID represents. &amp;nbsp;For this task, I've written a script called Get-Principal.ps1:&lt;/p&gt;
&lt;a name="Get-Principal.ps1"&gt;&lt;/a&gt;
&lt;!--Start Script--&gt;
&lt;div class='embedded-code-wrapper'&gt;
&lt;TABLE BORDER='0' cellpadding='5' cellspacing='0'&gt; 
&lt;TR&gt; 
    &lt;TD VALIGN='Top'&gt;&lt;div class='line-no-column'&gt;001&lt;BR /&gt;002&lt;BR /&gt;003&lt;BR /&gt;004&lt;BR /&gt;005&lt;BR /&gt;006&lt;BR /&gt;007&lt;BR /&gt;008&lt;BR /&gt;009&lt;BR /&gt;010&lt;BR /&gt;011&lt;BR /&gt;012&lt;BR /&gt;013&lt;BR /&gt;014&lt;BR /&gt;015&lt;BR /&gt;016&lt;BR /&gt;017&lt;BR /&gt;018&lt;BR /&gt;019&lt;BR /&gt;020&lt;BR /&gt;021&lt;BR /&gt;022&lt;BR /&gt;023&lt;BR /&gt;024&lt;BR /&gt;025&lt;BR /&gt;026&lt;BR /&gt;027&lt;BR /&gt;028&lt;BR /&gt;029&lt;BR /&gt;030&lt;BR /&gt;031&lt;BR /&gt;032&lt;BR /&gt;033&lt;BR /&gt;034&lt;BR /&gt;035&lt;BR /&gt;036&lt;BR /&gt;037&lt;BR /&gt;038&lt;BR /&gt;039&lt;BR /&gt;040&lt;BR /&gt;041&lt;BR /&gt;042&lt;BR /&gt;043&lt;BR /&gt;044&lt;BR /&gt;045&lt;BR /&gt;046&lt;BR /&gt;047&lt;BR /&gt;048&lt;BR /&gt;049&lt;BR /&gt;050&lt;BR /&gt;051&lt;BR /&gt;052&lt;BR /&gt;053&lt;BR /&gt;054&lt;BR /&gt;055&lt;BR /&gt;056&lt;BR /&gt;057&lt;BR /&gt;058&lt;BR /&gt;059&lt;BR /&gt;060&lt;BR /&gt;061&lt;BR /&gt;062&lt;BR /&gt;063&lt;BR /&gt;064&lt;BR /&gt;065&lt;BR /&gt;066&lt;BR /&gt;067&lt;BR /&gt;068&lt;BR /&gt;069&lt;BR /&gt;070&lt;BR /&gt;071&lt;BR /&gt;072&lt;BR /&gt;073&lt;BR /&gt;074&lt;BR /&gt;075&lt;BR /&gt;076&lt;BR /&gt;077&lt;BR /&gt;078&lt;BR /&gt;079&lt;BR /&gt;080&lt;BR /&gt;081&lt;BR /&gt;082&lt;BR /&gt;083&lt;BR /&gt;084&lt;BR /&gt;085&lt;BR /&gt;086&lt;BR /&gt;087&lt;BR /&gt;088&lt;BR /&gt;089&lt;BR /&gt;090&lt;BR /&gt;091&lt;BR /&gt;092&lt;BR /&gt;093&lt;BR /&gt;094&lt;BR /&gt;095&lt;BR /&gt;096&lt;BR /&gt;097&lt;BR /&gt;098&lt;BR /&gt;
&lt;/DIV&gt; 
    &lt;/TD&gt; 
    &lt;TD VALIGN='Top' NOWRAP='NOWRAP'&gt;&lt;div class='embedded-code-body'&gt;&lt;span class='psComment'&gt;&amp;lt;#
.SYNOPSIS

Gets a principal object from either an Active Directory Domain or a &amp;quot;local&amp;quot; SAM account database.
This can be either a user or a group. Note that this is not a search function, you must fully specify
a unique identifier for a principal.

.DESCRIPTION

Uses the System.DirectoryServices.AccountManagement namespace introduced in .Net 3.5 to locate
a principal object. Can bind on any property in the System.DirectoryServices.AccountManagement.IdentityType
enumeration (SamAccountName, Name, UserPrincipalName, DistinguishedName, Sid (in SDDL form), or Guid).

.PARAMETER Identity

The value to match on as a string. Should be one of the following:

SamAccountName (Administrator)
Name (Smith)
UserPrincipalName (user@domain.com)
DistinguishedName (cn=smith,ou=users,dc=domain,dc=com)
Sid (S-1-5-32-544)
Guid (0d15a1bb-dbec-4855-b949-25999828c24c)

.PARAMETER DomainName

The domain name to query. If none of DomainName, ComputerName, or Local are specified,
the default domain is queried. This can be specified as the NetBIOS name or FQDN of 
the domain.

.PARAMETER ComputerName

The name of the computer to query.

.PARAMETER Local

Query the local computer.

.EXAMPLE

Get the Administrators group on the local computer.

.\Find-Principal.ps1 Administrators -local

.EXAMPLE

Get a principal for a user named jsmith on the default domain.

.\Find-Principal.ps1 jsmith

.EXMAPLE

Get the user with sid S-1-5-21-654981354-654786135-6565798-327 on the domain example.com.

.\Find-Principal.ps1 &amp;quot;S-1-5-21-654981354-654786135-6565798-327&amp;quot; -domain &amp;quot;example.com&amp;quot;

.NOTES

This function requires .Net 3.5 or greater.

#&amp;gt;&lt;/span&gt;
&lt;span class='psOperator'&gt;[&lt;/span&gt;&lt;span class='psAttribute'&gt;CmdletBinding&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psMember'&gt;DefaultParametersetName&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;Domain&amp;quot;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psOperator'&gt;]&lt;/span&gt;
&lt;span class='psKeyword'&gt;Param&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;[&lt;/span&gt;&lt;span class='psAttribute'&gt;Parameter&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psMember'&gt;Position&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psNumber'&gt;0&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psMember'&gt;ValueFromPipeline&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psVariable'&gt;$true&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psMember'&gt;Mandatory&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psVariable'&gt;$true&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psOperator'&gt;]&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$Identity&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;[&lt;/span&gt;&lt;span class='psAttribute'&gt;Parameter&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psMember'&gt;ParameterSetName&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;Domain&amp;quot;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psOperator'&gt;]&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$DomainName&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;[&lt;/span&gt;&lt;span class='psAttribute'&gt;Parameter&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psMember'&gt;ParameterSetName&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;Computer&amp;quot;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psOperator'&gt;]&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$ComputerName&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;[&lt;/span&gt;&lt;span class='psAttribute'&gt;Parameter&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psMember'&gt;ParameterSetName&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;Computer&amp;quot;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psOperator'&gt;]&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psType'&gt;[switch]&lt;/span&gt;&lt;span class='psVariable'&gt;$Local&lt;/span&gt;
&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;

&lt;span class='psKeyword'&gt;if&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psOperator'&gt;!&lt;/span&gt;&lt;span class='psType'&gt;[reflection.assembly]&lt;/span&gt;&lt;span class='psOperator'&gt;::&lt;/span&gt;&lt;span class='psMember'&gt;LoadWithPartialName&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;System.DirectoryServices.AccountManagement&amp;quot;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;throw&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;.Net 3.5 required to run Find-Principal&amp;quot;&lt;/span&gt;
&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;

&lt;span class='psKeyword'&gt;switch&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;$PsCmdlet&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;ParameterSetName&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;Domain&amp;quot;&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;if&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;$DomainName&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&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;&lt;/span&gt;&lt;span class='psVariable'&gt;$ctx&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;New-Object&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandArgument'&gt;System.DirectoryServices.AccountManagement.PrincipalContext&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psType'&gt;[System.DirectoryServices.AccountManagement.ContextType]&lt;/span&gt;&lt;span class='psOperator'&gt;::&lt;/span&gt;&lt;span class='psMember'&gt;Domain&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$DomainName&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;else&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&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;&lt;/span&gt;&lt;span class='psVariable'&gt;$ctx&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;New-Object&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandArgument'&gt;System.DirectoryServices.AccountManagement.PrincipalContext&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psType'&gt;[System.DirectoryServices.AccountManagement.ContextType]&lt;/span&gt;&lt;span class='psOperator'&gt;::&lt;/span&gt;&lt;span class='psMember'&gt;Domain&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;Computer&amp;quot;&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;if&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;$ComputerName&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&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;&lt;/span&gt;&lt;span class='psVariable'&gt;$ctx&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;New-Object&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandArgument'&gt;System.DirectoryServices.AccountManagement.PrincipalContext&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psType'&gt;[System.DirectoryServices.AccountManagement.ContextType]&lt;/span&gt;&lt;span class='psOperator'&gt;::&lt;/span&gt;&lt;span class='psMember'&gt;Machine&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$ComputerName&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;else&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&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;&lt;/span&gt;&lt;span class='psVariable'&gt;$ctx&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;New-Object&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandArgument'&gt;System.DirectoryServices.AccountManagement.PrincipalContext&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psType'&gt;[System.DirectoryServices.AccountManagement.ContextType]&lt;/span&gt;&lt;span class='psOperator'&gt;::&lt;/span&gt;&lt;span class='psMember'&gt;Machine&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$env:computername&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;
&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;

&lt;span class='psKeyword'&gt;return&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psType'&gt;[System.DirectoryServices.AccountManagement.Principal]&lt;/span&gt;&lt;span class='psOperator'&gt;::&lt;/span&gt;&lt;span class='psMember'&gt;FindByIdentity&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;$ctx&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$identity&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt; 
&lt;/DIV&gt; 
    &lt;/TD&gt; 
&lt;/TR&gt; 
&lt;/TBODY&gt; 
&lt;/TABLE&gt; 
&lt;/DIV&gt;
&lt;!--End Script--&gt;
&lt;p&gt;Now we can take the string SID from $sid.ToString() and resolve the SID to either an account or group on the domain:&lt;/p&gt;
&lt;p&gt;&lt;span class="code"&gt;.\Get-Principal.ps1 $sid.ToString()&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;or on the local computer:&lt;/p&gt;
&lt;p&gt;&lt;span class="code"&gt;.\Get-Principal.ps1 $sid.ToString() -Local&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;Converting a Principal Back to a Binary SID&lt;/h3&gt;
&lt;p&gt;Going the other way is just as simple... there is a method on&amp;nbsp;&lt;a href="http://msdn.microsoft.com/en-us/library/system.security.principal.securityidentifier.aspx"&gt;System.Security.Principal.SecurityIdentifier&lt;/a&gt;&amp;nbsp;called GetBinaryForm that takes a byte array and populates it with the binary SID. &amp;nbsp;You just have to make sure that you create an empty byte array with enough space to hold the SID:&lt;/p&gt;
&lt;p&gt;&lt;span class="code"&gt;#Get the SID for the local Administrators group as an example&lt;br /&gt;
$sid = (.\Get-Principal "Administrators" -local).sid&lt;br /&gt;
&lt;br /&gt;
#Create a byte array long enough to hold the whole SID&lt;br /&gt;
$BinarySid = new-object byte[]($sid.BinaryLength)&lt;br /&gt;
&lt;br /&gt;
#Copy the binary sid into the byte array, starting at index 0&lt;br /&gt;
$sid.GetBinaryForm($BinarySid, 0)&lt;br /&gt;
&lt;br /&gt;
$BinarySid&lt;br /&gt;
1&lt;br /&gt;
2&lt;br /&gt;
0&lt;br /&gt;
0&lt;br /&gt;
0&lt;br /&gt;
0&lt;br /&gt;
0&lt;br /&gt;
5&lt;br /&gt;
32&lt;br /&gt;
0&lt;br /&gt;
0&lt;br /&gt;
0&lt;br /&gt;
32&lt;br /&gt;
2&lt;br /&gt;
0&lt;br /&gt;
0&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;Saving it Back to SQL&lt;/h3&gt;
&lt;p&gt;To bring this example back around full circle, the last bit is to save the new binary SID back into the database:&lt;/p&gt;
&lt;span class="code"&gt;#Create a template string to perform the update in SQL, in my case there is only 1 row in the table so it is easy&lt;br /&gt;
$SQLUpdate = "UPDATE [FIMDatabase].[mms_server_configuration] set [&lt;span class="Apple-style-span" style="color: darkred; font-family: Consolas, 'Lucida Console'; font-size: 13px; white-space: nowrap;"&gt;operators_sid&lt;/span&gt;] = {0}"&lt;br /&gt;
Invoke-SQLCmd ($SQLUpdate -f $BinarySid)&lt;br /&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I'll talk about why I'm actually doing all this in another post.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=oERGn-3I0H0:qPM-DnOYPeo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=oERGn-3I0H0:qPM-DnOYPeo:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=oERGn-3I0H0:qPM-DnOYPeo:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=oERGn-3I0H0:qPM-DnOYPeo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=oERGn-3I0H0:qPM-DnOYPeo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=oERGn-3I0H0:qPM-DnOYPeo:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=oERGn-3I0H0:qPM-DnOYPeo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=oERGn-3I0H0:qPM-DnOYPeo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatsUpDuckBlog/~4/oERGn-3I0H0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.whatsupduck.net/feeds/6223456932434903569/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.whatsupduck.net/2011/03/convert-windows-sid-from-binary-to-sddl.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/6223456932434903569?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/6223456932434903569?v=2" /><link rel="alternate" type="text/html" href="http://blog.whatsupduck.net/2011/03/convert-windows-sid-from-binary-to-sddl.html" title="Convert a Windows SID from Binary to SDDL Form" /><author><name>Chris Duck</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CUIMQHg9cCp7ImA9WhNSE0o.&quot;"><id>tag:blogger.com,1999:blog-7728225756528319729.post-5547159560244082435</id><published>2010-09-24T15:38:00.001-05:00</published><updated>2012-10-27T16:33:01.668-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-27T16:33:01.668-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="powershell" /><title>Issues With Configuring Powershell ExecutionPolicy via Group Policy</title><content type="html">&lt;p&gt;When you publish an ExecutionPolicy for Powershell via Group Policy, several issues will crop up.  The first I came across is that it breaks several of the Best Practices Analyzers.  The second is that it breaks some of the &lt;a href="http://support.microsoft.com/kb/981474"&gt;Exchange 2010 installers&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;You can reproduce this error on 2008 R2 with IIS or the File Services role installed:&lt;/p&gt;&lt;blockquote&gt;&lt;ol&gt;&lt;li&gt;Make sure your ExecutionPolicy is only defined locally:&lt;br /&gt;
&lt;blockquote&gt;&lt;span class="code"&gt;PS&amp;gt; Set-ExecutionPolicy RemoteSigned -Force&lt;br /&gt;
PS&amp;gt; Get-ExecutionPolicy -List&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MachinePolicy = Undefined&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;UserPolicy = Undefined&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Process = Undefined&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CurrentUser = Undefined&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LocalMachine = RemoteSigned&lt;/span&gt;&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;Run the IIS or File Services BPA, this should be successful&lt;/li&gt;
&lt;li&gt;Set the ExecutionPolicy in your Local Computer Policy:&lt;br /&gt;
&lt;blockquote&gt;Open Local Policy Editor, browse to Local Computer Policy&amp;gt; Computer Configuration&amp;gt; Administrative Templates&amp;gt; Windows Components&amp;gt; Windows Powershell.  Enable "Turn on Script Execution" and set the policy to "Allow local scripts and remote signed scripts".&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;Verify that your ExecutionPolicy is now defined as a Group/Local Policy:&lt;br /&gt;
&lt;blockquote&gt;&lt;span class="code"&gt;PS&amp;gt; Get-ExecutionPolicy -List&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MachinePolicy = RemoteSigned&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;UserPolicy = Undefined&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Process = Undefined&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CurrentUser = Undefined&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LocalMachine = RemoteSigned&lt;/span&gt;&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;Run IIS or File Services BPA, this fails with:&lt;br /&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;span class="code"&gt;There has been a Best Practice Analyzer engine error for Model ID:'Microsoft/Windows/FileServices' during execution of the Model. (Inner Exception: One or more model documents are invalid: {0} Discovery exception occurred proccessing file '{0}'.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span class="code"&gt;Windows PowerShell updated your execution policy successfully, but the setting is overridden by a policy defined at a more specific scope.  Due ot the override, your shell will retain its current effective execution policy of "RemoteSigned".&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;/blockquote&gt;&lt;p&gt;Rather than constantly have to move our Exchange servers in and out of the GPO, I decided to fix our issue by switching over to a Group Policy Preference that sets the same registry key as if you had typed &lt;span class="code"&gt;Set-ExecutionPolicy RemoteSigned&lt;/span&gt; at the command prompt.&lt;/p&gt;&lt;blockquote&gt;&lt;ol&gt;&lt;li&gt;Open Group Policy Management Editor&lt;/li&gt;
&lt;li&gt;Browse to Computer Configuration&amp;gt; Preferences&amp;gt;Windows Settings&amp;gt; Registry&lt;/li&gt;
&lt;li&gt;Right click and create a new registry item:&lt;br /&gt;
&lt;blockquote&gt;Action: &lt;span class="code"&gt;Update&lt;/span&gt;&lt;br /&gt;
Hive: &lt;span class="code"&gt;HKEY_LOCAL_MACHINE&lt;/span&gt;&lt;br /&gt;
Key Path: &lt;span class="code"&gt;SOFTWARE\Microsoft\PowersShell\1\ShellIds\Microsoft.PowerShell&lt;/span&gt;&lt;br /&gt;
Value name: &lt;span class="code"&gt;ExecutionPolicy&lt;/span&gt;&lt;br /&gt;
Value type: &lt;span class="code"&gt;REG_SZ&lt;/span&gt;&lt;br /&gt;
Value data: &lt;span class="code"&gt;RemoteSigned&lt;/span&gt;&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;Now create a second registry item that will cover 32-bit Powershell on 64-bit machines:&lt;br /&gt;
&lt;blockquote&gt;Action: &lt;span class="code"&gt;Update&lt;/span&gt;&lt;br /&gt;
Hive: &lt;span class="code"&gt;HKEY_LOCAL_MACHINE&lt;/span&gt;&lt;br /&gt;
Key Path: &lt;span class="code"&gt;SOFTWARE\Wow6432Node\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell&lt;/span&gt;&lt;br /&gt;
Value name: &lt;span class="code"&gt;ExecutionPolicy&lt;/span&gt;&lt;br /&gt;
Value type: &lt;span class="code"&gt;REG_SZ&lt;/span&gt;&lt;br /&gt;
Value data: &lt;span class="code"&gt;RemoteSigned&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
On the "Common" tab...&lt;br /&gt;
Check Item-level targeting&lt;br /&gt;
Press the "Targeting" button&lt;br /&gt;
Create a new "Environment Variable" item&lt;br /&gt;
Name: &lt;span class="code"&gt;PROCESSOR_ARCHITECTURE&lt;/span&gt;&lt;br /&gt;
Value: &lt;span class="code"&gt;AMD64&lt;/span&gt;&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;Verify that only the local settings are being applied and that the preference will reset the value if a user changes it:&lt;br /&gt;
&lt;blockquote&gt;&lt;span class="code"&gt;PS&amp;gt; Set-ExecutionPolicy Undefined -Force&lt;br /&gt;
PS&amp;gt; Get-ExecutionPolicy -List&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MachinePolicy = Undefined&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;UserPolicy = Undefined&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Process = Undefined&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CurrentUser = Undefined&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LocalMachine = Undefined&lt;br /&gt;
PS&amp;gt; gpupdate /force /target:computer&lt;br /&gt;
PS&amp;gt; Get-ExecutionPolicy -List&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MachinePolicy = Undefined&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;UserPolicy = Undefined&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Process = Undefined&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CurrentUser = Undefined&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LocalMachine = RemoteSigned&lt;/span&gt;&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;/blockquote&gt;&lt;p&gt;Note that this method does require the &lt;a href="http://support.microsoft.com/kb/943729"&gt;Group Policy Preferences Client&lt;/a&gt; to be installed on XP/Vista/2003 (it is included in Win7/2008/2008 R2) and be aware that an administrative user can easily override the ExecutionPolicy setting until Group Policy is applied again (although they could also override the Group Policy setting since they are admin, just not as easily).&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=mT-E2MRBgJ8:oxlL03YP-CE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=mT-E2MRBgJ8:oxlL03YP-CE:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=mT-E2MRBgJ8:oxlL03YP-CE:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=mT-E2MRBgJ8:oxlL03YP-CE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=mT-E2MRBgJ8:oxlL03YP-CE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=mT-E2MRBgJ8:oxlL03YP-CE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=mT-E2MRBgJ8:oxlL03YP-CE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=mT-E2MRBgJ8:oxlL03YP-CE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatsUpDuckBlog/~4/mT-E2MRBgJ8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.whatsupduck.net/feeds/5547159560244082435/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.whatsupduck.net/2010/09/issues-with-configuring-powershell.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/5547159560244082435?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/5547159560244082435?v=2" /><link rel="alternate" type="text/html" href="http://blog.whatsupduck.net/2010/09/issues-with-configuring-powershell.html" title="Issues With Configuring Powershell ExecutionPolicy via Group Policy" /><author><name>Chris Duck</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>3</thr:total></entry><entry gd:etag="W/&quot;DEQFSXoycCp7ImA9WxFUGUg.&quot;"><id>tag:blogger.com,1999:blog-7728225756528319729.post-2408647463499565111</id><published>2010-06-30T22:48:00.001-05:00</published><updated>2010-06-30T22:51:58.498-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-30T22:51:58.498-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="DRM" /><category scheme="http://www.blogger.com/atom/ns#" term="Hang" /><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight" /><title>The Case of the Silverlight Video Lockup</title><content type="html">I came home to a computer unwilling to play video today.  Netflix would launch the silverlight player, determine my video quality, buffer 5-30% of the video, then hard hang my computer.  I couldn't even get &lt;a href="http://msdn.microsoft.com/en-us/library/ff545499(VS.85).aspx"&gt;CrashOnCtrlScroll&lt;/a&gt; to work so I could try using WinDbg to determine what was causing the hang.&lt;br /&gt;
&lt;br /&gt;
After uninstalling loads of software and drivers (I had recently installed the Silverlight SDK, so I thought maybe that had something to do with it), I ended up in the system event log where I noticed this event:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;&lt;table&gt;&lt;tr&gt;     &lt;td colspan="2"&gt;Unused media renderer devices were not removed from the list of devices because required DRM components cannot run while a debugger is attached. Detach the debugger from the machine or from the WMPNetworkSvc service, and then restart the WMPNetworkSvc service.&lt;/td&gt;   &lt;/tr&gt;
&lt;tr&gt;     &lt;td&gt;&lt;b&gt;Log Name:&lt;/b&gt;&lt;/td&gt;&lt;td&gt;System&lt;/td&gt;   &lt;/tr&gt;
&lt;tr&gt;     &lt;td&gt;&lt;b&gt;Source:&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Windows Media Player Network Sharing Service&lt;/td&gt;   &lt;/tr&gt;
&lt;tr&gt;     &lt;td&gt;&lt;b&gt;Event ID:&lt;/b&gt;&lt;/td&gt;&lt;td&gt;14105&lt;/td&gt;   &lt;/tr&gt;
&lt;tr&gt;     &lt;td&gt;&lt;b&gt;Level:&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Warning&lt;/td&gt;   &lt;/tr&gt;
&lt;tr&gt;     &lt;td&gt;&lt;b&gt;OpCode:&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Info&lt;/td&gt;   &lt;/tr&gt;
&lt;/table&gt;&lt;/blockquote&gt;&lt;br /&gt;
At this point, I connected the dots that last night I had enabled live kernel debugging (&lt;span class="code"&gt;bcdedit /debug on&lt;/span&gt;) while working through one of the examples in &lt;a target="_blank"  href="http://www.amazon.com/Windows%C2%AE-Internals-Including-Windows-PRO-Developer/dp/0735625301?ie=UTF8&amp;tag=widgetsamazon-20&amp;link_code=btl&amp;camp=213689&amp;creative=392969"&gt;Windows® Internals, 5&lt;sup&gt;th&lt;/sup&gt; Edition&lt;/a&gt; (great book btw).  Disabling debugging and rebooting solved the hang.&lt;br /&gt;
&lt;br /&gt;
Apparently kernel debugging is the sworn enemy of watching 30 Rock on Netflix and Silverlight protects the content by hanging my computer.  Thanks a lot DRM.&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=PetHqCEv9zc:H-tIbgFpIxU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=PetHqCEv9zc:H-tIbgFpIxU:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=PetHqCEv9zc:H-tIbgFpIxU:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=PetHqCEv9zc:H-tIbgFpIxU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=PetHqCEv9zc:H-tIbgFpIxU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=PetHqCEv9zc:H-tIbgFpIxU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=PetHqCEv9zc:H-tIbgFpIxU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=PetHqCEv9zc:H-tIbgFpIxU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatsUpDuckBlog/~4/PetHqCEv9zc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.whatsupduck.net/feeds/2408647463499565111/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.whatsupduck.net/2010/06/case-of-silverlight-video-lockup.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/2408647463499565111?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/2408647463499565111?v=2" /><link rel="alternate" type="text/html" href="http://blog.whatsupduck.net/2010/06/case-of-silverlight-video-lockup.html" title="The Case of the Silverlight Video Lockup" /><author><name>Chris Duck</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0QMRnY-fip7ImA9WhBREEw.&quot;"><id>tag:blogger.com,1999:blog-7728225756528319729.post-5307603708782569157</id><published>2010-05-12T19:34:00.000-05:00</published><updated>2013-02-27T19:36:27.856-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-27T19:36:27.856-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="powershell" /><category scheme="http://www.blogger.com/atom/ns#" term="memory" /><title>Querying Peak Commit Bytes with Powershell (via NtQuerySystemInformation)</title><content type="html">&lt;p&gt;One of the more interesting values to determine how much memory to allocate a machine is the &lt;i&gt;Peak Committed Bytes&lt;/i&gt;. This value is available as &amp;quot;Commit Charge (K) - Peak&amp;quot; from Windows 2003 Task Manger and from &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx"&gt;Sysinternals Process Explorer&lt;/a&gt; and is a good representation of the maximum amount of memory that has been used at once since the computer was last rebooted. Wikipedia has more details about the &lt;a href="http://en.wikipedia.org/wiki/Commit_charge"&gt;Commit Charge&lt;/a&gt; numbers if you want to read more.&lt;/p&gt;
&lt;p&gt;The current committed bytes and current commit limit are both available as memory performance counters and can be accessed using the WMI class &lt;span class="code"&gt;Win32_PerfFormattedData_PerfOS_Memory&lt;/span&gt;&lt;sup&gt;[1]&lt;/sup&gt; as &lt;span class="code"&gt;CommitLimit&lt;/span&gt; and &lt;span class="code"&gt;CommittedBytes&lt;/span&gt;. Unfortunately, Microsoft has not provided a performance counter for the peak committed bytes. In fact, the only way I have been able to locate this counter is through the undocumented&lt;sup&gt;[2]&lt;/sup&gt; &lt;span class="code"&gt;NtQuerySystemInformation&lt;/span&gt; function of ntdll.dll. &lt;/p&gt;  &lt;p&gt;Powershell can be used to call unmanaged APIs as described in &lt;a href="http://www.leeholmes.com/blog/PowerShellPInvokeWalkthrough.aspx"&gt;PowerShell P/Invoke Walkthrough&lt;/a&gt; by Lee Holmes. I used the information in Lee's post as well as the examples on &lt;a href="http://www.pinvoke.net"&gt;www.pinvoke.net&lt;/a&gt; and the python solution by Mike Driscoll at &lt;a href="http://www.blog.pythonlibrary.org/2010/03/05/python-finding-the-commit-charge-values-in-windows/"&gt;Python: Finding the Commit Charge Values in Windows&lt;/a&gt; to construct the following Powershell script to query for the committed bytes peak value:&lt;/p&gt;
&lt;!--Start Script--&gt;
&lt;div class='embedded-code-wrapper'&gt;
&lt;TABLE BORDER='0' cellpadding='5' cellspacing='0'&gt; 
&lt;TR&gt; 
    &lt;TD VALIGN='Top'&gt;&lt;div class='line-no-column'&gt;001&lt;BR /&gt;002&lt;BR /&gt;003&lt;BR /&gt;004&lt;BR /&gt;005&lt;BR /&gt;006&lt;BR /&gt;007&lt;BR /&gt;008&lt;BR /&gt;009&lt;BR /&gt;010&lt;BR /&gt;011&lt;BR /&gt;012&lt;BR /&gt;013&lt;BR /&gt;014&lt;BR /&gt;015&lt;BR /&gt;016&lt;BR /&gt;017&lt;BR /&gt;018&lt;BR /&gt;019&lt;BR /&gt;020&lt;BR /&gt;021&lt;BR /&gt;022&lt;BR /&gt;023&lt;BR /&gt;024&lt;BR /&gt;025&lt;BR /&gt;026&lt;BR /&gt;027&lt;BR /&gt;028&lt;BR /&gt;029&lt;BR /&gt;030&lt;BR /&gt;031&lt;BR /&gt;032&lt;BR /&gt;033&lt;BR /&gt;034&lt;BR /&gt;035&lt;BR /&gt;036&lt;BR /&gt;037&lt;BR /&gt;038&lt;BR /&gt;039&lt;BR /&gt;040&lt;BR /&gt;041&lt;BR /&gt;042&lt;BR /&gt;043&lt;BR /&gt;044&lt;BR /&gt;045&lt;BR /&gt;046&lt;BR /&gt;047&lt;BR /&gt;048&lt;BR /&gt;049&lt;BR /&gt;050&lt;BR /&gt;051&lt;BR /&gt;052&lt;BR /&gt;053&lt;BR /&gt;054&lt;BR /&gt;055&lt;BR /&gt;056&lt;BR /&gt;057&lt;BR /&gt;058&lt;BR /&gt;059&lt;BR /&gt;060&lt;BR /&gt;061&lt;BR /&gt;062&lt;BR /&gt;063&lt;BR /&gt;064&lt;BR /&gt;065&lt;BR /&gt;066&lt;BR /&gt;067&lt;BR /&gt;068&lt;BR /&gt;069&lt;BR /&gt;070&lt;BR /&gt;071&lt;BR /&gt;072&lt;BR /&gt;073&lt;BR /&gt;074&lt;BR /&gt;075&lt;BR /&gt;076&lt;BR /&gt;077&lt;BR /&gt;078&lt;BR /&gt;079&lt;BR /&gt;080&lt;BR /&gt;081&lt;BR /&gt;082&lt;BR /&gt;083&lt;BR /&gt;084&lt;BR /&gt;085&lt;BR /&gt;086&lt;BR /&gt;087&lt;BR /&gt;088&lt;BR /&gt;089&lt;BR /&gt;090&lt;BR /&gt;091&lt;BR /&gt;092&lt;BR /&gt;093&lt;BR /&gt;094&lt;BR /&gt;095&lt;BR /&gt;096&lt;BR /&gt;097&lt;BR /&gt;098&lt;BR /&gt;099&lt;BR /&gt;100&lt;BR /&gt;101&lt;BR /&gt;102&lt;BR /&gt;103&lt;BR /&gt;104&lt;BR /&gt;105&lt;BR /&gt;106&lt;BR /&gt;107&lt;BR /&gt;108&lt;BR /&gt;109&lt;BR /&gt;110&lt;BR /&gt;111&lt;BR /&gt;112&lt;BR /&gt;113&lt;BR /&gt;114&lt;BR /&gt;115&lt;BR /&gt;116&lt;BR /&gt;117&lt;BR /&gt;118&lt;BR /&gt;119&lt;BR /&gt;120&lt;BR /&gt;121&lt;BR /&gt;122&lt;BR /&gt;123&lt;BR /&gt;124&lt;BR /&gt;125&lt;BR /&gt;126&lt;BR /&gt;127&lt;BR /&gt;
&lt;/DIV&gt; 
    &lt;/TD&gt; 
    &lt;TD VALIGN='Top' NOWRAP='NOWRAP'&gt;&lt;div class='embedded-code-body'&gt;&lt;span class='psComment'&gt;&amp;lt;# 
.SYNOPSIS 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Returns the PeakCommitment value using NtQuerySystemInformation 

.DESCRIPTION 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Uses p/Invoke to query the undocumented (unsupported) NtQuerySystemInformation 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;function in ntdll.dll. 

.NOTES 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Author : Chris Duck 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Name : Get-CommittedBytesPeak.ps1 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
.LINK 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;http://blog.whatsupduck.net 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
.INPUTS 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;None 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
.OUTPUTS 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;The value of committed bytes peak in bytes. 

.EXAMPLE 
get-committedbytespeak.ps1 

Returns the value for committed bytes peak on the local machine. 
.EXAMPLE 
[string]::format(&amp;quot;{0:#,#}Kb&amp;quot;, (.\get-committedbytespeak.ps1) / 1KB) 

Formats the value for committed bytes peak on the local machine as 8,301,621Kb. 
.EXAMPLE 
Invoke-Command remoteserver -FilePath .\get-committedbytespeak.ps1 

Returns the value for committed bytes peak on a remote machine named &amp;quot;remoteserver&amp;quot;. 
#&amp;gt;&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;
&lt;span class='psVariable'&gt;$sig&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;@&amp;#39; 
[StructLayout(LayoutKind.Sequential)] 
public struct SYSTEM_PERFORMANCE_INFORMATION { 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public Int64 IdleTime; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public Int64 ReadTransferCount; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public Int64 WriteTransferCount; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public Int64 OtherTransferCount; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint ReadOperationCount; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint WriteOperationCount; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint OtherOperationCount; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint AvailablePages; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint TotalCommittedPages; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint TotalCommitLimit; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint PeakCommitment; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint PageFaults; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint WriteCopyFaults; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint TransitionFaults; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint Reserved1; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint DemandZeroFaults; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint PagesRead; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint PageReadIos; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public ulong Reserved2; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint PagefilePagesWritten; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint PagefilePageWriteIos; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint MappedFilePagesWritten; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint MappedFilePageWriteIos; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint PagedPoolUsage; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint NonPagedPoolUsage; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint PagedPoolAllocs; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint PagedPoolFrees; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint NonPagedPoolAllocs; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint NonPagedPoolFrees; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint TotalFreeSystemPtes; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint SystemCodePage; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint TotalSystemDriverPages; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint TotalSystemCodePages; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint SmallNonPagedLookasideListAllocateHits; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint SmallPagedLookasideListAllocateHits; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint Reserved3; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint MmSystemCachePage; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint PagedPoolPage; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint SystemDriverPage; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint FastReadNoWait; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint FastReadWait; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint FastReadResourceMiss; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint FastReadNotPossible; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint FastMdlReadNoWait; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint FastMdlReadWait; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint FastMdlReadResourceMiss; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint FastMdlReadNotPossible; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint MapDataNoWait; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint MapDataWait; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint MapDataNoWaitMiss; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint MapDataWaitMiss; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint PinMappedDataCount; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint PinReadNoWait; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint PinReadWait; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint PinReadNoWaitMiss; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint PinReadWaitMiss; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint CopyReadNoWait; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint CopyReadWait; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint CopyReadNoWaitMiss; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint CopyReadWaitMiss; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint MdlReadNoWait; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint MdlReadWait; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint MdlReadNoWaitMiss; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint MdlReadWaitMiss; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint ReadAheadIos; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint LazyWriteIos; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint LazyWritePages; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint DataFlushes; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint DataPages; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint ContextSwitches; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint FirstLevelTbFills; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint SecondLevelTbFills; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public uint SystemCalls; 
} 

[DllImport(&amp;quot;ntdll.dll&amp;quot;)] 
public static extern int NtQuerySystemInformation( 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uint SYSTEM_INFORMATION_CLASS, 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ref SYSTEM_PERFORMANCE_INFORMATION returnStruct, 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uint length, 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ref uint returnLength); 
&amp;#39;@&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;

&lt;span class='psCommand'&gt;Add-Type&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandParameter'&gt;-MemberDefinition&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$sig&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandParameter'&gt;-Name&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandArgument'&gt;NTDLL&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandParameter'&gt;-Namespace&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandArgument'&gt;Win32&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;&amp;gt;&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$null&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;

&lt;span class='psVariable'&gt;$out&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;New-Object&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandArgument'&gt;Win32.NTDLL+SYSTEM_PERFORMANCE_INFORMATION&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;
&lt;span class='psVariable'&gt;$outlen&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;New-Object&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandArgument'&gt;int&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;

&lt;span class='psType'&gt;[Win32.NTDLL]&lt;/span&gt;&lt;span class='psOperator'&gt;::&lt;/span&gt;&lt;span class='psMember'&gt;NtQuerySystemInformation&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psNumber'&gt;2&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psType'&gt;[ref]&lt;/span&gt;&lt;span class='psVariable'&gt;$out&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psType'&gt;[System.Runtime.InteropServices.Marshal]&lt;/span&gt;&lt;span class='psOperator'&gt;::&lt;/span&gt;&lt;span class='psMember'&gt;SizeOf&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;$out&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psType'&gt;[ref]&lt;/span&gt;&lt;span class='psVariable'&gt;$outlen&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;&amp;gt;&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$null&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;
&lt;span class='psKeyword'&gt;return&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$out&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;PeakCommitment&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;*&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psNumber'&gt;4096&lt;/span&gt; 
&lt;/DIV&gt; 
    &lt;/TD&gt; 
&lt;/TR&gt; 
&lt;/TBODY&gt; 
&lt;/TABLE&gt; 
&lt;/DIV&gt;
&lt;!--End Script--&gt;
&lt;p&gt;As shown in the examples included in the script, this can be used with &lt;span class="code"&gt;Invoke-Command&lt;/span&gt; to run on remote servers.&amp;#160; It could even be combined with &lt;span class="code"&gt;Win32_OperatingSystem.TotalVisibleMemorySize&lt;/span&gt;&lt;sup&gt;[3]&lt;/sup&gt; to determine if a server has enough (or too much) memory allocated to it.&amp;#160; Just remember that the counter starts over every time the server is rebooted, so make sure there has been plenty of time since the last reboot when you are reading this number or it may not be an accurate reflection of all of the server's workloads.&lt;/p&gt;  &lt;p&gt;[1] &lt;a href="http://msdn.microsoft.com/en-us/library/aa394268(VS.85).aspx" name="ref1"&gt;Win32_PerfFormattedData_PerfOS_Memory&lt;/a&gt; on MSDN     &lt;br /&gt;[2] &lt;a href="http://msdn.microsoft.com/en-us/library/ms724509(VS.85).aspx" name="ref2"&gt;NtQuerySystemInformation&lt;/a&gt; on MSDN     &lt;br /&gt;[3] &lt;a href="http://msdn.microsoft.com/en-us/library/aa394239(VS.85).aspx" name="ref3"&gt;Win32_OperatingSystem&lt;/a&gt; on MSDN&lt;/p&gt;  &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=Q_wykqDxgQU:NWBmPAqLr9k:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=Q_wykqDxgQU:NWBmPAqLr9k:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=Q_wykqDxgQU:NWBmPAqLr9k:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=Q_wykqDxgQU:NWBmPAqLr9k:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=Q_wykqDxgQU:NWBmPAqLr9k:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=Q_wykqDxgQU:NWBmPAqLr9k:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=Q_wykqDxgQU:NWBmPAqLr9k:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=Q_wykqDxgQU:NWBmPAqLr9k:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatsUpDuckBlog/~4/Q_wykqDxgQU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.whatsupduck.net/feeds/5307603708782569157/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.whatsupduck.net/2010/05/querying-peak-commit-bytes-with.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/5307603708782569157?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/5307603708782569157?v=2" /><link rel="alternate" type="text/html" href="http://blog.whatsupduck.net/2010/05/querying-peak-commit-bytes-with.html" title="Querying Peak Commit Bytes with Powershell (via NtQuerySystemInformation)" /><author><name>Chris Duck</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;C0cEQ3Y-eCp7ImA9WxFRGU4.&quot;"><id>tag:blogger.com,1999:blog-7728225756528319729.post-1825709138453203572</id><published>2010-05-02T03:36:00.010-05:00</published><updated>2010-05-03T18:56:42.850-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-03T18:56:42.850-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="powershell" /><category scheme="http://www.blogger.com/atom/ns#" term="msbuild" /><category scheme="http://www.blogger.com/atom/ns#" term="source control" /><title>Using MSBuild to Maintain Powershell Modules</title><content type="html">&lt;h3&gt;The Problem&lt;/h3&gt;

&lt;p&gt;
One of the challenges faced when developing scripts that will be used from other scripts is keeping the library script updated. &amp;nbsp;Frequently the file is copied from the folder it was developed in to the folders containing the scripts that depend on it. &amp;nbsp;This is a good way to make sure that the dependency follows the main script if it is moved, but creates multiple copies of the library script that are unlikely to be updated if a bug is fixed or an improvement made.
&lt;/p&gt;

&lt;h3&gt;The Goal&lt;/h3&gt;

&lt;p&gt;
Ideally, there would be a way to link the library script to the dependent scripts, without actually having to keep a copy of it in the folder. &amp;nbsp;This would allow a single place to update all of the scripts and still maintain the dependencies with the main scripts.
&lt;/p&gt;

&lt;h3&gt;The Solution - MSBuild&lt;/h3&gt;

&lt;p&gt;
This solution will establish a workspace where all development of scripts occurs and then use MSBuild (included in the .NET framework) to deploy the scripts to a release folder. &amp;nbsp;The build process will copy all of the dependencies of the scripts into their local folders so the folder can then be moved to another computer and all of the dependencies will be packaged together.
&lt;/p&gt;

&lt;p&gt;
This also works well if there is a source control system maintaining the master copy of all the scripts. &amp;nbsp;The workspace can be set as the base folder for the source control system and then only a single copy of each file is included in source control.
&lt;/p&gt;

&lt;h3&gt;Environment and Directory Layout&lt;/h3&gt;

&lt;p&gt;
The easiest way to run a build is to add &lt;span class="code"&gt;msbuild.exe&lt;/span&gt; to the PATH environment variable and call it from a folder containing a &lt;span class="code"&gt;.proj&lt;/span&gt; file. &amp;nbsp;This will invoke the default target in the &lt;span class="code"&gt;.proj&lt;/span&gt; file and doesn't require any parameters to be passed to msbuild. &amp;nbsp;Msbuild.exe is included in the v2.0.50727 and v3.5 framework folders, usually located at&amp;nbsp;&lt;span class="code"&gt;C:\windows\Microsoft.NET\Framework&lt;/span&gt;. &amp;nbsp;Here is a batch file that can be run easily from explorer to run a build in its current folder:
&lt;/p&gt;

&lt;blockquote&gt;
&lt;span class="code"&gt;@echo off&lt;/span&gt;&lt;br /&gt;
&lt;span class="code"&gt;set path=%path%;c:\windows\Microsoft.Net\Framework\v3.5;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span class="code"&gt;msbuild&lt;/span&gt;
&lt;br /&gt;
&lt;span class="code"&gt;pause&lt;/span&gt;&lt;/blockquote&gt;

&lt;p&gt;
Here is some powershell that will locate the path for .NET 3.5 for you:
&lt;/p&gt;

&lt;blockquote&gt;
&lt;span class="code"&gt;get-itemproperty "HKLM:\Software\Microsoft\NET Framework Setup\NDP\v3.5").InstallPath&lt;/span&gt;&lt;/blockquote&gt;

&lt;p&gt;
The variable &lt;span class="code"&gt;$ws&lt;/span&gt; will be used to represent the workspace throughout this post. &amp;nbsp;This is where the master copy of the scripts are kept (if using a source control system, this would be where files are checked out to). &amp;nbsp;As an example, it could be set as follows:
&lt;/p&gt;

&lt;blockquote&gt;
&lt;span class="code"&gt;$ws &amp;nbsp;= c:\users\cduck\documents\scripts&lt;/span&gt;
&lt;/blockquote&gt;

&lt;p&gt;
The following folder structure is used within the workspace:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;span class="code"&gt;&lt;b&gt;$ws\Release&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
This will be the default output folder and is excluded from source control. &amp;nbsp;This folder is designed to be copied to c:\scripts and to have &lt;span class="code"&gt;c:\scripts\modules&lt;/span&gt; added to your &lt;span class="code"&gt;$env:PSModulePath&lt;/span&gt;. It will be automatically created by the MSBuild target.&lt;/li&gt;
&lt;li&gt;&lt;span class="code"&gt;&lt;b&gt;$ws\ThirdPartyLibs&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
This is for 3rd party libraries, like binaries or .NET assemblies and is under source control. &amp;nbsp;There will be a separate folder under here for each library that will be linked to from scripts and modules.&lt;/li&gt;
&lt;li&gt;&lt;span class="code"&gt;&lt;b&gt;$ws\src&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
This is where working copies of scripts and modules are saved and is under source control.&lt;/li&gt;
&lt;li&gt;&lt;span class="code"&gt;&lt;b&gt;$ws\src\Modules&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
Each module gets a new folder under &lt;span class="code"&gt;$ws\src\Modules\&lt;modulename&gt;&lt;/modulename&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="code"&gt;&lt;b&gt;$ws\src\Scripts&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
Single scripts can go in this root, or collections of scripts can be put in sub-folders here.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Configure the Main MSBuild Project File&lt;sup&gt;[5]&lt;/sup&gt;&lt;/h3&gt;

&lt;p&gt;
The main build process is controlled by a MSBuild project file in the workspace root,&amp;nbsp;&lt;span class="code"&gt;$ws\msbuild.proj&lt;/span&gt;. &amp;nbsp;This file is configured to&amp;nbsp;search the&amp;nbsp;&lt;span class="code"&gt;$ws\src\Modules\*&lt;/span&gt;&amp;nbsp;folders and &lt;span class="code"&gt;$ws\src\Scripts\*&lt;/span&gt; folders for any&amp;nbsp;&lt;span class="code"&gt;msbuild.proj&lt;/span&gt;&amp;nbsp;files (recursing only one folder deep) and run the default target for each of those files. &amp;nbsp;It also overrides the&amp;nbsp;&lt;span class="code"&gt;OutputDirectory&lt;/span&gt;&amp;nbsp;property of each of these build files to force the build output to &lt;span class="code"&gt;$ws\Release\Modules&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&amp;nbsp;for modules or&amp;nbsp;&lt;/span&gt;$ws\&lt;/span&gt; for scripts.
&lt;/p&gt;

&lt;p&gt;
The contents of &lt;span class="code"&gt;$ws\msbuild.proj&lt;/span&gt;&amp;nbsp;&lt;sup&gt;[2][3][4]&lt;/sup&gt; are:
&lt;/p&gt;

&lt;blockquote&gt;
&lt;span class="code"&gt;&amp;lt;Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"&amp;gt;&lt;/span&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;&amp;lt;OutputDirectory&amp;gt;$(MSBuildProjectDirectory)\Release&amp;lt;/OutputDirectory&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;&amp;lt;ModuleOutputDirectory&amp;gt;$(OutputDirectory)\Modules&amp;lt;/ModuleOutputDirectory&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;&amp;lt;ScriptOutputDirectory&amp;gt;$(OutputDirectory)&amp;lt;/ScriptOutputDirectory&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;span class="code"&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;&amp;lt;ItemGroup&amp;gt;&lt;/span&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;&amp;lt;ModuleBuilds Include="src\Modules\*\msbuild.proj" /&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;&amp;lt;ScriptBuilds Include="src\Scripts\*\msbuild.proj" /&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;&amp;lt;ScriptFiles Include="src\Scripts\**\*.*" /&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;span class="code"&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;&amp;lt;Target Name="ModuleBuild"&amp;gt;&lt;/span&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;&amp;lt;MSBuild&lt;/span&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;Projects="@(ModuleBuilds)"&lt;/span&gt;&lt;/div&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;Properties="OutputDirectory=$(ModuleOutputDirectory)"&lt;/span&gt;&lt;/div&gt;
&lt;span class="code"&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;span class="code"&gt;&amp;lt;/Target&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;&amp;lt;Target Name="ScriptBuild"&amp;gt;&lt;/span&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;&amp;lt;Copy&lt;/span&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;SourceFiles="@(ScriptFiles)"&lt;/span&gt;&lt;/div&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;DestinationFiles="@(ScriptFiles-&amp;gt;'$(ScriptOutputDirectory)\%(RecursiveDir)%(Filename)%(Extension)')"&lt;/span&gt;&lt;/div&gt;
&lt;span class="code"&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;&amp;lt;MSBuild&lt;/span&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;Projects="@(ScriptBuilds)"&lt;/span&gt;&lt;/div&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;Properties="OutputDirectory=$(ScriptOutputDirectory)\%(RecursiveDir)"&lt;/span&gt;&lt;/div&gt;
/&amp;gt;&lt;/div&gt;
&lt;span class="code"&gt;&amp;lt;/Target&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;&amp;lt;Target Name="Build"&amp;gt;&lt;/span&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;&amp;lt;CallTarget Targets="ModuleBuild;ScriptBuild" /&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;span class="code"&gt;&amp;lt;/Target&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;&amp;lt;Target Name="Clean"&amp;gt;&lt;/span&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;&amp;lt;RemoveDir&lt;/span&gt;
&lt;div class="tab"&gt;
&lt;span class="code"&gt;Directories="$(OutputDirectory)"&lt;/span&gt;&lt;/div&gt;
&lt;span class="code"&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;span class="code"&gt;&amp;lt;/Target&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;span class="code"&gt;&amp;lt;/Project&amp;gt;&lt;/span&gt;&lt;/blockquote&gt;

&lt;p&gt;
This file can be invoked by calling &lt;span class="code"&gt;msbuild.exe&lt;/span&gt;&lt;sup&gt;[1]&lt;/sup&gt; with your current directory set to your workspace (&lt;span class="code"&gt;$ws)&lt;/span&gt;, or by creating a file&amp;nbsp;&lt;span class="code"&gt;$ws\build.cmd&lt;/span&gt;&amp;nbsp;with the contents from above in it and double clicking on it.
&lt;/p&gt;

&lt;p&gt;
This build file defines a base output directory as&amp;nbsp;"a folder called 'Release' that is a sub-folder of the parent folder of the build file" and saves it&amp;nbsp;in the &lt;span class="code"&gt;OutputDirectory&lt;/span&gt;&amp;nbsp;parameter. &amp;nbsp;This can be overridden on the command line using &lt;span class="code"&gt;msbuild.exe /p:OutputDirectory=c:\scripts&lt;/span&gt;. &amp;nbsp;It also defines the parameters 'ModuleOutputDirectory' as a 'Modules' sub-folder of the main output directory&amp;nbsp;and 'ScriptOutputDirectory' as the same folder as the main output directory.
&lt;/p&gt;

&lt;p&gt;This source folder structure:&lt;/p&gt;

&lt;blockquote&gt;
&lt;span class="code"&gt;$ws\src\Scripts\script1.ps1&lt;/span&gt;&lt;br /&gt;
&lt;span class="code"&gt;$ws\src\Scripts\Nested\nestedScript1.ps1&lt;/span&gt;&lt;br /&gt;
&lt;span class="code"&gt;$ws\src\Modules\Module1\Module1.psm1&lt;/span&gt;
&lt;/blockquote&gt;

&lt;p&gt;Will be output as follows:&lt;/p&gt;
&lt;blockquote&gt;
&lt;span class="code"&gt;$ws\Release\script1.ps1&lt;/span&gt;&lt;br /&gt;
&lt;span class="code"&gt;$ws\Release\Nested\nestedScript1.ps1&lt;/span&gt;&lt;br /&gt;
&lt;span class="code"&gt;$ws\Release\Modules\Module1\Module1.psm1&lt;/span&gt;
&lt;/blockquote&gt;
&lt;p&gt;
As you can see, this allows the contents of &lt;span class="code"&gt;$ws\Release&lt;/span&gt; to be directly copied to &lt;span class="code"&gt;c:\scripts&lt;/span&gt;, or you can use the command line parameter above to set the output to &lt;span class="code"&gt;c:\scripts&lt;/span&gt; directly.
&lt;/p&gt;

&lt;h3&gt;Including a Custom MSBuild Project for a Module or Script Folder&lt;/h3&gt;

&lt;p&gt;
The whole point of this exercise is to allow a script or third party assembly/executable to be included in a module or script folder without having to create multiple copies of it in the source control system, but so far all we have is a way to recreate the directory structure of the&amp;nbsp;&lt;span class="code"&gt;$ws\src\scripts&lt;/span&gt; folder. &amp;nbsp;The magic of using MSBuild to accomplish this is in chaining project definitions contained in each module or script sub-folder to the main build definition.
&lt;/p&gt;

&lt;p&gt;
To add &lt;span class="code"&gt;pscp.exe&lt;/span&gt; from&amp;nbsp;&lt;span class="code"&gt;$ws\ThirdPartyLibs\PuTTY&lt;/span&gt; to the scripts contained in &lt;span class="code"&gt;$ws\src\Scripts\Linux&lt;/span&gt;, create the following&amp;nbsp;&lt;span class="code"&gt;msbuild.proj&lt;/span&gt;&amp;nbsp;in &lt;span class="code"&gt;$ws\src\Scripts\Linux&lt;/span&gt;:
&lt;/p&gt;

&lt;blockquote&gt;
&amp;lt;Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"&amp;gt;
&lt;div class="tab"&gt;
&amp;lt;ItemGroup&amp;gt;
&lt;div class="tab"&gt;
&amp;lt;tplibs Include="..\..\..\ThirdPartyLibs\PuTTY\pscp.exe" /&amp;gt;&lt;/div&gt;
&amp;lt;/ItemGroup&amp;gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="tab"&gt;
&amp;lt;Target Name="Build"&amp;gt;
&lt;div class="tab"&gt;
&amp;lt;Copy
&lt;div class="tab"&gt;
SourceFiles="@(tplibs)"&lt;/div&gt;
&lt;div class="tab"&gt;
DestinationFolder="$(OutputDirectory)"&lt;/div&gt;
/&amp;gt;&lt;/div&gt;
&amp;lt;/Target&amp;gt;&lt;/div&gt;
&amp;lt;/Project&amp;gt;&lt;/blockquote&gt;

&lt;p&gt;
Since the entire contents of &lt;span class="code"&gt;$ws\src\Scripts&lt;/span&gt;&amp;nbsp;will be copied to the output folder by the main &lt;span class="code"&gt;msbuild.proj&lt;/span&gt; file (&lt;span class="code"&gt;$ws\msbuild.proj&lt;/span&gt;), all that is needed in the &lt;span class="code"&gt;$ws\src\Scripts\Linux\msbuild.proj&lt;/span&gt; file is any dependency that needs to be added from outside of this folder. &amp;nbsp;This could even include scripts from other folders if you have some utility scripts that are used by other scripts. &amp;nbsp;If there are no outside dependencies, a &lt;span class="code"&gt;msbuild.proj&lt;/span&gt; file does not need to be created.
&lt;/p&gt;

&lt;p&gt;
Here is another example that copies &lt;span class="code"&gt;$ws\src\Scripts\new-share.ps1&lt;/span&gt; and &lt;span class="code"&gt;$ws\src\Scripts\DNS\set-cname.ps1&lt;/span&gt; to &lt;span class="code"&gt;$ws\src\Scripts\IIS&lt;/span&gt; so that a script located there (maybe &lt;span class="code"&gt;new-iissite.ps1&lt;/span&gt;) can use them to create a share and add a new CNAME record to DNS for the site:
&lt;/p&gt;

&lt;blockquote&gt;
&amp;lt;Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"&amp;gt;
&lt;div class="tab"&gt;
&amp;lt;ItemGroup&amp;gt;
&lt;div class="tab"&gt;
&amp;lt;tplibs Include="..\new-share.ps1;..\DNS\set-cname.ps1" /&amp;gt;&lt;/div&gt;
&amp;lt;/ItemGroup&amp;gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="tab"&gt;
&amp;lt;Target Name="Build"&amp;gt;
&lt;div class="tab"&gt;
&amp;lt;Copy
&lt;div class="tab"&gt;
SourceFiles="@(tplibs)"&lt;/div&gt;
&lt;div class="tab"&gt;
DestinationFolder="$(OutputDirectory)"&lt;/div&gt;
/&amp;gt;&lt;/div&gt;
&amp;lt;/Target&amp;gt;&lt;/div&gt;
&amp;lt;/Project&amp;gt;&lt;/blockquote&gt;

&lt;p&gt;
Now there is only one copy of &lt;span class="code"&gt;new-share.ps1&lt;/span&gt; and &lt;span class="code"&gt;set-cname.ps1&lt;/span&gt; in the source control system, but they are copied to the &lt;span class="code"&gt;IIS&lt;/span&gt;&amp;nbsp;folder to fulfill dependencies for the &lt;span class="code"&gt;new-iissite.ps1&lt;/span&gt; file in that folder.
&lt;/p&gt;

&lt;p&gt;
Modules will use a similar technique, but the msbuild.proj files have been crafted slightly differently to allow a module to be built independently. &amp;nbsp;The script version of the msbuild.proj file could be modified to work like modules or vice-versa if so desired.
&lt;/p&gt;

&lt;p&gt;
Here is the contents of &lt;span class="code"&gt;$ws\src\Modules\Linux\msbuild.proj&lt;/span&gt; that will be used to copy the module and add &lt;span class="code"&gt;$ws\ThirdPartyLibs\PuTTY\pscp.exe&lt;/span&gt; to this module:
&lt;/p&gt;

&lt;blockquote&gt;
&amp;lt;Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"&amp;gt;
&lt;div class="tab"&gt;
&amp;lt;PropertyGroup&amp;gt;
&lt;div class="tab"&gt;
&amp;lt;ModuleName&amp;gt;Linux&amp;lt;/ModuleName&amp;gt;&lt;/div&gt;
&lt;div class="tab"&gt;
&amp;lt;OutputDirectory&amp;gt;..\..\..\Release\Modules&amp;lt;/OutputDirectory&amp;gt;&lt;/div&gt;
&amp;lt;/PropertyGroup&amp;gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="tab"&gt;
&amp;lt;ItemGroup&amp;gt;
&lt;div class="tab"&gt;
&amp;lt;tplibs Include="..\..\..\ThirdPartyLibraries\PuTTY\pscp.exe" /&amp;gt;&lt;/div&gt;
&lt;div class="tab"&gt;
&amp;lt;ModuleFiles Include="**\*.*" Exclude="**\msbuild.proj" /&amp;gt;&lt;/div&gt;
&amp;lt;/ItemGroup&amp;gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="tab"&gt;
&amp;lt;Target Name="Build"&amp;gt;
&lt;div class="tab"&gt;
&amp;lt;Copy
&lt;div class="tab"&gt;
SourceFiles="@(tplibs)"&lt;/div&gt;
&lt;div class="tab"&gt;
DestinationFolder="$(OutputDirectory)\$(ModuleName)"&lt;/div&gt;
/&amp;gt;&lt;/div&gt;
&lt;div class="tab"&gt;
&amp;lt;Copy
&lt;div class="tab"&gt;
SourceFiles="@(ModuleFiles)"&lt;/div&gt;
&lt;div class="tab"&gt;
DestinationFolder="$(ModuleFiles-&amp;gt;'$(OutputDirectory)\$(ModuleName)\%(RecursiveDir)%(Filename)%(Extension)')"&lt;/div&gt;
/&amp;gt;&lt;/div&gt;
&amp;lt;/Target&amp;gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="tab"&gt;
&amp;lt;Target Name="Clean"&amp;gt;
&lt;div class="tab"&gt;
&amp;lt;RemoveDir
&lt;div class="tab"&gt;
Directories="$(OutputDirectory)\$(ModuleName)"&lt;/div&gt;
/&amp;gt;&lt;/div&gt;
&amp;lt;/Target&amp;gt;&lt;/div&gt;
&amp;lt;/Project&amp;gt;&lt;/blockquote&gt;

&lt;p&gt;
Placing the recursive file copy task in the module's &lt;span class="code"&gt;msbuild.proj&lt;/span&gt; file and including a default &lt;span class="code"&gt;OutputDirectory&lt;/span&gt; property allows the module to be built alone. &amp;nbsp;The &lt;span class="code"&gt;msbuild.proj&lt;/span&gt; file that was used in a script folder above only copied dependencies. &amp;nbsp;The module version could be used in a script folder, allowing that script folder to be built on its own, but then the full build process would be doing double file copies.
&lt;/p&gt;

&lt;h3&gt;Summary&lt;/h3&gt;

&lt;p&gt;
This post shows two examples of how to configure a&amp;nbsp;simple&amp;nbsp;MSBuild project to enable a single master copy of scripts to be maintained and then meshed together to build folders with local copies of any dependencies for each script. &amp;nbsp;MSBuild is a very robust build system and these examples can be extended to do much more.
&lt;/p&gt;

&lt;sup&gt;[1]&lt;/sup&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/ms164311.aspx"&gt;MSBuild Command Line Reference&lt;/a&gt;&lt;br /&gt;
&lt;sup&gt;[2]&lt;/sup&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/5dy88c2e(VS.90).aspx"&gt;MSBuild Project File Schema Reference&lt;/a&gt;&lt;br /&gt;
&lt;sup&gt;[3]&lt;/sup&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/7z253716(VS.90).aspx"&gt;MSBuild Task Reference&lt;/a&gt;&lt;br /&gt;
&lt;sup&gt;[4]&lt;/sup&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/ms164309(VS.90).aspx"&gt;MSBuild Reserved Properties Reference&lt;/a&gt;&lt;br /&gt;
&lt;sup&gt;[5]&lt;/sup&gt; &lt;a href="http://brennan.offwhite.net/blog/2006/11/29/msbuild-basics-1of7/"&gt;MSBuild: Basics Tutorial&lt;/a&gt;&amp;nbsp;by Brennan Stehling&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=RKIcGtbDSMY:o9mbY25FeXM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=RKIcGtbDSMY:o9mbY25FeXM:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=RKIcGtbDSMY:o9mbY25FeXM:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=RKIcGtbDSMY:o9mbY25FeXM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=RKIcGtbDSMY:o9mbY25FeXM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=RKIcGtbDSMY:o9mbY25FeXM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=RKIcGtbDSMY:o9mbY25FeXM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=RKIcGtbDSMY:o9mbY25FeXM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatsUpDuckBlog/~4/RKIcGtbDSMY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.whatsupduck.net/feeds/1825709138453203572/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.whatsupduck.net/2010/05/using-msbuild-to-maintain-powershell.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/1825709138453203572?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/1825709138453203572?v=2" /><link rel="alternate" type="text/html" href="http://blog.whatsupduck.net/2010/05/using-msbuild-to-maintain-powershell.html" title="Using MSBuild to Maintain Powershell Modules" /><author><name>Chris Duck</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;CkIARXs-fCp7ImA9WxFQF0w.&quot;"><id>tag:blogger.com,1999:blog-7728225756528319729.post-5366077070169677166</id><published>2010-04-23T00:17:00.010-05:00</published><updated>2010-05-12T19:29:04.554-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-12T19:29:04.554-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ie" /><category scheme="http://www.blogger.com/atom/ns#" term="kerberos" /><category scheme="http://www.blogger.com/atom/ns#" term="impersonation" /><category scheme="http://www.blogger.com/atom/ns#" term="delegation" /><category scheme="http://www.blogger.com/atom/ns#" term="authentication" /><category scheme="http://www.blogger.com/atom/ns#" term="iis" /><title>Kerberos Authentication in IIS and IE</title><content type="html">&lt;h3&gt;What is Kerberos&lt;/h3&gt;&lt;br /&gt;
Kerberos authentication is very useful when you need to impersonate the end user's credentials to access another system.  This is also known as a double-hop authentication.  The alternative to implementing Kerberos on the initial request is to enable constrained delegation with protocol transition.  This will enable the client (IE) to fall back to NTLM authentication to the server (IIS) and then the server will transition the authentication token to Kerberos to pass along to the back end systems (SQL, SSRS, web services, cifs, etc).  Constrained delegation can be hard to implement and maintain as you have to approve each allowed back end service the front end server is allowed to delegate to, but this is also more secure as your credentials cannot be delegated to any random service on the network.&lt;br /&gt;
&lt;br /&gt;
This post is going to cover the basics of getting Kerberos working and the speed bumps I have encountered in my implementations at work.  If you want to learn the details behind what is going on, I recommend you read the series posted by Ken Shaefer on his blog, starting with &lt;a href="http://www.adopenstatic.com/cs/blogs/ken/archive/2006/10/19/512.aspx"&gt;&lt;em&gt;What is Kerberos and how does it work?&lt;/em&gt;&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Configuring Kerbros on IIS&lt;/h3&gt;&lt;br /&gt;
Initially, you need to determine two pieces of information to successfully implement Kerberos:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;What is the URL my service will be exposed at?&lt;br /&gt;
For example: &lt;span class="code"&gt;http://www.example.com&lt;/span&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;What is the account the service will be running as?&lt;br /&gt;
For example: &lt;span class="code"&gt;corp.example.com\wwwPool&lt;/span&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
&lt;h3&gt;Determining the SPN&lt;/h3&gt;&lt;br /&gt;
The URL will be used to construct the &lt;a href="http://www.adopenstatic.com/cs/blogs/ken/archive/2006/11/19/606.aspx"&gt;Service Principal Name (SPN)&lt;/a&gt; for your service.  This will be used by the KDC (a Domain Controller in AD) to locate the service account that is running your site.  In my example above, IE will generate an SPN like this:&lt;br /&gt;
&lt;blockquote&gt;&lt;span class="code"&gt;HTTP/www.example.com&lt;/span&gt;&lt;/blockquote&gt;Some things to watch out for here are:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;If your page is hosted on a non-standard port (not 80 or 443), out of the box IE will ignore the port when generating the SPN.  This means you cannot have 2 websites running on the same DNS name and different application pool identities, unless you implement &lt;a href="http://support.microsoft.com/default.aspx?scid=kb;EN-US;908209"&gt;KB 908209&lt;/a&gt; on all of your IE clients who will be accessing your site.  If you are running IE6, you have to make sure your version includes the hotfix listed in the KB before it will read the registry keys.  All later versions already include the hotfix, but you still have to apply the registry key changes listed in the KB as the default behavior is still to ignore the port.  I do not have any information on how other browsers construct their SPNs.&lt;/li&gt;
&lt;li&gt;You cannot use a CNAME record for your DNS entry without applying the registry changes in &lt;a href="http://support.microsoft.com/default.aspx?scid=kb;EN-US;911149"&gt;KB 911149&lt;/a&gt; (IE6 also requires the hotfix, newer versions already have the patch included).  This is because IE will use the A Name that the CNAME is pointing to when it constructs the SPN.  You can see this in action by disabling IWA and browsing to the site.  On the credential prompt you will see the server listed as the A Name instead of the correct CNAME record.  You can either apply this KB or use an A Name record to work around this issue.&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;h3&gt;Assigning the SPN to the Correct Account&lt;/h3&gt;&lt;br /&gt;
The next piece of the puzzle is the account you are running the site as.  Kerberos is designed to ensure the identity of the user to the server AND the server to the user.  This requires an administrator to link the service (site) to the account that is supposed to be running that service, which is done by setting an SPN on the application pool identity account.  The SPN needs to match the one IE will generate exactly so the correct account can be located in AD.&lt;br /&gt;
&lt;br /&gt;
If you are running this site on multiple servers (ie behind a load balancer or using round-robin DNS), you have to setup a domain service account because the two-way authentication requires the service (your site) maps to a single service account, not to two different machine accounts.&lt;br /&gt;
Since I used a domain account in my example above, I would use the following command to create my SPN &lt;sup&gt;[1]&lt;/sup&gt;:&lt;br /&gt;
&lt;blockquote&gt;&lt;span class="code"&gt;setspn.exe&amp;nbsp;-s&amp;nbsp;HTTP/www.example.com&amp;nbsp;corp.example.com\wwwPool&lt;/span&gt;&lt;/blockquote&gt;If you have applied KB 908209 and are running your site on a non-standard port, you would use:&lt;br /&gt;
&lt;blockquote&gt;&lt;span class="code"&gt;setspn.exe&amp;nbsp;-s&amp;nbsp;HTTP/www.example.com:8080&amp;nbsp;corp.example.com\wwwPool&lt;/span&gt;&lt;/blockquote&gt;When setting an SPN, you need to make sure you have not created a duplicate, as this leaves the KDC (DC in AD) unable to locate the correct account to encrypt the tokens for and will cause kerberos authentication to fail.  Newer versions of setspn.exe have the -s and -x switches to help you locate duplicate SPNs.  You may also need to do a forest wide search using the -f parameter.&lt;br /&gt;
&lt;br /&gt;
If your site is running on the same DNS name as your server AND your site is running as Network Service, you do not need to create an SPN as the KDC will fail back to the host SPN for the computer (ie &lt;span class="code"&gt;HOST/wfe1.corp.example.com&lt;/span&gt;), which is automatically set on the machine account when it joins the domain.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Configuring IIS/Asp.NET/IE&lt;/h3&gt;&lt;br /&gt;
The last step is to make sure the site has "Integrated Windows Authentication"&lt;sup&gt;[3]&lt;/sup&gt; enabled and that your IE is showing "Local Intranet" for your zone and that "Automatic Login" is enabled for the zone.  An important note to consider in IIS7+ is that when you enable "Integrated Windows Authentication", you also need to determine if you need to leave kernel mode authentication enabled.  By default, IWA in IIS7 assumes your site will be running under the &lt;em&gt;Network Service&lt;/em&gt; account which would require your SPN to be set on the machine account.  If you set an SPN on a domain account, you will need to click the "Advanced Settings" link and un-check (disable) kernel mode authentication&lt;sup&gt;[3]&lt;/sup&gt; on your site.  This will cause the Kerberos tokens to be processed by the application pool account instead of the machine account.&lt;br /&gt;
&lt;br /&gt;
At this point you should be able to authenticate to your web server using Kerberos.  You can verify that you are using Kerberos by checking your security log and look for event 4624 with the "Authentication Package" field set to Kerberos.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Delegation&lt;/h3&gt;&lt;br /&gt;
Now that you are successfully authenticating using Kerberos, you may want to pass those credentials on to the next tier of your application.  You'll need to open up Users and Computers and locate the service account.  This is the account that you set the SPN on, in my example above it would be the &lt;span class="code"&gt;corp.example.com\wwwPool&lt;/span&gt; account.  You should now have a "Delegation" tab available (this tab only shows up when an SPN is set on an account).  You will need to enable one of the "Trust this user for delegation" settings, you can read about &lt;a href="http://www.adopenstatic.com/cs/blogs/ken/archive/2007/01/28/1282.aspx"&gt;Simple Delegation&lt;/a&gt; and &lt;a href="http://www.adopenstatic.com/cs/blogs/ken/archive/2007/07/19/8460.aspx"&gt;Constrained Delegation&lt;/a&gt; at Ken's blog, but the easiest setting to make here would be to enable delegation to any service.  This will allow your site to delegate a user's credentials to any other service running in environment.  If you want to restrict where the delegated credentials can go, you will want to read about constrained delegation.&lt;br /&gt;
&lt;br /&gt;
The final setting you need to make to enable delegation is in your application.  You can either set the entire web application to run using the end user's credentials via the "ASP.Net Impersonation" setting in the "Authentication" module of IIS manager &lt;sup&gt;[2]&lt;/sup&gt;, or use the instructions in the section titled &lt;em&gt;Impersonate the Authenticating User in Code&lt;/em&gt; in &lt;a href="http://support.microsoft.com/kb/306158/"&gt;KB 306158&lt;/a&gt; to only impersonate the user in specific code sections in your site.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;sup&gt;[1]&lt;/sup&gt; I'm assuming you are using setspn from Vista or newer, if not use "-a" instead of "-s".  The "-s" switch searches for an existing SPN to help prevent duplicates from being set.&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;sup&gt;[2]&lt;/sup&gt; This sets the &amp;lt;identity&amp;gt; tag in your web.config file to enable impersonation.  Full documentation can be found on &lt;a href="http://msdn.microsoft.com/en-us/library/72wdk8cc(VS.71).aspx"&gt;MSDN&lt;/a&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;sup&gt;[3]&lt;/sup&gt; While this setting can be set in the IIS manager, in IIS7+ the default configuration is for this setting to be saved in the application's web.config file.&lt;/span&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=eexH5MBue9c:Xj5YYTsn6BM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=eexH5MBue9c:Xj5YYTsn6BM:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=eexH5MBue9c:Xj5YYTsn6BM:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=eexH5MBue9c:Xj5YYTsn6BM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=eexH5MBue9c:Xj5YYTsn6BM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=eexH5MBue9c:Xj5YYTsn6BM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=eexH5MBue9c:Xj5YYTsn6BM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=eexH5MBue9c:Xj5YYTsn6BM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatsUpDuckBlog/~4/eexH5MBue9c" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.whatsupduck.net/feeds/5366077070169677166/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.whatsupduck.net/2010/04/kerberos-authentication-in-iis-and-ie.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/5366077070169677166?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/5366077070169677166?v=2" /><link rel="alternate" type="text/html" href="http://blog.whatsupduck.net/2010/04/kerberos-authentication-in-iis-and-ie.html" title="Kerberos Authentication in IIS and IE" /><author><name>Chris Duck</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DUYCR3s_fip7ImA9WhBREEw.&quot;"><id>tag:blogger.com,1999:blog-7728225756528319729.post-7659981499074588077</id><published>2009-09-16T21:57:00.006-05:00</published><updated>2013-02-27T20:06:06.546-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-27T20:06:06.546-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="powershell" /><category scheme="http://www.blogger.com/atom/ns#" term="wsman" /><category scheme="http://www.blogger.com/atom/ns#" term="esx" /><category scheme="http://www.blogger.com/atom/ns#" term="vmware" /><title>(Not) Using PowerShell v2 to View WSMan Data From ESX</title><content type="html">&lt;p&gt;Today I was trying to get at my "Health Status" data on my ESX servers though PowerShell using the tutorial posted on the PowerCLI Blog (&lt;a href="http://blogs.vmware.com/vipowershell/2009/03/monitoring-esx-hardware-with-powershell.html"&gt;http://blogs.vmware.com/vipowershell/2009/03/monitoring-esx-hardware-with-powershell.html&lt;/a&gt;), but I kept getting an "Access Denied" message.  I did a little more research into using WSMan in PowerShell and discovered that before V2, there was a way to use a COM object to query WSMan that gave you a little more control over the connection (&lt;a href="http://technet.microsoft.com/en-us/magazine/2007.11.heyscriptingguy.aspx"&gt;http://technet.microsoft.com/en-us/magazine/2007.11.heyscriptingguy.aspx&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Here is a PowerShell script based on the PowerCLI script that uses the COM object from the Scripting Guy article (it assumes you're already connected to your Virtual Center server):&lt;/p&gt;
&lt;!--Start Script--&gt;
&lt;div class='embedded-code-wrapper'&gt;
&lt;TABLE BORDER='0' cellpadding='5' cellspacing='0'&gt; 
&lt;TR&gt; 
    &lt;TD VALIGN='Top'&gt;&lt;div class='line-no-column'&gt;001&lt;BR /&gt;002&lt;BR /&gt;003&lt;BR /&gt;004&lt;BR /&gt;005&lt;BR /&gt;006&lt;BR /&gt;007&lt;BR /&gt;008&lt;BR /&gt;009&lt;BR /&gt;010&lt;BR /&gt;011&lt;BR /&gt;012&lt;BR /&gt;013&lt;BR /&gt;014&lt;BR /&gt;015&lt;BR /&gt;016&lt;BR /&gt;017&lt;BR /&gt;018&lt;BR /&gt;019&lt;BR /&gt;020&lt;BR /&gt;
&lt;/DIV&gt; 
    &lt;/TD&gt; 
    &lt;TD VALIGN='Top' NOWRAP='NOWRAP'&gt;&lt;div class='embedded-code-body'&gt;&lt;span class='psVariable'&gt;$vmhost&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;get-vmhost&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class='psVariable'&gt;$view&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;get-view&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$vmhost&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;id&lt;/span&gt;

&lt;span class='psVariable'&gt;$token&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$view&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;acquireCimServicesTicket&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;sessionId&lt;/span&gt;

&lt;span class='psVariable'&gt;$uri&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;https:///wsman&amp;quot;&lt;/span&gt;
&lt;span class='psVariable'&gt;$object&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;&amp;quot;http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_NumericSensor&amp;quot;&lt;/span&gt;

&lt;span class='psVariable'&gt;$wsman&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;new-object&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandParameter'&gt;-com&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandArgument'&gt;WSMan.automation&lt;/span&gt;
&lt;span class='psVariable'&gt;$options&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$wsman&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;createConnectionOptions&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psVariable'&gt;$options&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;username&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$token&lt;/span&gt;
&lt;span class='psVariable'&gt;$options&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;password&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$token&lt;/span&gt;
&lt;span class='psVariable'&gt;$flags&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$wsman&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;sessionFlagUseBasic&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;-bor&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$wsman&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;sessionFlagCredUserNamePassword&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;-bor&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$wsman&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;sessionflagskipcacheck&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;-bor&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$wsman&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;sessionflagskipcncheck&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;-bor&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$wsman&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;sessionflagskiprevocationcheck&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;

&lt;span class='psVariable'&gt;$session&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$wsman&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;createSession&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;$uri&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$flags&lt;/span&gt;&lt;span class='psOperator'&gt;,&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$options&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psVariable'&gt;$result&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$session&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;enumerate&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;$object&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;

&lt;span class='psVariable'&gt;$xml&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;while&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psOperator'&gt;!&lt;/span&gt;&lt;span class='psVariable'&gt;$result&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;atendofstream&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;$result&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;readitem&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psGroupEnd'&gt;}&lt;/span&gt; 
&lt;/DIV&gt; 
    &lt;/TD&gt; 
&lt;/TR&gt; 
&lt;/TBODY&gt; 
&lt;/TABLE&gt; 
&lt;/DIV&gt;
&lt;!--End Script--&gt;
&lt;p&gt;This proved that it was possible to pull this data from Windows, but I wanted to use my shiny new v2 cmdlets to do it (plus I wanted objects instead of XML that I was having problems casting without modification).&lt;/p&gt;
&lt;p&gt;My next step was to sniff the network from my workstation and see exactly what Get-WSManInstance was passing to the ESX server for the username and password.  That involved locating a version of Wireshark that had the SSL decryption libraries enabled (I'm using x64 Windows 7) and copying the private key from the ESX server to my workstation.&lt;/p&gt;
&lt;p&gt;After installing many different versions of Wireshark (1.2.2 for x86 worked) , I discovered that OpenWSMan logs authentication messages (that include the username) to /var/log/messages on the ESX server.  Either way you decide to go, what you will find is that Get-WSManInstance is pre-pending a "\" before the username:&lt;/p&gt;
&lt;p&gt;Sep 16 21:34:00 xvhalp22 openwsman(pam_unix)[12388]: bad username [\5297c1ab-ecf9-43c1-6b4a-cb7dce63d813]&lt;/p&gt;
&lt;p&gt;I decided to try and determine if the Powershell cmdlet was the culprit or if it was the .Net implementation of WSMan that was adding the extra character, so I did a little searching and came across this blog post that includes a function that allows you to pipe a cmdlet to it and it will locate the appropriate class and DLL and then load it up in Reflector (&lt;a href="http://www.nivot.org/2008/10/30/ATrickToJumpDirectlyToACmdletsImplementationInReflector.aspx"&gt;http://www.nivot.org/2008/10/30/ATrickToJumpDirectlyToACmdletsImplementationInReflector.aspx&lt;/a&gt;).  The command would be:&lt;/p&gt;
&lt;!--Start Script--&gt;
&lt;div class='embedded-code-wrapper'&gt;
&lt;TABLE BORDER='0' cellpadding='5' cellspacing='0'&gt; 
&lt;TR&gt; 
    &lt;TD VALIGN='Top'&gt;&lt;div class='line-no-column'&gt;001&lt;BR /&gt;
&lt;/DIV&gt; 
    &lt;/TD&gt; 
    &lt;TD VALIGN='Top' NOWRAP='NOWRAP'&gt;&lt;div class='embedded-code-body'&gt;&lt;span class='psCommand'&gt;get-command&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandArgument'&gt;Get-WSManInstance&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;|&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;Reflect-Cmdlet&lt;/span&gt; 
&lt;/DIV&gt; 
    &lt;/TD&gt; 
&lt;/TR&gt; 
&lt;/TBODY&gt; 
&lt;/TABLE&gt; 
&lt;/DIV&gt;
&lt;!--End Script--&gt;
&lt;p&gt;What I found after a little digging is that in the CreateSessionObject function of the WSManHelper class, they are setting the credentials as follows:&lt;/p&gt;
&lt;!--Start Script--&gt;
&lt;div class='embedded-code-wrapper'&gt;
&lt;TABLE BORDER='0' cellpadding='5' cellspacing='0'&gt; 
&lt;TR&gt; 
    &lt;TD VALIGN='Top'&gt;&lt;div class='line-no-column'&gt;001&lt;BR /&gt;002&lt;BR /&gt;003&lt;BR /&gt;004&lt;BR /&gt;005&lt;BR /&gt;006&lt;BR /&gt;007&lt;BR /&gt;008&lt;BR /&gt;009&lt;BR /&gt;010&lt;BR /&gt;011&lt;BR /&gt;012&lt;BR /&gt;013&lt;BR /&gt;014&lt;BR /&gt;015&lt;BR /&gt;016&lt;BR /&gt;017&lt;BR /&gt;018&lt;BR /&gt;019&lt;BR /&gt;020&lt;BR /&gt;021&lt;BR /&gt;022&lt;BR /&gt;023&lt;BR /&gt;
&lt;/DIV&gt; 
    &lt;/TD&gt; 
    &lt;TD VALIGN='Top' NOWRAP='NOWRAP'&gt;&lt;div class='embedded-code-body'&gt;&lt;span class='psKeyword'&gt;if&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;credential&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;!=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;null&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psType'&gt;NetworkCredential&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;networkCredential&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommand'&gt;new&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psCommandArgument'&gt;NetworkCredential&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psStatementSeparator'&gt;;&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;if&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;credential&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;get_UserName&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;!=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;null&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;networkCredential&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;credential&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;GetNetworkCredential&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psStatementSeparator'&gt;;&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;if&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psType'&gt;string&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;networkCredential&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Domain&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;if&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psVariable'&gt;authentication&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Equals&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psType'&gt;AuthenticationMechanism&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Digest&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  &amp;nbsp;&amp;nbsp;  &lt;/span&gt;&lt;span class='psVariable'&gt;connectionOptions&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;UserName&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;networkCredential&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;UserName&lt;/span&gt;&lt;span class='psStatementSeparator'&gt;;&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;else&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;connectionOptions&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;UserName&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;@&amp;quot;\&amp;quot;&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;+&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;networkCredential&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;UserName&lt;/span&gt;&lt;span class='psStatementSeparator'&gt;;&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;else&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;{&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;connectionOptions&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;UserName&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;networkCredential&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Domain&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;+&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psString'&gt;@&amp;quot;\&amp;quot;&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;+&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;networkCredential&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;UserName&lt;/span&gt;&lt;span class='psStatementSeparator'&gt;;&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupEnd'&gt;}&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;connectionOptions&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Password&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;=&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;networkCredential&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Password&lt;/span&gt;&lt;span class='psStatementSeparator'&gt;;&lt;/span&gt;
&lt;span class='psUnknown'&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class='psKeyword'&gt;if&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psOperator'&gt;!&lt;/span&gt;&lt;span class='psVariable'&gt;authentication&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Equals&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psType'&gt;AuthenticationMechanism&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Credssp&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;||&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;!&lt;/span&gt;&lt;span class='psVariable'&gt;authentication&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Equals&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psType'&gt;AuthenticationMechanism&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Digest&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psOperator'&gt;||&lt;/span&gt;&lt;span class='psUnknown'&gt;&amp;nbsp;&lt;/span&gt;&lt;span class='psVariable'&gt;authentication&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Equals&lt;/span&gt;&lt;span class='psGroupStart'&gt;(&lt;/span&gt;&lt;span class='psType'&gt;AuthenticationMechanism&lt;/span&gt;&lt;span class='psOperator'&gt;.&lt;/span&gt;&lt;span class='psMember'&gt;Basic&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;&lt;span class='psGroupEnd'&gt;)&lt;/span&gt;
&lt;/DIV&gt; 
    &lt;/TD&gt; 
&lt;/TR&gt; 
&lt;/TBODY&gt; 
&lt;/TABLE&gt; 
&lt;/DIV&gt;
&lt;!--End Script--&gt;
&lt;p&gt;I think line 15 is the cause of my problem and I believe this is a bug in the cmdlet.  I'm not sure which "basic" authentication schemes would be expecting a username like "\user", and in fact the System.Net.WebClient doesn't add this leading slash when you use Basic and a PSCredential.&lt;/p&gt;
&lt;p&gt;I haven't tried this on the Vista or XP PowerShell v2 RC, but I have to assume that this behavior was introduced sometime after CTP3, or the PowerCLI Blog people would never have been able to connect.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=5Q2abTui70E:2rfYZmW9aTo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=5Q2abTui70E:2rfYZmW9aTo:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=5Q2abTui70E:2rfYZmW9aTo:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=5Q2abTui70E:2rfYZmW9aTo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=5Q2abTui70E:2rfYZmW9aTo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=5Q2abTui70E:2rfYZmW9aTo:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=5Q2abTui70E:2rfYZmW9aTo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=5Q2abTui70E:2rfYZmW9aTo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatsUpDuckBlog/~4/5Q2abTui70E" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.whatsupduck.net/feeds/7659981499074588077/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.whatsupduck.net/2009/09/not-using-powershell-v2-to-view-wsman.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/7659981499074588077?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/7659981499074588077?v=2" /><link rel="alternate" type="text/html" href="http://blog.whatsupduck.net/2009/09/not-using-powershell-v2-to-view-wsman.html" title="(Not) Using PowerShell v2 to View WSMan Data From ESX" /><author><name>Chris Duck</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>5</thr:total></entry><entry gd:etag="W/&quot;A0ABQ3w5fCp7ImA9WhdbFEU.&quot;"><id>tag:blogger.com,1999:blog-7728225756528319729.post-4098304879352687037</id><published>2009-07-15T10:51:00.011-05:00</published><updated>2011-10-13T02:09:12.224-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-13T02:09:12.224-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SSL" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="ePO" /><category scheme="http://www.blogger.com/atom/ns#" term="Certificate" /><category scheme="http://www.blogger.com/atom/ns#" term="Tomcat" /><title>Adding a Custom Certificate to McAfee ePO Server 4.0 (Apache)</title><content type="html">&lt;p&gt;Our ePO adminitrators came to me asking for help installing an enterprise certificate on our new ePO 4.0 server so they could provide a vanity dns name for management to view reports.  &lt;a href="https://kc.mcafee.com/corporate/index?page=content&amp;amp;id=KB52736"&gt;According to McAfee&lt;/a&gt;, this is not supported in 4.0, but will be a feature of 4.5. Knowing that ePO runs on Tomcat, I was pretty confident that I could get it working anyway... just remember that none of this is supported. If you need a supported solution on 4.0, I recommend adding the self signed certificate to your domain certificate trust list and using the computer name to access the site.&lt;/p&gt;
&lt;p&gt;If you just have to have your vanity url, here's how you can get it set up.&lt;/p&gt;
&lt;p&gt;The main idea here is to import a certificate that will be trusted by your browsers (either a domain certificate or a public certificate from a trusted CA like EnTrust or Verisign) into the Java keystore that Tomcat is using. Our security team provided us with a certificate and a private key from an existing wildcard certificate for our domain.&lt;/p&gt;
&lt;p&gt;In order to locate the correct keystore, I loaded up the Tomcat configuration file located at c:\Program Files\McAfee\ePolicy Orchestrator\Server\conf\server.xml. From here, you need to locate the "Connector" element that is binding to the port for the site you are using. In our case, this is 8443 so the element looks like this:&lt;/p&gt;
&lt;span class="tab code"&gt;&amp;lt;connector acceptcount="100" ciphers="…list of encyrption algorithms..." clientauth="false" disableuploadtimeout="true" enablelookups="false" keystorefile="keystore/server.keystore" keystorepass="*****" maxhttpheadersize="8192" maxsparethreads="75" maxthreads="150" minsparethreads="25" port="8443" scheme="https" secure="true" server="Undefined" sslprotocol="TLS" truststorefile="keystore/ca.keystore" truststorepass="*****" uriencoding="UTF-8"&amp;gt;&amp;lt;/connector&amp;gt;&lt;/span&gt;
&lt;p&gt;Sun Java provides a tool to edit keystores called &lt;a href="http://java.sun.com/javase/6/docs/technotes/tools/windows/keytool.html"&gt;keytool.exe&lt;/a&gt;. However, there is a limitation on this tool (described &lt;a href="http://cunning.sharp.fm/2008/06/importing_private_keys_into_a.html"&gt;here&lt;/a&gt;) that prevents us from adding a private key separately. Fortunately ePO uses the latest version of Java, so we do have the ability to import a PKCS12 file containing both our public certificate as well as our private key.&lt;/p&gt;
&lt;p&gt;First, I had to get my separate files into one PKCS12 file. I did this using the following &lt;a href="http://www.slproweb.com/products/Win32OpenSSL.html"&gt;OpenSSL&lt;/a&gt; command:&lt;/p&gt;
&lt;span class="code"&gt;&amp;gt; openssl pkcs12 -export -out c:\temp\store.pfx -in c:\temp\certificate.cer -inkey c:\temp\private.key&lt;/span&gt;
&lt;p&gt;Now that I have a PKCS12 file with both the certificate and private key, I can import those into the Java keystore for Tomcat. My first step was to add the JRE\bin to my path and change to the directory of the keystore:&lt;/p&gt;
&lt;span class="code"&gt;&amp;gt; set path=%path%;c:\Program Files\McAfee\ePolicy Orchestrator\JRE\bin&lt;br /&gt;
&amp;gt; cd C:\Program Files\McAfee\ePolicy Orchestrator\Server\keystore\&lt;/span&gt;
&lt;p&gt;Next I made a backup of the original McAfee keystore (so we can go back to the supported configuration if needed):&lt;/p&gt;
&lt;span class="code"&gt;&amp;gt; copy server.keystore server.keystore.original&lt;/span&gt;
&lt;p&gt;Then I deleted the existing certificate and private key from the keystore, then imported the new pair from the PKCS12 file, and finally renamed the alias for the key to match the original:&lt;/p&gt;
&lt;span class="code"&gt;&amp;gt; keytool -delete -alias mykey -keystore server.keystore&lt;br /&gt;
&amp;gt; keytool -delete -alias cacert -keystore server.keystore&lt;br /&gt;
&amp;gt; keytool -importkeystore -srckeystore c:\vhacert\store.pfx -destkeystore server.keystore -srcstoretype pkcs12&lt;br /&gt;
&amp;gt; keytool -changealias -keystore server.keystore -alias 1 -destalias mykey&lt;/span&gt;
&lt;p&gt;Finally, you just need to restart all 3 ePO services.  Tomcat should now be providing your custom certificate.&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=xUXfyB0sr_4:h-ia4MyJOoQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=xUXfyB0sr_4:h-ia4MyJOoQ:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=xUXfyB0sr_4:h-ia4MyJOoQ:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=xUXfyB0sr_4:h-ia4MyJOoQ:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=xUXfyB0sr_4:h-ia4MyJOoQ:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=xUXfyB0sr_4:h-ia4MyJOoQ:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.whatsupduck.net/~ff/WhatsUpDuckBlog?a=xUXfyB0sr_4:h-ia4MyJOoQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/WhatsUpDuckBlog?i=xUXfyB0sr_4:h-ia4MyJOoQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatsUpDuckBlog/~4/xUXfyB0sr_4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.whatsupduck.net/feeds/4098304879352687037/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.whatsupduck.net/2009/07/adding-custom-certificate-to-mcafee-epo.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/4098304879352687037?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7728225756528319729/posts/default/4098304879352687037?v=2" /><link rel="alternate" type="text/html" href="http://blog.whatsupduck.net/2009/07/adding-custom-certificate-to-mcafee-epo.html" title="Adding a Custom Certificate to McAfee ePO Server 4.0 (Apache)" /><author><name>Chris Duck</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry></feed>
