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

<channel>
	<title>grokgarble.com &#187; .NET</title>
	<atom:link href="http://jeffmurr.com/blog/?cat=8&#038;feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://jeffmurr.com/blog</link>
	<description>Database, Software, and System Engineering</description>
	<lastBuildDate>Tue, 26 Sep 2017 19:07:40 +0000</lastBuildDate>
	<language>en-US</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.9.30</generator>
	<item>
		<title>PEM Certificate from .NET/PowerShell</title>
		<link>http://jeffmurr.com/blog/?p=255</link>
		<comments>http://jeffmurr.com/blog/?p=255#comments</comments>
		<pubDate>Fri, 22 Aug 2014 15:12:34 +0000</pubDate>
		<dc:creator><![CDATA[Jeff Murr]]></dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://jeffmurr.com/blog/?p=255</guid>
		<description><![CDATA[It is a tough thing &#8211; cryptography.  Especially when you try to standardize it enough for consumption among various components on hosted on multiple platforms.  Microsoft has done a good job of making their import features agnostic to file format.  Other platforms are not so forgiving and require it to be very specific based on [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>It is a tough thing &#8211; cryptography.  Especially when you try to standardize it enough for consumption among various components on hosted on multiple platforms.  Microsoft has done a good job of making their import features agnostic to file format.  Other platforms are not so forgiving and require it to be very specific based on function.  One of those specific formats is base64, with the appropriate line breaks, with a header and footer &#8211; or PEM.  This comes into play when you need to send a public certificate hosted on a Windows machine to a platform other than Windows, like an AS/400 mainframe for client certificate authentication.</p>
<p>PowerShell gives us the ability to quickly come up with an certificate object that is quite common on the Windows side: <a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2(v=vs.110).aspx">System.Security.Cryptography.X509Certificates.X509Certificate2</a>.  To get there you can use the &#8220;cert&#8221; mount like this:</p>
<pre class="brush:powershell">cd Cert:\CurrentUser\My</pre>
<p>This allows you to get all certificates in your current user store and enumerate them as individual X509Certificate2 objects.  You can see them all once you&#8217;re here with a &#8220;DIR&#8221; or &#8220;Get-ChildItem&#8221; command to get a complete list of everything in the container.</p>
<p>To get a specific one stored into a variable use the handy Where-Object cmdlet like this:</p>
<pre class="brush:powershell">$Cert = Get-ChildItem | where{ $_.Thumbprint -eq "DDC843EE6EFF730D4F5B87E2EF1212FB77223B27" }</pre>
<p>If you want to confirm the type do a quick Get-Member (I do this so often to keep a bead on what I have available to me with a given object all the time)</p>
<pre class="brush:powershell">$Cert | gm</pre>
<p>Now, lets export the public certificate out as a base64 PEM with headers you&#8217;ll need to add them to the RawData property of the $Cert object:</p>
<pre class="brush:powershell">$out = New-Object String[] -ArgumentList 3
$OutputFile = "C:\Temp\MyCertAsPEM.CER"

$out[0] = "-----BEGIN CERTIFICATE-----"
$out[1] = [System.Convert]::ToBase64String($Cert.PublicKey.EncodedKeyValue.RawData, "InsertLineBreaks")
$out[2] = "-----END CERTIFICATE-----"

[System.IO.File]::WriteAllLines($OutputFile,$out)</pre>
<p>The above takes in account that you might have a private key and limits the output file to the public key only.</p>
<p>So, what about that pesky private key? Stay tuned..</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<div data-counters='1' data-style='square' data-size='regular' data-url='http://jeffmurr.com/blog/?p=255' data-title='PEM Certificate from .NET/PowerShell' class='linksalpha_container linksalpha_app_3'><a href='//www.linksalpha.com/share?network='facebook' class='linksalpha_icon_facebook'></a><a href='//www.linksalpha.com/share?network='twitter' class='linksalpha_icon_twitter'></a><a href='//www.linksalpha.com/share?network='googleplus' class='linksalpha_icon_googleplus'></a><a href='//www.linksalpha.com/share?network='mail' class='linksalpha_icon_mail'></a></div><div data-position='' data-url='http://jeffmurr.com/blog/?p=255' data-title='PEM Certificate from .NET/PowerShell' class='linksalpha_container linksalpha_app_7'><a href='//www.linksalpha.com/share?network='facebook' class='linksalpha_icon_facebook'></a><a href='//www.linksalpha.com/share?network='twitter' class='linksalpha_icon_twitter'></a><a href='//www.linksalpha.com/share?network='googleplus' class='linksalpha_icon_googleplus'></a><a href='//www.linksalpha.com/share?network='mail' class='linksalpha_icon_mail'></a></div>
<!-- NgfbSharing::get_buttons content filter skipped: buttons not allowed in rss feeds -->
]]></content:encoded>
			<wfw:commentRss>http://jeffmurr.com/blog/?feed=rss2&#038;p=255</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Grant NTFS Permissions to a Domain Group using C#</title>
		<link>http://jeffmurr.com/blog/?p=244</link>
		<comments>http://jeffmurr.com/blog/?p=244#comments</comments>
		<pubDate>Tue, 22 Apr 2014 12:54:11 +0000</pubDate>
		<dc:creator><![CDATA[Jeff Murr]]></dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://jeffmurr.com/blog/?p=244</guid>
		<description><![CDATA[Coupled with creating a network file share, you need to also ensure NTFS permissions are not more restrictive than the permissions you create on your share.  Otherwise, they will trump those permissions and your file share will be half done.  The least restrictive permissions always win.  See technet for more details on the security model. Using [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Coupled with creating a network <a href="http://jeffmurr.com/blog/?p=241">file share</a>, you need to also ensure NTFS permissions are not more restrictive than the permissions you create on your share.  Otherwise, they will trump those permissions and your file share will be half done.  The least restrictive permissions always win.  See <a href="http://technet.microsoft.com/en-us/library/cc754178.aspx">technet </a>for more details on the security model.</p>
<p>Using a mix of the <a href="http://msdn.microsoft.com/en-us/library/System.Security.Principal(v=vs.110).aspx">Security.Principal</a> and <a href="http://msdn.microsoft.com/en-us/library/system.security.accesscontrol(v=vs.110).aspx">Security.AccessControl </a>.NET Classes you can couple this with your file share create class and get a complete set up of a file share; or, just use it to set NTFS permissions without all the file share portions in the previous post to set NTFS permissions on their own.</p>
<pre class="brush:csharp">using System.Security.Principal;
using System.Security.AccessControl;

        public static void GrantNTFSPermissions(string FolderPath, string Domain, string Group)
        {
            // Create a new DirectoryInfo object.
            DirectoryInfo directoryInfo = new DirectoryInfo(FolderPath);

            // Get a DirectorySecurity object that represents the 
            // current security settings.
            DirectorySecurity directorySecurity = directoryInfo.GetAccessControl();

            // Add the FileSystemAccessRule to the security settings. 
            directorySecurity.AddAccessRule(
                new FileSystemAccessRule(
                    new NTAccount(Domain, Group), 
                    FileSystemRights.Modify | FileSystemRights.ReadAndExecute | FileSystemRights.ListDirectory | FileSystemRights.Read | FileSystemRights.Write, 
                    InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None,
                    AccessControlType.Allow)
                );

            // Set the new access settings.
            directoryInfo.SetAccessControl(directorySecurity);

        }</pre>
<p><strong>Important Note:</strong>  Passing mulitple values separated with a &#8220;|&#8221; to the <a href="http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.filesystemaccessrule(v=vs.110).aspx">FileSystemAccessRule </a>class constructor&#8217;s parameters, allows you to set multiple options at once over mutliple calls/rewrites.</p>
<div data-counters='1' data-style='square' data-size='regular' data-url='http://jeffmurr.com/blog/?p=244' data-title='Grant NTFS Permissions to a Domain Group using C#' class='linksalpha_container linksalpha_app_3'><a href='//www.linksalpha.com/share?network='facebook' class='linksalpha_icon_facebook'></a><a href='//www.linksalpha.com/share?network='twitter' class='linksalpha_icon_twitter'></a><a href='//www.linksalpha.com/share?network='googleplus' class='linksalpha_icon_googleplus'></a><a href='//www.linksalpha.com/share?network='mail' class='linksalpha_icon_mail'></a></div><div data-position='' data-url='http://jeffmurr.com/blog/?p=244' data-title='Grant NTFS Permissions to a Domain Group using C#' class='linksalpha_container linksalpha_app_7'><a href='//www.linksalpha.com/share?network='facebook' class='linksalpha_icon_facebook'></a><a href='//www.linksalpha.com/share?network='twitter' class='linksalpha_icon_twitter'></a><a href='//www.linksalpha.com/share?network='googleplus' class='linksalpha_icon_googleplus'></a><a href='//www.linksalpha.com/share?network='mail' class='linksalpha_icon_mail'></a></div>
<!-- NgfbSharing::get_buttons content filter skipped: buttons not allowed in rss feeds -->
]]></content:encoded>
			<wfw:commentRss>http://jeffmurr.com/blog/?feed=rss2&#038;p=244</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Network File Share in .NET C#</title>
		<link>http://jeffmurr.com/blog/?p=241</link>
		<comments>http://jeffmurr.com/blog/?p=241#comments</comments>
		<pubDate>Wed, 19 Feb 2014 22:41:31 +0000</pubDate>
		<dc:creator><![CDATA[Jeff Murr]]></dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://jeffmurr.com/blog/?p=241</guid>
		<description><![CDATA[Well, kinda&#8230; Using the ManagmentClass class (someone might be regretting the naming here) we can expose WMI in .NET.  Then, we can operate on methods of the Windows Managment Interface to create shares in C# code. Like all Windows API work, this isn&#8217;t super clear throughout MSDN or the Internet.  I also find that Windows [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Well, kinda&#8230;</p>
<p>Using the <a href="http://msdn.microsoft.com/en-us/library/system.management.managementclass(v=vs.110).aspx">ManagmentClass</a> class (someone might be regretting the naming here) we can expose WMI in .NET.  Then, we can operate on methods of the Windows Managment Interface to create shares in C# code.</p>
<p>Like all Windows API work, this isn&#8217;t super clear throughout MSDN or the Internet.  I also find that Windows API return codes are a pain.  When I operate in that old schools space I try to take the next step and get a return code description method created.</p>
<p>Below, we create a security descriptor and share using .NET and WMI objects (with some return code flare).</p>
<p>Enjoy!</p>
<p>1) Figure out who you want access to your share.  This must be done with the use of of a <a href="http://msdn.microsoft.com/en-us/library/aa394402(v=vs.85).aspx">Win32_SecurityDescriptor</a> in WMI:</p>
<pre class="brush:csharp">        private static ManagementBaseObject SecurityDescriptor()
        {
            NTAccount account = new NTAccount("NT Authority", "Everyone");
            SecurityIdentifier sid = (SecurityIdentifier)account.Translate(typeof(SecurityIdentifier));
            byte[] sidArray = new byte[sid.BinaryLength];
            sid.GetBinaryForm(sidArray, 0);
            ManagementObject Trustee = new ManagementClass(new ManagementPath("Win32_Trustee"), null);
            Trustee["Domain"] = "NT Authority";
            Trustee["Name"] = "Everyone";
            Trustee["SID"] = sidArray;
            ManagementObject AdminACE = new ManagementClass(new ManagementPath("Win32_Ace"), null);
            AdminACE["AccessMask"] = 2032127;
            AdminACE["AceFlags"] = 3;
            AdminACE["AceType"] = 0;
            AdminACE["Trustee"] = Trustee;
            ManagementObject SecurityDescriptor = new ManagementClass(new ManagementPath("Win32_SecurityDescriptor"), null);
            SecurityDescriptor["ControlFlags"] = 4; //SE_DACL_PRESENT
            SecurityDescriptor["DACL"] = new object[] { AdminACE };
            return SecurityDescriptor;
        }</pre>
<p>It&#8217;s never easy with security&#8230;.</p>
<p>So for an explaination of the above; first, you look up your principle using <a href="http://msdn.microsoft.com/en-us/library/system.security.principal.ntaccount(v=vs.110).aspx">NTAccount</a> then create a <a href="http://msdn.microsoft.com/en-us/library/aa394501(v=vs.85).aspx">Win32_Trustee</a> from that principal.</p>
<p><strong><em>note:</em></strong>  this method can *easily* be parameterized for a domain:</p>
<pre class="brush:csharp">        private static ManagementBaseObject SecurityDescriptor(string domain, string user)
        {
            NTAccount account = new NTAccount(domain, user);
            SecurityIdentifier sid = (SecurityIdentifier)account.Translate(typeof(SecurityIdentifier));

[...]</pre>
<p>Then, you estable what access controll entry (<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa374868(v=vs.85).aspx">ACE)</a> you want to grant to the principal(s) using the <a href="http://msdn.microsoft.com/en-us/library/aa394063(v=vs.85).aspx">Win32_Ace</a> object.  The SecurityDescriptor method above includes it all.  Side note: ACL and ACE&#8217;s are the most confusing things to code in Windows for me, bar none.  It&#8217;s not easy, play with the code to taste if you need specific access and don&#8217;t forget to review the <a href="http://msdn.microsoft.com/en-us/library/aa394063(v=vs.85).aspx">AccessMask</a> and <a href="http://msdn.microsoft.com/en-us/library/aa394063(v=vs.85).aspx">AceTypes</a> to limit down from full control as needed.  To add multiple add them as comma separated DACL&#8217;s like so:</p>
<pre class="brush:csharp">SecurityDescriptor["DACL"] = new object[] { AdminACE, MyACE, YourACE, OurACE };</pre>
<p>2) Finally, create your share</p>
<p>First, create your <a href="http://msdn.microsoft.com/en-us/library/system.management.managementclass(v=vs.110).aspx">ManagmentClass object</a> and parameters (using your above security principal(s)) for the &#8220;Create&#8221; method of the <a href="http://msdn.microsoft.com/en-us/library/aa389393(v=vs.85).aspx">Win32_Share</a>.  If anything funky happens decode the response code description.</p>
<pre class="brush:csharp">        public static void CreateShare(string FolderPath, string ShareName, string Description)
        {
            //create a ManagementClass object
            ManagementClass managementClass = new ManagementClass("Win32_Share");

            //create ManagementBaseObjects for in and out parameters
            ManagementBaseObject inParams = managementClass.GetMethodParameters("Create");
            ManagementBaseObject outParams;

            // Set the input parameters
            inParams["Description"] = Description;
            inParams["Name"] = ShareName;
            inParams["Path"] = FolderPath;
            inParams["Type"] = 0x0; // Disk Drive

            //invoke the method
            outParams = managementClass.InvokeMethod("Create", inParams, null);

            //check to see if the method invocation was successful
            uint rVal = (uint)(outParams.Properties["ReturnValue"].Value);
            if (rVal != 0 &amp;&amp; rVal != 22) //ok if it already exists
            {
                throw new Exception(String.Format("Unable to share directory. \nReturn Code: {0} \nDescription: {1}", rVal, getCreateShareReturnCodeDescription(rVal)));
            }
        }

        private static string getCreateShareReturnCodeDescription(uint returnValue)
        {
            switch (returnValue)
            {
                case 0:
                    return "Success";
                case 2:
                    return "Access Denied";
                case 8:
                    return "Unknown Failure";
                case 9:
                    return "Invalid Name";
                case 10:
                    return "Invalid Level";
                case 21:
                    return "Invalid Parameter";
                case 22:
                    return "Duplicate Share";
                case 23:
                    return "Redirect Path";
                case 24:
                    return "Unknown Device or Directory";
                case 25:
                    return "Net Name Not Found";
            }
            return "Unknown";
        }</pre>
<div data-counters='1' data-style='square' data-size='regular' data-url='http://jeffmurr.com/blog/?p=241' data-title='Network File Share in .NET C#' class='linksalpha_container linksalpha_app_3'><a href='//www.linksalpha.com/share?network='facebook' class='linksalpha_icon_facebook'></a><a href='//www.linksalpha.com/share?network='twitter' class='linksalpha_icon_twitter'></a><a href='//www.linksalpha.com/share?network='googleplus' class='linksalpha_icon_googleplus'></a><a href='//www.linksalpha.com/share?network='mail' class='linksalpha_icon_mail'></a></div><div data-position='' data-url='http://jeffmurr.com/blog/?p=241' data-title='Network File Share in .NET C#' class='linksalpha_container linksalpha_app_7'><a href='//www.linksalpha.com/share?network='facebook' class='linksalpha_icon_facebook'></a><a href='//www.linksalpha.com/share?network='twitter' class='linksalpha_icon_twitter'></a><a href='//www.linksalpha.com/share?network='googleplus' class='linksalpha_icon_googleplus'></a><a href='//www.linksalpha.com/share?network='mail' class='linksalpha_icon_mail'></a></div>
<!-- NgfbSharing::get_buttons content filter skipped: buttons not allowed in rss feeds -->
]]></content:encoded>
			<wfw:commentRss>http://jeffmurr.com/blog/?feed=rss2&#038;p=241</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Asymmetric Encryption of Text using x.509 Certificates in PowerShell</title>
		<link>http://jeffmurr.com/blog/?p=228</link>
		<comments>http://jeffmurr.com/blog/?p=228#comments</comments>
		<pubDate>Sat, 07 Dec 2013 18:29:00 +0000</pubDate>
		<dc:creator><![CDATA[Jeff Murr]]></dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Encryption]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://jeffmurr.com/blog/?p=228</guid>
		<description><![CDATA[I&#8217;ve been requested to encryption sections of my script (user name/password) using a certificate issued by a trusted CA.  No problem. To do this in the blog, I&#8217;ll I created a self-signed x.509 certificate and a CN of &#8220;PowerShellCert&#8221;.  I will use the public portion of the certificate in a file that&#8217;s base64 .cer to encrypt the [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve been requested to encryption sections of my script (user name/password) using a certificate issued by a trusted CA.  No problem.</p>
<p>To do this in the blog, I&#8217;ll I created a self-signed <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms721636(v=vs.85).aspx#_security_x.509_gly">x.509</a> certificate and a CN of &#8220;PowerShellCert&#8221;.  I will use the public portion of the certificate in a file that&#8217;s base64 .cer to encrypt the sections.  That certificate I&#8217;ll place in the Windows key store and referenced by thumbprint for decryption.  For the actual work, I&#8217;ll import the CA trusted certificate into the same key store, replace the thumbprint with that CA trusted one and make sure the certificate is trusted either by the user or machine the script is running.</p>
<p>Here&#8217;s the command used with the <a href="http://msdn.microsoft.com/en-us/library/bfsktky3(v=vs.110).aspx">makecert </a>utility to create a 2048 length cert:</p>
<pre class="brush:shell">C:\Program Files\Microsoft SDKs\Windows\v7.1&gt;makecert.exe -r -pe -n "CN=PowerShellCert" -ss my -sr localmachine -eku 1.3.6.1.5.5.7.3.2 -len 2048 -e 01/01/2030 C:\Scripts\PowerShell\Asymmetrical-Encryption\PowerShellAsymmetrical.cer</pre>
<p>Here&#8217;s the encryption function:</p>
<pre class="brush:powershell">Function Encrypt-Asymmetric {
	[CmdletBinding()]
	[OutputType([System.String])]
	param(
		[Parameter(Position=0, Mandatory=$true)][ValidateNotNullOrEmpty()][System.String]
		$ClearText,
		[Parameter(Position=1, Mandatory=$true)][ValidateNotNullOrEmpty()][ValidateScript({Test-Path $_ -PathType Leaf})][System.String]
		$PublicCertFilePath
	)
    # Encrypts a string with a public key
    $PublicCert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($PublicCertFilePath)
    $ByteArray = [System.Text.Encoding]::UTF8.GetBytes($ClearText)
	$EncryptedByteArray = $PublicCert.PublicKey.Key.Encrypt($ByteArray,$true)
	$Base64String = [Convert]::ToBase64String($EncryptedByteArray)

	Return $Base64String 
}</pre>
<p>&#8230;here&#8217;s the decryption function:</p>
<pre class="brush:powershell">Function Decrypt-Asymmetric
{
	[CmdletBinding()]
	[OutputType([System.String])]
	param(
		[Parameter(Position=0, Mandatory=$true)][ValidateNotNullOrEmpty()][System.String]
		$EncryptedBase64String,
		[Parameter(Position=1, Mandatory=$true)][ValidateNotNullOrEmpty()][System.String]
		$CertThumbprint
	)
    # Decrypts cipher text using the private key
    # Assumes the certificate is in the LocalMachine\My (Personal) Store
    $Cert = Get-ChildItem cert:\LocalMachine\My | where { $_.Thumbprint -eq $CertThumbprint }
	if($Cert) {
	    $EncryptedByteArray = [Convert]::FromBase64String($EncryptedBase64String)
	    $ClearText = [System.Text.Encoding]::UTF8.GetString($Cert.PrivateKey.Decrypt($EncryptedByteArray,$true))
    }
	Else {Write-Error "Certificate with thumbprint: $CertThumbprint not found!"}

	Return $ClearText
}</pre>
<p>To Encrypt clear text:</p>
<pre class="brush:shell">PS C:\&gt;Encrypt-Asymmetric -ClearText "CLEAR TEXT DATA" -PublicCertFilePath "C:\Scripts\PowerShell\Asymmetrical-Encryption\PowerShellAsymmetricalTest.cer"</pre>
<p>To Decrypt clear text:</p>
<pre>PS C:\&gt;Decrypt-Asymmetric -EncryptedBase64String $Base64String -CertThumbprint "83D2D68907681EF3D823B23DEE24B0CBB3FA3C51"</pre>
<p>To find your Certificate&#8217;s thumbprint (assuming you gave it the same name as I did above):</p>
<pre class="brush:powershell">PS C:\&gt; Get-ChildItem cert:\LocalMachine\My | where { $_.Subject -eq "CN=PowerShellCert" } | select Thumbprint</pre>
<p>Now, encryption keys can be garded under the Windows key store.</p>
<div data-counters='1' data-style='square' data-size='regular' data-url='http://jeffmurr.com/blog/?p=228' data-title='Asymmetric Encryption of Text using x.509 Certificates in PowerShell' class='linksalpha_container linksalpha_app_3'><a href='//www.linksalpha.com/share?network='facebook' class='linksalpha_icon_facebook'></a><a href='//www.linksalpha.com/share?network='twitter' class='linksalpha_icon_twitter'></a><a href='//www.linksalpha.com/share?network='googleplus' class='linksalpha_icon_googleplus'></a><a href='//www.linksalpha.com/share?network='mail' class='linksalpha_icon_mail'></a></div><div data-position='' data-url='http://jeffmurr.com/blog/?p=228' data-title='Asymmetric Encryption of Text using x.509 Certificates in PowerShell' class='linksalpha_container linksalpha_app_7'><a href='//www.linksalpha.com/share?network='facebook' class='linksalpha_icon_facebook'></a><a href='//www.linksalpha.com/share?network='twitter' class='linksalpha_icon_twitter'></a><a href='//www.linksalpha.com/share?network='googleplus' class='linksalpha_icon_googleplus'></a><a href='//www.linksalpha.com/share?network='mail' class='linksalpha_icon_mail'></a></div>
<!-- NgfbSharing::get_buttons content filter skipped: buttons not allowed in rss feeds -->
]]></content:encoded>
			<wfw:commentRss>http://jeffmurr.com/blog/?feed=rss2&#038;p=228</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PowerShell for Free Space?</title>
		<link>http://jeffmurr.com/blog/?p=208</link>
		<comments>http://jeffmurr.com/blog/?p=208#comments</comments>
		<pubDate>Tue, 10 Sep 2013 13:47:11 +0000</pubDate>
		<dc:creator><![CDATA[Jeff Murr]]></dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://jeffmurr.com/blog/?p=208</guid>
		<description><![CDATA[I needed a script that could be executed to report free space.  I&#8217;ll review how to do it locally and how to wrap it around an array of computer names so it can be ran from anywhere with RPC access to the target machines. For Starters Here&#8217;s the script that gets my my report from [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I needed a script that could be executed to report free space.  I&#8217;ll review how to do it locally and how to wrap it around an array of computer names so it can be ran from anywhere with RPC access to the target machines.</p>
<h3>For Starters</h3>
<p>Here&#8217;s the script that gets my my report from a local computer:</p>
<pre class="brush:powershell">Get-WmiObject -Class Win32_LogicalDisk -Filter "DriveType=3" |
Select-Object Name, FileSystem,FreeSpace,BlockSize,Size |
ForEach-Object {
	$_.BlockSize=(($_.FreeSpace)/($_.Size))*100;$_.FreeSpace=($_.FreeSpace/1GB);$_.Size=($_.Size/1GB);$_
	} |
Format-Table @{n='Server';e={$env:COMPUTERNAME}}, @{n='Disk';e={$_.Name}}, @{n='FS';e={$_.FileSystem}},@{n='Capacity (GB)';e={'{0:N3}' -f $_.Size}},@{n='GB Free';e={'{0:N2}'-f $_.FreeSpace}}, @{n='% Free';e={'{0:N2}'-f $_.BlockSize}} -AutoSize</pre>
<h3>Do it Remote:</h3>
<p>Keep in mind the entire script can be wrapped around a &#8220;<strong>foreach</strong>&#8221; statement and pass in the <strong>ComputerName</strong> parameter for remote execution.</p>
<pre class="brush:powershell">$ComputerNames = @("Server1", "Server2", "Server3")

foreach ($ComputerName in $ComputerNames) {

	Get-WmiObject -ComputerName $ComputerName -Class Win32_LogicalDisk -Filter "DriveType=3" |
	Select-Object Name, FileSystem,FreeSpace,BlockSize,Size |
	ForEach-Object {
		$_.BlockSize=(($_.FreeSpace)/($_.Size))*100;$_.FreeSpace=($_.FreeSpace/1GB);$_.Size=($_.Size/1GB);$_
		} |
	Format-Table @{n='Server';e={$ComputerName}}, @{n='Disk';e={$_.Name}}, @{n='FS';e={$_.FileSystem}},@{n='Capacity (GB)';e={'{0:N3}' -f $_.Size}},@{n='GB Free';e={'{0:N2}'-f $_.FreeSpace}}, @{n='% Free';e={'{0:N2}'-f $_.BlockSize}} -AutoSize

}</pre>
<h3>Report What You Found:</h3>
<p>Afterward, sprinkle in the export type you&#8217;d like (file, CSV, etc.) to deliver.</p>
<pre class="brush:powershell">$ComputerNames = @("Server1", "Server2", "Server3")

$DiskSpaceReport = foreach ($ComputerName in $ComputerNames) {

	Get-WmiObject -Class Win32_LogicalDisk -Filter "DriveType=3" |
	Select-Object Name, FileSystem,FreeSpace,BlockSize,Size |
	ForEach-Object {
		$_.BlockSize=(($_.FreeSpace)/($_.Size))*100;$_.FreeSpace=($_.FreeSpace/1GB);$_.Size=($_.Size/1GB);$_
		} |
	Format-Table @{n='Server';e={$ComputerName}}, @{n='Disk';e={$_.Name}}, @{n='FS';e={$_.FileSystem}},@{n='Capacity (GB)';e={'{0:N3}' -f $_.Size}},@{n='GB Free';e={'{0:N2}'-f $_.FreeSpace}}, @{n='% Free';e={'{0:N2}'-f $_.BlockSize}} -AutoSize

}

$DiskSpaceReport | Export-Csv
$DiskSpaceReport | Out-File
$DiskSpaceReport | Out-GridView</pre>
<p>&nbsp;</p>
<div data-counters='1' data-style='square' data-size='regular' data-url='http://jeffmurr.com/blog/?p=208' data-title='PowerShell for Free Space?' class='linksalpha_container linksalpha_app_3'><a href='//www.linksalpha.com/share?network='facebook' class='linksalpha_icon_facebook'></a><a href='//www.linksalpha.com/share?network='twitter' class='linksalpha_icon_twitter'></a><a href='//www.linksalpha.com/share?network='googleplus' class='linksalpha_icon_googleplus'></a><a href='//www.linksalpha.com/share?network='mail' class='linksalpha_icon_mail'></a></div><div data-position='' data-url='http://jeffmurr.com/blog/?p=208' data-title='PowerShell for Free Space?' class='linksalpha_container linksalpha_app_7'><a href='//www.linksalpha.com/share?network='facebook' class='linksalpha_icon_facebook'></a><a href='//www.linksalpha.com/share?network='twitter' class='linksalpha_icon_twitter'></a><a href='//www.linksalpha.com/share?network='googleplus' class='linksalpha_icon_googleplus'></a><a href='//www.linksalpha.com/share?network='mail' class='linksalpha_icon_mail'></a></div>
<!-- NgfbSharing::get_buttons content filter skipped: buttons not allowed in rss feeds -->
]]></content:encoded>
			<wfw:commentRss>http://jeffmurr.com/blog/?feed=rss2&#038;p=208</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>To VARCHAR or NVARCHAR? (and how it bit me using HASHBYTES)</title>
		<link>http://jeffmurr.com/blog/?p=202</link>
		<comments>http://jeffmurr.com/blog/?p=202#comments</comments>
		<pubDate>Tue, 20 Aug 2013 16:53:45 +0000</pubDate>
		<dc:creator><![CDATA[Jeff Murr]]></dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false">http://jeffmurr.com/blog/?p=202</guid>
		<description><![CDATA[The Difference The key difference between the two data types is how they&#8217;re stored. VARCHAR is stored as regular 8-bit data, NVARCHAR strings are stored in the database as UTF-16. UTF-8 (UCS Transformation Format—8-bit) is a variable-width encoding that can represent every character in the Unicode character set. It was designed for backward compatibility with [&#8230;]]]></description>
				<content:encoded><![CDATA[<h3><strong>The Difference</strong></h3>
<p>The key difference between the two data types is how they&#8217;re stored. <a href="http://technet.microsoft.com/en-us/library/ms176089.aspx">VARCHAR </a>is stored as regular 8-bit data, <a href="http://technet.microsoft.com/en-us/library/ms186939.aspx">NVARCHAR </a>strings are stored in the database as UTF-16.</p>
<p>UTF-8 (UCS Transformation Format—8-bit) is a variable-width encoding that can represent every character in the Unicode character set. It was designed for backward compatibility with ASCII and to avoid the complications of <a href="http://en.wikipedia.org/wiki/Endianness">endianness </a>and byte order marks in UTF-16 and UTF-32.</p>
<p>UTF-8 has become the dominant character encoding.  Over half of all internet pages are encoded this way, the Internet Mail Consortium (IMC) recommends that all e-mail programs be able to display and create mail using UTF-8, and UTF-8 is also increasingly being used as the default character encoding in operating systems, programming languages, APIs, and software applications.</p>
<p>UTF-8 is [or continues to be] kind of a big deal&#8230; The others, not so much anymore.</p>
<h3><strong>Storage</strong></h3>
<p>NVARCHAR strings have the same length restrictions as its VARCHAR brother — 8,000 bytes. However, since NVARCHARs use two bytes for each character, that means a given NVARCHAR can only hold 4,000 characters (<i>not</i> bytes) maximum. The amount of storage needed for NVARCHAR entities is going to be twice whatever you&#8217;d allocate for a plain old VARCHAR.  Therefore, most don&#8217;t want to use NVARCHAR universally, and may want to fall back on VARCHAR — which takes up less space per row — whenever possible.</p>
<h3><strong>How it bit me&#8230;</strong></h3>
<p>I have some data that&#8217;s MD5 hased using a C# function much like this example from <a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.md5.aspx">MSDN </a>that I needed to validate at my data layer (SQL Server 2008 R2).  However, I was getting different values that should have matched since I was providing the same intput.</p>
<p>Here&#8217;s the function using the MD5 class</p>
<pre class="brush:csharp">static string GetMd5Hash(MD5 md5Hash, string input)
        {

            // Convert the input string to a byte array and compute the hash. 
            byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));

            // Create a new Stringbuilder to collect the bytes 
            // and create a string.
            StringBuilder sBuilder = new StringBuilder();

            // Loop through each byte of the hashed data  
            // and format each one as a hexadecimal string. 
            for (int i = 0; i &lt; data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }

            // Return the hexadecimal string. 
            return sBuilder.ToString();
        }</pre>
<p>The code is storing the returned string object in a column along with some salted details for a password.  Somehow a few of the values were not syncing up with the input correctly.  To test I used input and the  <a href="http://technet.microsoft.com/en-us/library/ms174415.aspx">HASHBYTES </a>function to convert and compare to stored values with original inputs&#8217; HASED values to find the culprits.  But, what I found was nothing matched!  I went back to simple data to troubleshoot and found that I was getting different values for &#8220;FOO&#8221; from using the C# method vs. the SQL method!</p>
<p>Here&#8217;s an example:</p>
<h4>C#</h4>
<pre class="brush:csharp">MD5 md5Hash = MD5.Create();
string input = "FOO";
string results = GetMd5Hash(md5Hash, input);
#results = 901890A8E9C8CF6D5A1A542B229FEBFF</pre>
<h4>SQL</h4>
<pre class="brush:sql">DECLARE @nvarchar nvarchar(400) 

SET @nvarchar = 'FOO'

SELECT CONVERT(VARCHAR(32), HASHBYTES( 'MD5', @nvarchar ), 2)
--RESULT:  4676C8342EF52153F898C2EAAD1C528D</pre>
<h3><strong>The Problem</strong></h3>
<p>The <a href="http://technet.microsoft.com/en-us/library/ms174415.aspx">HASHBYTES </a>built-in function indicates it will take an input of varchar, nvarchar, or varbinary to be hashed.  What is easy to overlook is that <strong>the encoding of datatype matters.  </strong></p>
<p>Even though it clearly shows in the C# code and example that it is encoding to UTF-8, I didn&#8217;t catch it until after I pulled out a few remaining hairs that the encoding of the variables in storage were causing my problem.  SQL ambiguates  the conversion of nvarchar and varchar on the fly, displaying them both as unincoded strings, post conversion when you select on them.  So, the difference its transparent when inspecting the result sets.  At least that makes me &#8220;feel&#8221; like less of an idiot.</p>
<h2><strong>Solution</strong></h2>
<p>Depending on how your variable is stored within SQL will dictate the output of your hash, regardless of algorithm since the <strong>binary</strong> data presented to the function will be different per <strong>data type</strong>.</p>
<p>Therefore, if you&#8217;re wondering why your HASHED values of any encryption algorithm differ from their clear text counter parts.  Ensure your encoding of your data type is the same as the original source.</p>
<p>For a proof, play with the below and modify the datatypes of both the conversion and variables and see how encryption and hashing are always done at the byte level.</p>
<pre class="brush:sql"> DECLARE @varchar varchar(400) 
 DECLARE @nvarchar nvarchar(400) 

 SET @varchar = 'FOO'
 SET @nvarchar = 'FOO'

 SELECT CONVERT(VARCHAR(32), HASHBYTES( 'MD5', @varchar ), 2)
--RESULT:  901890A8E9C8CF6D5A1A542B229FEBFF
 SELECT CONVERT(VARCHAR(32), HASHBYTES( 'MD5', @nvarchar ), 2)
--RESULT: 4676C8342EF52153F898C2EAAD1C528D</pre>
<div data-counters='1' data-style='square' data-size='regular' data-url='http://jeffmurr.com/blog/?p=202' data-title='To VARCHAR or NVARCHAR? (and how it bit me using HASHBYTES)' class='linksalpha_container linksalpha_app_3'><a href='//www.linksalpha.com/share?network='facebook' class='linksalpha_icon_facebook'></a><a href='//www.linksalpha.com/share?network='twitter' class='linksalpha_icon_twitter'></a><a href='//www.linksalpha.com/share?network='googleplus' class='linksalpha_icon_googleplus'></a><a href='//www.linksalpha.com/share?network='mail' class='linksalpha_icon_mail'></a></div><div data-position='' data-url='http://jeffmurr.com/blog/?p=202' data-title='To VARCHAR or NVARCHAR? (and how it bit me using HASHBYTES)' class='linksalpha_container linksalpha_app_7'><a href='//www.linksalpha.com/share?network='facebook' class='linksalpha_icon_facebook'></a><a href='//www.linksalpha.com/share?network='twitter' class='linksalpha_icon_twitter'></a><a href='//www.linksalpha.com/share?network='googleplus' class='linksalpha_icon_googleplus'></a><a href='//www.linksalpha.com/share?network='mail' class='linksalpha_icon_mail'></a></div>
<!-- NgfbSharing::get_buttons content filter skipped: buttons not allowed in rss feeds -->
]]></content:encoded>
			<wfw:commentRss>http://jeffmurr.com/blog/?feed=rss2&#038;p=202</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Execute PowerShell from a ASP.NET Web Application</title>
		<link>http://jeffmurr.com/blog/?p=142</link>
		<comments>http://jeffmurr.com/blog/?p=142#comments</comments>
		<pubDate>Tue, 23 Jul 2013 03:01:56 +0000</pubDate>
		<dc:creator><![CDATA[Jeff Murr]]></dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Visual Studio 2012]]></category>

		<guid isPermaLink="false">http://jeffmurr.com/blog/?p=142</guid>
		<description><![CDATA[I had an interesting request come in to automate existing server-side PowerShell processes that have been initiated by server admins thus far locally on the server, using a web interface instead.  Turns out, the admins want to offload the work back to the business users so it can be more on demand. Essentially, they want the [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I had an interesting request come in to automate existing server-side PowerShell processes that have been initiated by server admins thus far locally on the server, using a web interface instead.  Turns out, the admins want to offload the work back to the business users so it can be more on demand. Essentially, they want the non-techies to reuse what the techies have been using server side without having to involve 1) the techies, 2) the overhead of logging in to the server, or worse 3) the business users perform PowerShell commands server side (..and therefore running the risk of executing something incorrectly and/or making a security admin&#8217;s head explode).</p>
<p>No problem.  Here&#8217;s a quick demo on how it can be done.</p>
<p>Our plan of attack will be to build a web form project using Visual Studio 2012 and .NET Framework 4.5.  It will execute server side and scripts of <a href="http://technet.microsoft.com/en-us/library/bb978526.aspx">PowerShell </a>commands using the framework&#8217;s <span style="line-height: 24px;"><a href="http://msdn.microsoft.com/en-us/library/system.management.automation.powershell(v=vs.85).aspx">PowerShell </a>class from the </span><a style="line-height: 24px;" href="http://msdn.microsoft.com/en-us/library/system.management.automation.powershell(v=vs.85).aspx">System.Management.Automation</a><span style="line-height: 24px;"> name space.  The response I&#8217;ll handle as a string, and paint it to a Text box</span></p>
<p>Here we go&#8230;</p>
<p>First, create the Empty Web Application called <strong>PowerShellExecution.</strong></p>
<p><a href="http://jeffmurr.com/blog/wp-content/uploads/2013/07/PowerShell-BlankWebApplication.png"><img class="alignnone size-medium wp-image-144" alt="PowerShell-BlankWebApplication" src="http://jeffmurr.com/blog/wp-content/uploads/2013/07/PowerShell-BlankWebApplication-300x207.png" width="300" height="207" /></a></p>
<p>Next, add a <strong>New Item&#8230;</strong> of <strong>Default web form</strong> named &#8220;<strong>Default.aspx&#8221;</strong> to the solution to align with the demo content below.</p>
<p>Now, copy and paste over the default <strong>Default.aspx</strong> code that&#8217;s generated with the below for the quick UI test:</p>
<pre class="brush:csharp">&lt;%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="PowerShellExecution.Default" %&gt;

&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;head id="Head1" runat="server"&gt;
    &lt;title&gt;&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;form id="form1" runat="server"&gt;
    &lt;div&gt;
        &lt;table&gt;
            &lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&lt;h1 align="left"&gt;PowerShell Command Harness&lt;/h1&gt;&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;PowerShell Command&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;
                &lt;br /&gt;
                &lt;/td&gt;&lt;td&gt;
                &lt;asp:TextBox ID="Input" runat="server" TextMode="MultiLine" Width="433px" Height="73px" &gt;&lt;/asp:TextBox&gt;
            &lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;
                &amp;nbsp;&lt;/td&gt;&lt;td&gt;
                &lt;asp:Button ID="ExecuteCode" runat="server" Text="Execute" Width="200" onclick="ExecuteCode_Click" /&gt;
            &lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&lt;h3&gt;Result&lt;/h3&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;
                    &amp;nbsp;&lt;/td&gt;&lt;td&gt;
                    &lt;asp:TextBox ID="ResultBox" TextMode="MultiLine" Width="700" Height="200" runat="server"&gt;&lt;/asp:TextBox&gt;
                &lt;/td&gt;&lt;/tr&gt;
        &lt;/table&gt;
    &lt;/div&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Next, to get the <a href="http://msdn.microsoft.com/en-us/library/system.management.automation.powershell(v=vs.85).aspx">System.Management.Automation</a> name space included in our solution we need to install the System.Mangement.Automation package.  To do that, under the <strong>Tools</strong> menu select<strong> Library Package Manager</strong> &gt;&gt;<strong> Package Manager Console</strong></p>
<p><a href="http://jeffmurr.com/blog/wp-content/uploads/2013/07/PowerShell-VisualStudioLibraryPackage.png"><img class="alignnone size-medium wp-image-143" alt="PowerShell-VisualStudioLibraryPackage" src="http://jeffmurr.com/blog/wp-content/uploads/2013/07/PowerShell-VisualStudioLibraryPackage-300x198.png" width="300" height="198" /></a></p>
<p>&#8230;within the <strong>Package Manager Console</strong> execute &#8220;<strong>Install-Package System.Management.Automation&#8221;</strong></p>
<p><a href="http://jeffmurr.com/blog/wp-content/uploads/2013/07/PowerShell-NuGet.png"><img class="alignnone size-medium wp-image-145" alt="PowerShell-NuGet" src="http://jeffmurr.com/blog/wp-content/uploads/2013/07/PowerShell-NuGet-300x37.png" width="300" height="37" /></a></p>
<p>After a successful execution of that package install, you&#8217;ll want to add the reference to your <strong>Default.aspx.cs</strong> file:</p>
<pre class="brush:csharp">using System.Management.Automation;</pre>
<p>I&#8217;m going to use a button&#8217;s onclick action to invoke the method that will perform the magic of submitting and reading the response from my PowerShell.  The remaining item to address, that may vary on your circumstance, is how to handle the response from the PowerShell.</p>
<p>Remember, everything in PowerShell is returned as an object.  We need to display our object back on the page as a string for this demo.  You&#8217;ll need to be mindful of that when executing, as well as how or what you&#8217;re wanting your results displayed on the page.</p>
<p>To ensure that happens for me, I am going manage the output of my PowerShell execution by building a string out of the objects returned.  I&#8217;ll paint those string casted results in a TextBox control called &#8220;ResultBox&#8221; using the <a href="http://msdn.microsoft.com/en-us/library/system.text.stringbuilder.aspx">StringBuilder</a> class within in the <a href="http://msdn.microsoft.com/en-us/library/System.Text.aspx">System.Text</a> name space.  Therefore, I need to reference that name space as well in my code behind.</p>
<pre class="brush:csharp">using System.Text;</pre>
<p>Below is my complete <strong>Default.aspx.cs</strong> code for the purposes of this demo.  It includes the above references  I discussed, the default page load, and especially the onclick method to support the execution details submitted to the Input control using the PowerShell class.</p>
<p>I sprinkled in comments for context:</p>
<pre class="brush:csharp">using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Management.Automation;
using System.Text;

namespace PowerShellExecution
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void ExecuteCode_Click(object sender, EventArgs e)
        {
            // Clean the Result TextBox
            ResultBox.Text = string.Empty;

            // Initialize PowerShell engine
            var shell = PowerShell.Create();

            // Add the script to the PowerShell object
            shell.Commands.AddScript(Input.Text);

            // Execute the script
            var results = shell.Invoke();

            // display results, with BaseObject converted to string
            // Note : use |out-string for console-like output
            if (results.Count &gt; 0)
            {
                // We use a string builder ton create our result text
                var builder = new StringBuilder();

                foreach (var psObject in results)
                {
                    // Convert the Base Object to a string and append it to the string builder.
                    // Add \r\n for line breaks
                    builder.Append(psObject.BaseObject.ToString() + "\r\n");
                }

                // Encode the string in HTML (prevent security issue with 'dangerous' caracters like &lt; &gt;
                ResultBox.Text = Server.HtmlEncode(builder.ToString());
            }
        }
    }
}</pre>
<p>Copy and paste that in and you&#8217;re ready to test&#8230;</p>
<p>Once rendered in your browser, type into the &#8220;PowerShell Command&#8221; window <strong>Get-Service | Out-String </strong>(or your favorite cmdlet for a test).</p>
<p><a href="http://jeffmurr.com/blog/wp-content/uploads/2013/07/UITest.png"><img class="alignnone size-medium wp-image-150" alt="UITest" src="http://jeffmurr.com/blog/wp-content/uploads/2013/07/UITest-300x170.png" width="300" height="170" /></a></p>
<p>Remember, port everything to the <strong>Out-String</strong> cmdlet so it can be handled properly by the StringBuilder class.  Otherwise, you&#8217;ll get stringbuilder output of the data type details of the objects returned by your cmdlet &#8211; one long get-member call, most likely not what you&#8217;re after.</p>
<p>If you&#8217;re wondering if you can run scripts that are on the local file system of the server, the answer is <strong>yes.  </strong>Simply pass the script location an parameters in string form to the <strong>AddScript()</strong> method within <strong>Default.aspx.cs</strong> using double slashes format.</p>
<pre class="brush:csharp">//shell.Commands.AddScript(Input.Text);
shell.Commands.AddScript("C:\\Scripts\\PowerShell\\PowerShellScript.ps1");</pre>
<p>Contents of this test <strong>PowerShellScript.ps1</strong> (same as what was used in the Input control):</p>
<pre class="brush:powershell">Get-Service | Out-String</pre>
<p>(I removed the Input box control and test again the solution below)</p>
<p><a href="http://jeffmurr.com/blog/wp-content/uploads/2013/07/UITest1.png"><img class="alignnone size-medium wp-image-151" alt="UITest" src="http://jeffmurr.com/blog/wp-content/uploads/2013/07/UITest1-300x170.png" width="300" height="170" /></a></p>
<p><strong>Note:</strong> To run this on a server, the ApplicationPool hosting your application will have to have administrator rights.</p>
<p>There you have it, a quick server side PowerShell web method.</p>
<p>&nbsp;</p>
<div data-counters='1' data-style='square' data-size='regular' data-url='http://jeffmurr.com/blog/?p=142' data-title='Execute PowerShell from a ASP.NET Web Application' class='linksalpha_container linksalpha_app_3'><a href='//www.linksalpha.com/share?network='facebook' class='linksalpha_icon_facebook'></a><a href='//www.linksalpha.com/share?network='twitter' class='linksalpha_icon_twitter'></a><a href='//www.linksalpha.com/share?network='googleplus' class='linksalpha_icon_googleplus'></a><a href='//www.linksalpha.com/share?network='mail' class='linksalpha_icon_mail'></a></div><div data-position='' data-url='http://jeffmurr.com/blog/?p=142' data-title='Execute PowerShell from a ASP.NET Web Application' class='linksalpha_container linksalpha_app_7'><a href='//www.linksalpha.com/share?network='facebook' class='linksalpha_icon_facebook'></a><a href='//www.linksalpha.com/share?network='twitter' class='linksalpha_icon_twitter'></a><a href='//www.linksalpha.com/share?network='googleplus' class='linksalpha_icon_googleplus'></a><a href='//www.linksalpha.com/share?network='mail' class='linksalpha_icon_mail'></a></div>
<!-- NgfbSharing::get_buttons content filter skipped: buttons not allowed in rss feeds -->
]]></content:encoded>
			<wfw:commentRss>http://jeffmurr.com/blog/?feed=rss2&#038;p=142</wfw:commentRss>
		<slash:comments>92</slash:comments>
		</item>
		<item>
		<title>HTTP Error 500.19 &#8220;Failed to decrypt attribute &#8220;password&#8221;&#8221;</title>
		<link>http://jeffmurr.com/blog/?p=77</link>
		<comments>http://jeffmurr.com/blog/?p=77#comments</comments>
		<pubDate>Sat, 16 Feb 2013 19:45:22 +0000</pubDate>
		<dc:creator><![CDATA[Jeff Murr]]></dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[IIS]]></category>
		<category><![CDATA[IIS 6]]></category>
		<category><![CDATA[IIS 7]]></category>
		<category><![CDATA[Regisrty]]></category>

		<guid isPermaLink="false">http://jeffmurr.com/blog/?p=77</guid>
		<description><![CDATA[Background Important information within IIS is stored in flat files with encrypted sections.  The specific sections encrypted are identity of the application pool along with ACL information.  When you move the configurations to a new server, or when you&#8217;ve used a hypervisor to clone a server, keys used to decrypt these values will no longer work.  Or more specifically, [&#8230;]]]></description>
				<content:encoded><![CDATA[<h3><strong><big>Background</big></strong></h3>
<p>Important information within IIS is stored in flat files with encrypted sections.  The specific sections encrypted are identity of the application pool along with ACL information.  When you move the configurations to a new server, or when you&#8217;ve used a hypervisor to clone a server, keys used to decrypt these values will no longer work.  Or more specifically, they&#8217;re not found&#8230;I&#8217;ll get to that (the fourth solution to this problem explains it all).</p>
<p><a href="http://jeffmurr.com/blog/wp-content/uploads/2013/02/500.19Error1.png"><img class="alignnone size-full wp-image-108" alt="500.19Error" src="http://jeffmurr.com/blog/wp-content/uploads/2013/02/500.19Error1.png" width="249" height="293" /></a></p>
<p>The 500 primary error means it is a server error. The .19 secondary error code indicates that &#8220;The requested page can not be accessed because the related configuration data is invalid.&#8221; IIS, points out that the issue is due to its inability to decrypt an attribute of a configuration file for us. <a href="http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/a0ea8e51-fb2a-4e80-9d5a-7fe3ae246570.mspx?mfr=true" target="_blank">Metabase.xml</a> is the central store where IIS 6.0 stores most of its configuration information.  In IIS 7.0 Microsoft shifted to a new XML based configuration store that is modeled after ASP.NET.  The same model is maintained in IIS 7.5.  IIS no longer centralized into a single file. The hierarchical store starts with the <a href="http://technet.microsoft.com/en-us/library/cc753369(v=WS.10).aspx" target="_blank">applicationHost.config</a> file and can be distributed among web.config files under your application for a more modular inheritance  exposed through the app.configs (web.config).</p>
<p>In IIS 7 the local accounts and groups that IIS 6.0 used (IUSR_MACHINENAME / IIS_WPG) were also replaced by built-in accounts (IUSR / IIS_IUSRS). The built-in accounts have the same SID across Windows 2008/2008 R2 servers and are not machine specific.  The idea is that, like web applications&#8217; configurations, you should be able to have an IIS configuration that could be machine independent.  Therefore, like web.configs, you should be able to just <a href="http://technet.microsoft.com/en-us/library/cc770873(v=ws.10).aspx" target="_blank">copy </a>your <a href="http://technet.microsoft.com/en-us/library/cc753369(v=WS.10).aspx" target="_blank">applicationHost.config</a><strong> </strong>from one server to another and IIS will pick up the settings and work.</p>
<h3><strong><big>Problem</big></strong></h3>
<p>This all works perfectly, if you don&#8217;t care about the identity your application runs under.  In a distributed environment this isn&#8217;t always the case.  If you modify the identity of your application pool servicing your application hosted in IIS, then move the <a href="http://technet.microsoft.com/en-us/library/cc753369(v=WS.10).aspx" target="_blank">applicationHost.config</a> to a different IIS 7.0 server, or <strong>clone</strong> it you&#8217;re greeted with this error when trying to render a page, web service, or worse a failure of application pools with an error from WAS in your event log looking like this:</p>
<blockquote><p>Application pool &lt;ApplicationPool&gt; has been disabled. Windows Process Activation Service (WAS) did not create a worker process to serve the application pool because the application pool identity is invalid.</p></blockquote>
<p>If you try to modify the account, depending on how you installed the application  you may not be able to change the password and &#8220;reset&#8221; this problem away that&#8217;s truly a the mismatch of identity on multiple levels.</p>
<p>This issues results in this error:</p>
<blockquote><p>There was an error while performing this operation.  Details: Bad Data. (Exception from HRESULT: 0&#215;80090005)</p></blockquote>
<p>It is rooted in the inability to decrypt the sections of the <a href="http://technet.microsoft.com/en-us/library/cc753369(v=WS.10).aspx" target="_blank">applicationHost.config</a><strong> </strong>that&#8217;s encrypted with machine keys.  Any custom username / password tried for the identity of the application pool may result in either of these error conditions.  A work around is to set application pool to one of the built in accounts works or remove the encryption in the configuration file.  Both not that great of solutions if you need some level of identity on a remote system or security by encrypting this sensitive data at rest, as it should be.</p>
<p>The issue is with your machine keys used to decrypt sections of your <a href="http://technet.microsoft.com/en-us/library/cc753369(v=WS.10).aspx" target="_blank">applicationHost.config</a><strong>.  </strong>For example, IIS keeps a local copy of the username and password of a custom identity in the <a href="http://technet.microsoft.com/en-us/library/cc753369(v=WS.10).aspx" target="_blank">applicationHost.config</a><strong> </strong>and and encrypts it.  If you open the file you&#8217;ll see this:</p>
<p><code>&lt;processModel identityType="User" userName="domain\username" password="[enc:IISWASOnlyAesProvider:2Woq1bHFmcDxzSEKLe9q1eZsvlUuBcmb0Luy3DzkZWg=:enc]" /&gt;</code></p>
<p>When the <a href="http://technet.microsoft.com/en-us/library/cc753369(v=WS.10).aspx" target="_blank">applicationHost.config</a><strong> </strong>is used on a server it didn&#8217;t originate on,  IIS can no longer decrypt the <a href="http://www.iis.net/configreference">iisConfiguration </a>and <a href="http://www.iis.net/configreference">iisWasKey </a>containers in this file since it uses the original machine keys to do they encryption.</p>
<h2><strong><big>Solutions<big></big></big></strong></h2>
<p>To get this working you have four options, in order of suggested implementation.  The first requires<em><strong> A </strong><strong>working </strong></em>server with a similar configuration, the second requires <span style="color: #000000;"><b><i>THE  actual </i></b></span>source server, the third is down right insecure, the fourth I would challenge that anyone should use &#8211; but works, and is important to understanding the under pinning of what&#8217;s going on.</p>
<p>The first three are supported methods by Microsoft documentation, the fourth isn&#8217;t &#8211; and with all, take proper precautions.</p>
<h3><strong><em>First one (best/easiest)&#8230;</em></strong></h3>
<p>Export the IIS config of a working web server and import using the <a href="http://www.iis.net/learn/manage/managing-your-configuration-settings/shared-configuration_264" target="_blank">Shared Configuration</a> of IIS 7.</p>
<p>1. Navigate to the root of you server in IIS admin console<br />
2. Double click shared Configuration</p>
<p><a href="http://jeffmurr.com/blog/wp-content/uploads/2013/02/IISRoot.png"><img alt="IISRoot" src="http://jeffmurr.com/blog/wp-content/uploads/2013/02/IISRoot-300x168.png" width="300" height="168" /></a></p>
<p>3. Click Export Configuration on the left hand pane</p>
<p><a href="http://jeffmurr.com/blog/wp-content/uploads/2013/02/ExportConfig.png"><img alt="ExportConfig" src="http://jeffmurr.com/blog/wp-content/uploads/2013/02/ExportConfig.png" width="153" height="120" /></a></p>
<p>4. Select a location<br />
5. Select a Password<br />
6. And Select OK</p>
<p><a href="http://jeffmurr.com/blog/wp-content/uploads/2013/02/6Password.png"><img alt="6Password" src="http://jeffmurr.com/blog/wp-content/uploads/2013/02/6Password.png" width="220" height="120" /></a></p>
<p>7. This process creates files to be imported on target machine<br />
8. Move the files to a location on the target server<br />
9. In Shared Configuration manager on the target machine check the Enable Shared Configuration and select Apply</p>
<p><a href="http://jeffmurr.com/blog/wp-content/uploads/2013/02/SharedConfig.png"><img alt="SharedConfig" src="http://jeffmurr.com/blog/wp-content/uploads/2013/02/SharedConfig-300x51.png" width="300" height="51" /></a></p>
<p>10. Enter the password when prompted<br />
11. Ok to the follow couple of prompts<br />
12. IISReset<br />
13. Navigate to your resource to confirm it renders (no longer an 500.19 error)</p>
<p><a href="http://jeffmurr.com/blog/wp-content/uploads/2013/02/ServiceWSDLIIS.png"><img alt="ServiceWSDLIIS" src="http://jeffmurr.com/blog/wp-content/uploads/2013/02/ServiceWSDLIIS.png" width="153" height="120" /></a></p>
<p>14. In Shared Configuration manager on the target machine un-check the Enable <a href="http://www.iis.net/learn/manage/managing-your-configuration-settings/shared-configuration_264" target="_blank">Shared Configuration</a> and select Apply<br />
15. Select yes to overwrite</p>
<p><a href="http://jeffmurr.com/blog/wp-content/uploads/2013/02/Confirm.png"><img alt="Confirm" src="http://jeffmurr.com/blog/wp-content/uploads/2013/02/Confirm-300x161.png" width="300" height="161" /></a></p>
<p>16. Yes when prompted to IISReset<br />
17. Perform IISReset</p>
<p>&nbsp;</p>
<h3><strong><em>Second (easy)&#8230;</em></strong></h3>
<p>Export keys from source server:</p>
<div>
<pre class="brush:shell">aspnet_regiis -px "iisConfigurationKey" "C:\IISKEY\iisConfigurationKey.xml" -pri
aspnet_regiis -px "iisWasKey" "C:\IISKEY\iisWasKey.xml" -pri</pre>
</div>
<p>Import on your target/problem server:</p>
<div>
<pre class="brush:shell">aspnet_regiis -pi "iisConfigurationKey" "C:\IISKEY\iisConfigurationKey.xml"
aspnet_regiis -pi "iisWasKey" "C:\IISKEY\iisWasKey.xml"</pre>
<p>&nbsp;</p>
<h3><b><i>Third</i></b><strong><em> one (work intensive/insecure)  </em></strong></h3>
<p>Remove the encryption tags in the <a href="http://technet.microsoft.com/en-us/library/cc753369(v=WS.10).aspx" target="_blank">applicationHost.config</a><strong>.  </strong>Depending on how big your problem is this may be extensive work.</p>
<p>Open your <a href="http://technet.microsoft.com/en-us/library/cc753369(v=WS.10).aspx" target="_blank">applicationHost.config</a> in %windir%\system32\inetsrv\config and search for &#8220;<em>[enc:</em>&#8221; and put the configurations that are encrypted in the file in clear text.</p>
<p>Example Before:</p>
<p><code>&lt;processModel identityType="User" userName="domain\username" password="[enc:IISWASOnlyAesProvider:2Woq1bHFmcDxzSEKLe9q1eZsvlUuBcmb0Luy3DzkZWg=:enc]" /&gt;</code></p>
<p>Example After:</p>
<p><code>&lt;processModel identityType="User" userName="domain\username" password="UserNamesPasswordInClearText" /&gt;</code></p>
<p>&nbsp;</p>
<p><strong><em>The Fourth, (absolutely crazy, but explains what&#8217;s really going on on the file system)&#8230;</em></strong></p>
<p>Modify your <strong>MahineGuid</strong> to match your keys needed to decrypt.</p>
<p>This is pretty aggressive and I would suggest this only as an academic exercise in figuring out the inner workings of the RSA suite and usage within the Windows OS.  But <strong>explains what&#8217;s really going on</strong>.  I&#8217;m not comfortable suggesting any use this as a policy since I can find no documentation on Microsoft&#8217;s site to support its validity; but, it was something I spent a good amount of time on and it worked, I&#8217;d hate to not post the findings.  It also gives you the whole story of the problem.</p>
<p>In <strong>C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys</strong> are all of your private keys.  The appropriate key is called up by an application needing the machine key portion by a <strong>MachineGuid</strong> registry key.  When xcopy-ing or cloning your flat files no longer match your <strong>MachineGuid</strong> nested in the registry.</p>
<p><strong>So, your inability to decrypt is actually rooted in your inability to find the key required to do the decryption!</strong></p>
<p>The naming convention of all of the keys stored in this location is &lt;KEYGUID&gt;_&lt;MACHINEGUID&gt;.  If you flip the <strong>MachineGuid</strong> in <strong>HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography </strong>to match the suffix of the keys stored in <strong>C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys </strong>IIS will start referencing the previous certificates and IIS will be able to decrypt the password sections again.</p>
<p><em id="__mceDel"><a href="http://jeffmurr.com/blog/wp-content/uploads/2013/02/RSAKeys.png"><img class="alignnone size-medium wp-image-86" alt="RSAKeys" src="http://jeffmurr.com/blog/wp-content/uploads/2013/02/RSAKeys-300x102.png" width="300" height="102" /></a></em></p>
<p>Extensive testing was not done on this solution so again, proceed with caution.  Only a cool trick in my book, no telling what else this could break along the way.  You will notice however, both of the other solutions in this post create *new* keys in this location with the correct <strong>MachineGuid</strong>, so a good troubleshooting skill and confirmation technique to store away for future use.</p>
<p>&nbsp;</p>
</div>
<div data-counters='1' data-style='square' data-size='regular' data-url='http://jeffmurr.com/blog/?p=77' data-title='HTTP Error 500.19 &#8220;Failed to decrypt attribute &#8220;password&#8221;&#8221;' class='linksalpha_container linksalpha_app_3'><a href='//www.linksalpha.com/share?network='facebook' class='linksalpha_icon_facebook'></a><a href='//www.linksalpha.com/share?network='twitter' class='linksalpha_icon_twitter'></a><a href='//www.linksalpha.com/share?network='googleplus' class='linksalpha_icon_googleplus'></a><a href='//www.linksalpha.com/share?network='mail' class='linksalpha_icon_mail'></a></div><div data-position='' data-url='http://jeffmurr.com/blog/?p=77' data-title='HTTP Error 500.19 &#8220;Failed to decrypt attribute &#8220;password&#8221;&#8221;' class='linksalpha_container linksalpha_app_7'><a href='//www.linksalpha.com/share?network='facebook' class='linksalpha_icon_facebook'></a><a href='//www.linksalpha.com/share?network='twitter' class='linksalpha_icon_twitter'></a><a href='//www.linksalpha.com/share?network='googleplus' class='linksalpha_icon_googleplus'></a><a href='//www.linksalpha.com/share?network='mail' class='linksalpha_icon_mail'></a></div>
<!-- NgfbSharing::get_buttons content filter skipped: buttons not allowed in rss feeds -->
]]></content:encoded>
			<wfw:commentRss>http://jeffmurr.com/blog/?feed=rss2&#038;p=77</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>&#8220;Unable to load one or more of the requested types.&#8221;</title>
		<link>http://jeffmurr.com/blog/?p=55</link>
		<comments>http://jeffmurr.com/blog/?p=55#comments</comments>
		<pubDate>Wed, 30 Jan 2013 04:06:17 +0000</pubDate>
		<dc:creator><![CDATA[Jeff Murr]]></dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[IIS]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[IIS 7]]></category>

		<guid isPermaLink="false">http://jeffmurr.com/blog/?p=55</guid>
		<description><![CDATA[This annoying exception greeted me this morning&#8230; Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: System.Reflection.ReflectionTypeLoadException: Unable to load [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>This annoying exception greeted me this morning&#8230;</p>
<p><a href="http://jeffmurr.com/blog/wp-content/uploads/2013/01/LoaderError1.png"><img class="alignnone size-medium wp-image-70" alt="LoaderError" src="http://jeffmurr.com/blog/wp-content/uploads/2013/01/LoaderError1-300x100.png" width="300" height="100" /></a></p>
<blockquote><p>Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.</p>
<p>Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.</p>
<p>Exception Details: System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.</p></blockquote>
<p>It occurs when an assembly type was not able to load properly during the start-up of your application hosted in IIS.  Specifically, when a dependency is missing.  Depending on when the error occurs in the compile of your solution, you may not get a good error in IIS failed request trace, IIS logs proper (a simple 500 result is logged), or any extended logging assemblies you have included in your solution since the error very well could occur before those logging logic libraries have included/loaded.</p>
<p>To correct it you need to find the missing dependency.  To find that missing dependency you can stage an add of all binaries using PowerShell.  Specifically, all by a <a href="http://technet.microsoft.com/library/hh849800.aspx">Get-ChildItem</a>, that you can properly filter by name as needed, one by one in a &#8220;foreach&#8221; loop using the <a href="http://technet.microsoft.com/en-us/library/hh849914">Add-Type </a>cmdlet to stage the same .NET load performed at start-up   You can closely inspect the details of the exception raised during the load of each to find any missing dependencies.  Specifically, inspect the <a href="http://msdn.microsoft.com/en-us/library/system.reflection.reflectiontypeloadexception.loaderexceptions.aspx">LoaderExceptions</a> property that holds the I/O details holding the &#8220;file not found&#8221; error [like the error message in IIS suggests].</p>
<p>Here&#8217;s a quick script snippet.  Modify the file location of your binary folder and/or your gci filter as needed:</p>
<pre class="brush:powershell">$BinPath = "D:\Webroot\wwwroot\bin"
  try
  {
    $Error.Clear()
    Push-Location $BinPath
    Get-ChildItem "*.dll" | Foreach {
	Write-Host $_.Name;
        $assembly = Add-Type -Path $_.FullName;    
    }
  }
  catch 
  {
    Write-Host -foreground yellow "LoadException";
    $Error | format-list -force
    Write-Host -foreground red $Error[0].Exception.LoaderExceptions;
  }

Write-Host "Complete."
Pop-Location</pre>
<div data-counters='1' data-style='square' data-size='regular' data-url='http://jeffmurr.com/blog/?p=55' data-title='&#8220;Unable to load one or more of the requested types.&#8221;' class='linksalpha_container linksalpha_app_3'><a href='//www.linksalpha.com/share?network='facebook' class='linksalpha_icon_facebook'></a><a href='//www.linksalpha.com/share?network='twitter' class='linksalpha_icon_twitter'></a><a href='//www.linksalpha.com/share?network='googleplus' class='linksalpha_icon_googleplus'></a><a href='//www.linksalpha.com/share?network='mail' class='linksalpha_icon_mail'></a></div><div data-position='' data-url='http://jeffmurr.com/blog/?p=55' data-title='&#8220;Unable to load one or more of the requested types.&#8221;' class='linksalpha_container linksalpha_app_7'><a href='//www.linksalpha.com/share?network='facebook' class='linksalpha_icon_facebook'></a><a href='//www.linksalpha.com/share?network='twitter' class='linksalpha_icon_twitter'></a><a href='//www.linksalpha.com/share?network='googleplus' class='linksalpha_icon_googleplus'></a><a href='//www.linksalpha.com/share?network='mail' class='linksalpha_icon_mail'></a></div>
<!-- NgfbSharing::get_buttons content filter skipped: buttons not allowed in rss feeds -->
]]></content:encoded>
			<wfw:commentRss>http://jeffmurr.com/blog/?feed=rss2&#038;p=55</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
