<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Omar AL Zabir blog on ASP.NET Ajax and .NET 3.5 : powershell</title><link>http://msmvps.com/blogs/omar/archive/tags/powershell/default.aspx</link><description>Tags: powershell</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Reduce website download time by heavily compressing PNG and JPEG</title><link>http://msmvps.com/blogs/omar/archive/2008/04/07/reduce-website-download-time-by-heavily-compressing-png-and-jpeg.aspx</link><pubDate>Mon, 07 Apr 2008 13:17:47 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1576733</guid><dc:creator>omar</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1576733</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2008/04/07/reduce-website-download-time-by-heavily-compressing-png-and-jpeg.aspx#comments</comments><description>&lt;p&gt;PNG and JPEG are two most popular formats for web graphics. JPEG is used for photographs, screenshots and backgrounds where PNG is used for all other graphics need including cliparts, buttons, headers, footers, borders and so on. As a result, these two types of graphics file usually take up 80% of the total graphics used in a website. Of course, there&amp;#39;s the GIF, which is very popular. But as it supports only 256 colors, it is losing its popularity day by day. PNG seems to be a all rounder winner for all kinds of graphics need. As all browsers support PNG well enough and PNG supports alpha transparency, it&amp;#39;s surely the best format so far on the web for all purpose graphics need for websites. So, if you can optimize all PNG and JPEG on your website and compress them rigorously, you can easily shed off several seconds of load time from your website without doing any coding. Especially if your website is graphics rich like &lt;a href="http://www.pageflakes.com"&gt;Pageflakes&lt;/a&gt;, 30% reduction in total size of graphics throughout the website is a big performance win.&lt;/p&gt; &lt;h3&gt;&lt;/h3&gt; &lt;h3&gt;Optimize all PNG on your website&lt;/h3&gt; &lt;p&gt;PNG has a lot of scope for optimization. Generally regular graphics tools like Photoshop, Paintshop pro, Paint.NET all generate PNG using a moderate compression. So, PNG can be compressed further by using advanced compression tools. &lt;a href="http://en.wikipedia.org/wiki/OptiPNG"&gt;OptiPNG&lt;/a&gt; is such a tool that can compress PNG and sometimes produce 50% smaller output. At Pageflakes, we have around 380 PNG which when compressed using OptiPNG, gives us 40% reduction in total size. This is a big win for us.&lt;/p&gt; &lt;p&gt;Here&amp;#39;s what wikipedia says about OptiPNG:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;OptiPNG is an open source command line computer program that reduces the size of PNG files. The compression is lossless, meaning that the resulting image will have exactly the same appearance as the source image.  &lt;p&gt;The main purpose of OptiPNG is to reduce the size of the PNG IDAT data stream by trying various filtering and compression methods. It also performs automatic bit depth, color type and color palette reduction where possible, and can correct some data integrity errors in input files.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Here&amp;#39;s a poweshell script that you can run from the root folder of your website. It will scan through all the PNG files in the webtree and run OptiPNG on each file. This takes quite some time if you have hundreds of files. So, you should make it a part of your build script.&lt;/p&gt;&lt;pre class="csharpcode"&gt;gci -include *.png -recurse | &lt;span class="kwrd"&gt;foreach&lt;/span&gt;
 { $fileName = $_.FullName; cmd /c &amp;quot;C:\soft\png\optipng.exe -o7 `&amp;quot;&lt;span class="str"&gt;$fileName`&amp;quot;&amp;quot;&lt;/span&gt; }&lt;/pre&gt;
&lt;p&gt;Here I have stored the optipng.exe on the c:\soft\png folder.&lt;/p&gt;
&lt;p&gt;OptiPNG gives very good compression. But there&amp;#39;s even more scope for compression. &lt;a href="http://en.wikipedia.org/wiki/AdvanceCOMP"&gt;AdvanceCOMP&lt;/a&gt; is the ultimate in compression technology for PNG as it uses the mighty &lt;a href="http://www.7-zip.org/"&gt;7zip&lt;/a&gt; compression algorithm. It can squeeze down PNG even further after being compressed by OptiPNG using its maximum compression mode. PNG files are compressed using DEFLATE algorithm. DEFLATE has 0 to 9 compression level, where 9 is the highest. AdvanceCOMP uses 7zip DEFLATE encoder, that extends the compression factor even more. During 7zip compression, a much more detailed search of compression possibilities is performed, at the expense of significant further processor time spent on searching. Effectively, the 10-point scale used in gzip is extended to include extra settings above 9, the previous maximum search level. There will be no difference in decompression speed, regardless of the level of compressed size achieved or time taken to encode the data.&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s a poweshell script that you can run from the root folder of your website. It will scan through all the PNG files in the webtree and run AdvanceCOMP on each file. You need to run AdvanceCOMP after running OptiPNG.&lt;/p&gt;&lt;pre class="csharpcode"&gt;gci -include *.png -recurse | &lt;span class="kwrd"&gt;foreach&lt;/span&gt;
 { $fileName = $_.FullName; cmd /c &lt;span class="str"&gt;&amp;quot;C:\soft\png\advpng.exe 
 --shrink-insane -z `&amp;quot;&lt;/span&gt;$fileName`&lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt; }&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I have collected &lt;a href="http://omar.mvps.org/tool/png.zip"&gt;both optipng and advpng in this zip&lt;/a&gt; file.&lt;/p&gt;
&lt;h3&gt;Optimize all JPEG on your website&lt;/h3&gt;
&lt;p&gt;Unfortunately, there&amp;#39;s not much powerful tool like OptiPNG for jpeg that you can run on all your jpeg files and compress them rigorously. JPEG file is compressed when it is saved. Generally all graphics applications provide you an option to select what&amp;#39;s the quality ratio of the jpeg being saved. So, you have to consciously make the best compression vs quality choice while saving the jpeg file. However, &lt;a href="http://en.wikipedia.org/wiki/Libjpeg"&gt;libjpeg&lt;/a&gt; project has a jpeg optimizer tool that does some optimization on jpeg files. It has a jpegtran utility which does the optimization according to wikipedia:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;jpegtran - a utility for lossless transcoding between different JPEG formats. The jpegtran command-line program is useful to optimize the compression of a JPEG file, convert between progressive and non-progressive JPEG formats, eliminate non-standard application-specific data inserted by some image programs, or to perform certain transformations on a file — such as grayscaling, or rotating and flipping (within certain limits) — all done &amp;quot;losslessly&amp;quot; (i.e. without decompressing and recompressing the data, and so causing a reduction of image quality due to generation loss).&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;However, when we ran jpegtran on all the jpeg files in Pageflakes, we are able to reduce about 20% total size of all jpeg. So, that was not too bad. &lt;/p&gt;
&lt;p&gt;Here&amp;#39;s how you run jpegtran to get all the jpeg files within your website directory optimized:&lt;/p&gt;&lt;pre class="csharpcode"&gt;gci -include *.jpg -recurse | &lt;span class="kwrd"&gt;foreach&lt;/span&gt;
 { $fileName = $_.FullName; $newFileName = $fileName + &lt;span class="str"&gt;&amp;quot;.tmp&amp;quot;&lt;/span&gt;; 
cmd /c &lt;span class="str"&gt;&amp;quot;C:\soft\jpeg\jpegtran.exe -optimize -outfile `&amp;quot;&lt;/span&gt;$newFileName`&lt;span class="str"&gt;&amp;quot; `&amp;quot;&lt;/span&gt;$fileName`&lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;; 
copy $newFileName $fileName; del $newFileName; }&lt;/pre&gt;
&lt;p&gt;The &lt;a href="http://omar.mvps.org/tool/jpeg.zip"&gt;libjpeg binaries are uploaded here&lt;/a&gt; for your convenience.&lt;/p&gt;
&lt;p&gt;Warning: You have to run all these powershell commands in a single line. I have broken the commands in multiple line for better readability.&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s save global bandwidth, go green.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1576733" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/performance/default.aspx">performance</category><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/production/default.aspx">production</category><category domain="http://msmvps.com/blogs/omar/archive/tags/powershell/default.aspx">powershell</category><category domain="http://msmvps.com/blogs/omar/archive/tags/compress/default.aspx">compress</category><category domain="http://msmvps.com/blogs/omar/archive/tags/optimize/default.aspx">optimize</category><category domain="http://msmvps.com/blogs/omar/archive/tags/jpeg/default.aspx">jpeg</category><category domain="http://msmvps.com/blogs/omar/archive/tags/png/default.aspx">png</category></item><item><title>Automate website deployment using Powershell</title><link>http://msmvps.com/blogs/omar/archive/2006/12/15/automate-website-deployment-using-powershell.aspx</link><pubDate>Fri, 15 Dec 2006 08:58:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:422924</guid><dc:creator>omar</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=422924</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2006/12/15/automate-website-deployment-using-powershell.aspx#comments</comments><description>&lt;p&gt;I published an article which automates website deployment.&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.codeproject.com/KB/install/DeploySite.aspx"&gt;http://www.codeproject.com/dotnet/DeploySite.asp&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;The Powershell script does the following for you:&lt;/p&gt;
&lt;p&gt;&amp;middot; Maintains different configuration information for
different deployments. For example, different connection strings
for development servers and production servers (one or more
production servers).&lt;/p&gt;
&lt;p&gt;&amp;middot; Creates a deployment folder using the deployment date,
time, and version so that you have a separate folder for each
deployment and can keep track of things deployed on a day, e.g.,
20061214-1.&lt;/p&gt;
&lt;p&gt;&amp;middot; Copies only the change files and some predefined files
to the deployment folder. So, you don&amp;#39;t deploy the whole website
every day.&lt;/p&gt;
&lt;p&gt;&amp;middot; Copies the web.config and customizes the
&amp;lt;appSettings&amp;gt;, &amp;lt;connectionString&amp;gt;, &amp;lt;assemblies&amp;gt;
etc., as per the deployment configuration. For example, you can
have different connection strings for different servers.&lt;/p&gt;
&lt;p&gt;&amp;middot; Updates all JavaScript files with a version number so
that in every deployment, a new file gets downloaded by client
browsers.&lt;/p&gt;
&lt;p&gt;&amp;middot; Updates default.aspx automatically with the modified
script file name.&lt;/p&gt;
&lt;p&gt;&amp;middot; Compresses all JavaScript files that gets deployed.&lt;/p&gt;
&lt;p&gt;&amp;middot; Compresses all static HTML files using an Absolute HTML
Optimizer.&lt;/p&gt;
&lt;p&gt;&amp;middot; Creates a zip file which contains the deployment
package.&lt;/p&gt;
&lt;p&gt;&amp;middot; FTP the zip file to a target server.&lt;/p&gt;
&lt;p&gt;So all you need to do is, run the script, extract the zip on
server and voila!&lt;/p&gt;
&lt;p&gt;If you like it, please vote for me.&lt;/p&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=422924" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/powershell/default.aspx">powershell</category></item><item><title>Generate Javascript string from HTML using Power Shell script</title><link>http://msmvps.com/blogs/omar/archive/2006/08/06/generate-javascript-string-from-html-using-power-shell-script.aspx</link><pubDate>Sun, 06 Aug 2006 17:29:33 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:106893</guid><dc:creator>omar</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=106893</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2006/08/06/generate-javascript-string-from-html-using-power-shell-script.aspx#comments</comments><description>&lt;p&gt;Say you want to generate a javascript representation of HTML fragment so that you can use document.write(‘’) or use element.innerHTML to inject it in the document dynamically. You need to do the following steps in order to convert HTML to BLOCKED SCRIPT
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div&gt;Bring HTML in one line
&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;Clear unnecessary spaces
&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;Replace all quote with backslash quote (\’)
&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;Replace all backslash with double backslash (\\)
&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Here’s a power shell script which does it for you:
&lt;/p&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;    1&lt;/span&gt;&lt;span style="color:black;"&gt; ###################################
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;    2&lt;/span&gt;&lt;span style="color:black;"&gt; # Make JS string out of HTML
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;    3&lt;/span&gt;&lt;span style="color:black;"&gt; #
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;    4&lt;/span&gt;&lt;span style="color:black;"&gt; # Takes a HTML fragment and converts
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;    5&lt;/span&gt;&lt;span style="color:black;"&gt; # it to a JS representation so that
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;    6&lt;/span&gt;&lt;span style="color:black;"&gt; # the JS can be used &lt;/span&gt;&lt;span style="color:blue;"&gt;in&lt;/span&gt;&lt;span style="color:black;"&gt; innerHTML or
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;    7&lt;/span&gt;&lt;span style="color:black;"&gt; # document.write
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;    8&lt;/span&gt;&lt;span style="color:black;"&gt; ###################################
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;    9&lt;/span&gt;&lt;span style="color:black;"&gt; Param( [string]$filePath, [string]$outputPath, [Boolean]$generateDocumentWrite=[Boolean]0 )
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   10&lt;/span&gt;&lt;span style="color:black;"&gt; 
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   11&lt;/span&gt;&lt;span style="color:black;"&gt; $streamReader = &lt;/span&gt;&lt;span style="color:blue;"&gt;new&lt;/span&gt;&lt;span style="color:black;"&gt;-object System.IO.StreamReader($filePath, [Boolean]&lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;quot;True&amp;quot;&lt;/span&gt;&lt;span style="color:black;"&gt;);
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   12&lt;/span&gt;&lt;span style="color:black;"&gt; $fileContent = $streamReader.ReadToEnd();
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   13&lt;/span&gt;&lt;span style="color:black;"&gt; $streamReader.Close();
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   14&lt;/span&gt;&lt;span style="color:black;"&gt; $streamReader.Dispose();
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   15&lt;/span&gt;&lt;span style="color:black;"&gt; 
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   16&lt;/span&gt;&lt;span style="color:black;"&gt; $fileContent=$fileContent.Replace(&lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;quot;`n&amp;quot;&lt;/span&gt;&lt;span style="color:black;"&gt;, &lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style="color:black;"&gt;).Replace(&lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;quot;`r&amp;quot;&lt;/span&gt;&lt;span style="color:black;"&gt;, &lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style="color:black;"&gt;).Replace(&lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;quot;`t&amp;quot;&lt;/span&gt;&lt;span style="color:black;"&gt;, &lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span style="color:black;"&gt;).Replace(&lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;quot;    &amp;quot;&lt;/span&gt;&lt;span style="color:black;"&gt;, &lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span style="color:black;"&gt;).Replace(&lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;quot;  &amp;quot;&lt;/span&gt;&lt;span style="color:black;"&gt;, &lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span style="color:black;"&gt;).Replace(&lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;quot;  &amp;quot;&lt;/span&gt;&lt;span style="color:black;"&gt;, &lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span style="color:black;"&gt;).Replace(&lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;quot;\&amp;quot;, &amp;quot;&lt;/span&gt;&lt;span style="color:black;"&gt;\\&lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;quot;).Replace(&amp;quot;&amp;#39;&amp;quot;, &amp;quot;\&amp;#39;&amp;quot;);&lt;/span&gt;&lt;span style="color:black;"&gt;
			&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   17&lt;/span&gt;&lt;span style="color:black;"&gt; 
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   18&lt;/span&gt;&lt;span style="color:black;"&gt; &lt;/span&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt;&lt;span style="color:black;"&gt;( [System.IO.File]::Exists($outputPath) ) { [System.IO.File]::Delete( $outputPath ); }
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   19&lt;/span&gt;&lt;span style="color:black;"&gt; 
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   20&lt;/span&gt;&lt;span style="color:black;"&gt; $streamWriter = &lt;/span&gt;&lt;span style="color:blue;"&gt;new&lt;/span&gt;&lt;span style="color:black;"&gt;-object System.IO.StreamWriter($outputPath, [Boolean]&lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;quot;True&amp;quot;&lt;/span&gt;&lt;span style="color:black;"&gt;);
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   21&lt;/span&gt;&lt;span style="color:black;"&gt; 
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   22&lt;/span&gt;&lt;span style="color:black;"&gt; &lt;/span&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt;&lt;span style="color:black;"&gt;( $generateDocumentWrite)
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   23&lt;/span&gt;&lt;span style="color:black;"&gt; {
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   24&lt;/span&gt;&lt;span style="color:black;"&gt;     $streamWriter.Write(&lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;quot;document.write(&amp;#39;&amp;quot;&lt;/span&gt;&lt;span style="color:black;"&gt;);
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   25&lt;/span&gt;&lt;span style="color:black;"&gt;     $streamWriter.Write($fileContent);
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   26&lt;/span&gt;&lt;span style="color:black;"&gt;     $streamWriter.Write(&lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;quot;&amp;#39;);&amp;quot;&lt;/span&gt;&lt;span style="color:black;"&gt;);
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   27&lt;/span&gt;&lt;span style="color:black;"&gt; }
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   28&lt;/span&gt;&lt;span style="color:black;"&gt; &lt;/span&gt;&lt;span style="color:blue;"&gt;else&lt;/span&gt;&lt;span style="color:black;"&gt;
			&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   29&lt;/span&gt;&lt;span style="color:black;"&gt; {
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   30&lt;/span&gt;&lt;span style="color:black;"&gt;     $streamWriter.Write($fileContent);
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   31&lt;/span&gt;&lt;span style="color:black;"&gt; }
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   32&lt;/span&gt;&lt;span style="color:black;"&gt; $streamWriter.Close();
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   33&lt;/span&gt;&lt;span style="color:black;"&gt; $streamWriter.Dispose();
&lt;/span&gt;&lt;/p&gt;&lt;p style="background:white;"&gt;&lt;span style="color:#2b91af;"&gt;   34&lt;/span&gt;&lt;span style="color:black;"&gt; 
&lt;/span&gt;&lt;/p&gt;&lt;/span&gt;&lt;p&gt;    
 &lt;/p&gt;&lt;p&gt;Just  run the script by passing a input file name and output file name and optionally a “1” in order to generate document.write(‘&amp;lt;converted js&amp;gt;’) statement.&lt;/p&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=106893" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/powershell/default.aspx">powershell</category></item><item><title>Using Power Shell to automate incremental updates to websites</title><link>http://msmvps.com/blogs/omar/archive/2006/08/06/using-power-shell-to-automate-incremental-updates-to-websites.aspx</link><pubDate>Sun, 06 Aug 2006 17:10:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:106891</guid><dc:creator>omar</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=106891</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2006/08/06/using-power-shell-to-automate-incremental-updates-to-websites.aspx#comments</comments><description>&lt;p&gt;Here&amp;rsquo;s something we used to do manually every time we had
to deploy a patch to production server:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div&gt;Get all the files changed since last deployment date &amp;amp;
time from latest code base that has been tested well enough&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Copy them to a folder which is dated.&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Update the web.config using Production server
configuration&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Update some other settings in &amp;lt;appSettings&amp;gt; inside
web.config&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Run through all the HTML files and compress them&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Run JSMIN on all JS files&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Increase version number in all external &amp;lt;SCRIPT
src=&amp;rdquo;&amp;hellip;&amp;rdquo;&amp;gt; tags. Increase only those which have
been changed&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Zip the entire folder&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;FTP it&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Extract the folder on production server and overwrite the
files&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now doing all these manually is pretty difficult and
there&amp;rsquo;s always change of human error. Thanks to Power Shell,
we have automated the entire process up to FTP and copy on
Production Server. We have a script named &amp;ldquo;deploy.ps1&amp;rdquo;
which takes a date time, server name and a version number, and does
all the preparation for us and gives us a nice zip file to upload.
The deployment script can prepare zip files for our developer
testing server, for beta server and for individual production
server in NLB.&lt;/p&gt;
&lt;p&gt;Let me show you how the file looks like:&lt;/p&gt;
&lt;p&gt;The file starts with some header and constants:&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;#************************************************************&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;# (C) Omar AL
Zabir&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Pageflakes Ltd.&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;# Create a
deployment compressed file which&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;# contains the
latest files after the given&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;# date.&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;#&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;# 1. Find all
the files after the specified date&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;# 2. Create a
deployment folder using the date time&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;# 3. Copy all
the changed files to the deployment folder&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;# 4. Copy
web.config and modify it according to settings&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;# 5. JSMin the
script files, if any&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;# 6. Update
default.aspx with latest version of Framework1-###.js &amp;amp;
Framework2-###.js&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;# 7. Use
Absolute HTML Compressor to compress all HTML files&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;# 8. Create a
zip file&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;#************************************************************&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;Param
([DateTime] $lastDatetime = [DateTime]::Now.AddDays(-1), $SERVER =
&amp;quot;www&amp;quot;, $VERSION = 1)&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The script takes a date time after which modified files are
copied to a deployment directory. It also takes the server name and
a version number.&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;if( $SERVER -eq
&amp;quot;nlb1&amp;quot; )&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;{&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$DB_HOST
= &amp;quot;(local)&amp;quot;;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$DB_NAME
= &amp;quot;PageFlakesDB&amp;quot;;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$CREDENTIAL
= &amp;quot;...&amp;quot;;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$EXTERNAL_SITE_PREFIX
= &amp;quot;http://www.pageflakes.com/&amp;quot;;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$EMAILTEMPLATE_FOLDER
= &amp;quot;d:\www\EmailTemplates\&amp;quot;;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;These are some constants that we use in web.config. As these
settings are purely server and site specific, we decide what will
be their value based on the server type specified.&lt;/p&gt;
&lt;p&gt;After this comes some path constants to files and folders:&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$CONNECTION_STRING
= &amp;quot;data source=&amp;quot; + $DB_HOST + &amp;quot;;initial catalog=&amp;quot; + $DB_NAME + &amp;quot;;&amp;quot;
+ $CREDENTIAL;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$JSMIN_PATH =
&amp;quot;jsmin.exe&amp;quot;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$HTML_COMPRESSOR_PATH
= &amp;quot;ahc.exe&amp;quot;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$HTML_COMPRESSOR_PARAMS
= &amp;quot;-y -s -l -w -t -c -d -b- -m`&amp;quot;*.htm;*.html`&amp;quot;&amp;quot;;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$HOSTNAME =
&amp;quot;ftp://69.41.181.68&amp;quot;;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$TARGET = &amp;quot;/&amp;quot; +
$SERVER + &amp;quot;/updates/&amp;quot;;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$WEB_PROJECT_PATH
= &amp;quot;..\src\EarlyPrototypes&amp;quot;;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$DEPLOYMENT_PATH
= &amp;quot;..\Deployments\&amp;quot; + $SERVER;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$FRAMEWORK1_FILENAME
= &amp;quot;Framework1.js&amp;quot;;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$FRAMEWORK2_FILENAME
= &amp;quot;Framework2.js&amp;quot;;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$DEFAULT_ASPX =
&amp;quot;Default.aspx&amp;quot;;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;These paths are determined by the folder where we have the
deploy.ps1 file located and where the web site code and deployment
directory is located. We currently have the following folder
structure in our local code base:&lt;/p&gt;
&lt;p&gt;Pageflakes\&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Src\WebSite&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Deployments&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Scripts\&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Deploy.ps1&lt;/p&gt;
&lt;p&gt;So, all the paths are relative to the deploy.ps1 file.&lt;/p&gt;
&lt;p&gt;Now we determine the absolute path of locations from their
relative path:&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$srcPath =
[System.IO.Path]::GetFullPath([System.IO.Path]::Combine(
$pwd.ToString(), $WEB_PROJECT_PATH ) );&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$destinationFolder
= [System.IO.Path]::GetFullPath([System.IO.Path]::Combine(
$pwd.ToString(), $DEPLOYMENT_PATH ));&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;$pwd is an internal variable in Power Shell which gives you
current path.&lt;/p&gt;
&lt;p&gt;Then we create a folder for deployment based on current date
time. The folder name is derived in yyyyMMdd format. Which means if
we are deploying on February 31
&lt;sup&gt;st&lt;/sup&gt;, 2006, the folder name will be 20060231.&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$deployFolder =
[DateTime]::Now.ToString(&amp;quot;yyyyMMdd&amp;quot;) + &amp;quot;-&amp;quot; + $VERSION;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$deployZipFileName
= $deployFolder + &amp;quot;.zip&amp;quot;;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Before starting to copy the file, we first delete the deployment
folder if it already exists:&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;if(
[System.IO.Directory]::Exists($deployPath) ){ remove-item -Path
$deployPath -recurse; }&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;remove-item with the &amp;ndash;recurse is equivalent to the
deltree.exe we had during DOS days. Unfortunately there&amp;rsquo;s
been no equivalent to deltree since Windows 98. But now with Power
Shell you can delete a directory along with all subdirectory and
files using remove-item &amp;ndash;recurse.&lt;/p&gt;
&lt;p&gt;In order to zip files to a zip file, we use
ICSharpCode.SharpZipLib.dll from SharpZip. Here&amp;rsquo;s how you can
load an external DLL and instantiate a class using powershell:&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$zipLibraryPath
= [System.IO.Path]::GetFullPath([System.IO.Path]::Combine(
$pwd.ToString(), &amp;quot;ICSharpCode.SharpZipLib.dll&amp;quot; ));&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;[void][System.Reflection.Assembly]::LoadFile($zipLibraryPath);&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$zip =
new-object ICSharpCode.SharpZipLib.Zip.FastZip;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now we will copy all the changed files after a specific
date:&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;quot;Copying files
to deployment folder...&amp;quot;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;# Get the files
which were changed after the $lastDateTime&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$changedFiles =
get-childitem $srcPath -exclude &amp;quot;*.log&amp;quot; -Recurse | where { $_ -is
[System.IO.FileInfo] -and $_.LastWriteTime -ge $lastDateTime -or
$_.Name -eq &amp;quot;Default.aspx&amp;quot; }&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;# Get each file
and copy the file to the proper destination directory&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;foreach( $file
in $changedFiles )&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;{&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[string]$filePath
= $file.ToString();&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[string]$relativePath
= $file.DirectoryName.substring($srcPath.Length);&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(
-not $relativePath.StartsWith(&amp;quot;\users\&amp;quot;) )&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#
if the relative path contains a subdirectory, then create a
subdirectory under the deploy path&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[string]$copyPath
= [System.IO.Path]::Combine( $deployPath,
$relativePath.TrimStart(&amp;#39;\&amp;#39;) );&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(
![System.IO.Directory]::Exists($copyPath) )&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&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;$newDir
= [System.IO.Directory]::CreateDirectory($copyPath);&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;copy
$filePath $copyPath;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;quot;Copy
complete.&amp;quot;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The above script copies changed files from one folder to a
destination folder recursively. Here&amp;rsquo;s the line that selects
the change file:&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$changedFiles =
get-childitem $srcPath -exclude &amp;quot;*.log&amp;quot; -Recurse | where { $_ -is
[System.IO.FileInfo] -and $_.LastWriteTime -ge $lastDateTime -or
$_.Name -eq &amp;quot;Default.aspx&amp;quot; }&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Note: if we do not put the filter &amp;ldquo;$_ -is
[System.IO.FileInfo]&amp;rdquo; then directories also get selected.&lt;/p&gt;
&lt;p&gt;Now&amp;rsquo;s a fun part, how do you modify web.config using Power
Shell? Do you know how easy it is to work with Xml files in
PowerShell? See this:&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;quot;Configuring
web.config...&amp;quot;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$webConfigFilePath
= [System.IO.Path]::Combine( $deployPath, &amp;quot;web.config&amp;quot; );&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;if(
[System.IO.File]::Exists( $webConfigFilePath ) )&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;{&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Web
config found&amp;quot;;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[System.Xml.XmlDocument]$doc
= new-object System.Xml.XmlDocument;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$doc.Load($webConfigFilePath);&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$root
= $doc.get_DocumentElement();&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$root.&amp;quot;system.web&amp;quot;.compilation.debug
= &amp;quot;false&amp;quot;;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$root.connectionStrings.add.connectionString
= $CONNECTION_STRING&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;foreach(
$item in $root.appSettings.add )&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(
$item.key -eq &amp;quot;SitePrefix&amp;quot; )&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
$item.Value = $EXTERNAL_SITE_PREFIX;
}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(
$item.key -eq &amp;quot;InternalSitePrefix&amp;quot;
)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;foreach(
$item in $root.&amp;quot;system.web&amp;quot;.compilation.assemblies.add )&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(
$item.assembly.Contains(&amp;quot;nunit&amp;quot;) )&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
$removedNode =
$root.&amp;quot;system.web&amp;quot;.compilation.assemblies.RemoveChild( $item );
}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$doc.Save($webConfigFilePath);&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;See how conveniently you can access nodes just like object
properties. For example, you can change the &amp;lt;compilation&amp;gt;
tags &amp;ldquo;debug&amp;rdquo; attribute this way:&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$root.&amp;quot;system.web&amp;quot;.compilation.debug
= &amp;quot;false&amp;quot;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s no need for SelectNode and then SetAttribute call
on XmlElement.&lt;/p&gt;
&lt;p&gt;Similarly you can iterate all &amp;lt;add key=&amp;rdquo;&amp;hellip;&amp;rdquo;
value=&amp;rdquo;&amp;hellip;&amp;rdquo; /&amp;gt; nodes in &amp;lt;appSettings&amp;gt; and
modify their value like this:&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;foreach( $item
in $root.appSettings.add )&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;{&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;if( $item.key
-eq &amp;quot;SitePrefix&amp;quot; )&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
$item.Value = $EXTERNAL_SITE_PREFIX;
}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(
$item.key -eq &amp;quot;InternalSitePrefix&amp;quot; )&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
$item.Value = $INTERNAL_SITE_PREFIX;
}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Power Shell makes Xml file manipulation peace of cake. You can
add nodes and remove nodes just like adding objects in arrays. For
example, here&amp;rsquo;s how I am removing all &amp;ldquo;nunit&amp;rdquo;
assembly reference nodes in
&amp;lt;system.web&amp;gt;&amp;lt;compilation&amp;gt;&amp;lt;assemblies&amp;gt; tag:&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;foreach( $item
in $root.&amp;quot;system.web&amp;quot;.compilation.assemblies.add )&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;{&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(
$item.assembly.Contains(&amp;quot;nunit&amp;quot;) )&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
$removedNode =
$root.&amp;quot;system.web&amp;quot;.compilation.assemblies.RemoveChild( $item );
}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If you use NUnit, you will see they get added to the web project
for no reason and if you don&amp;rsquo;t deploy nunit DLLs, you cannot
run your web site due to the assembly references. The above code
cleans up nunit reference from web.config.&lt;/p&gt;
&lt;p&gt;Now&amp;rsquo;s another interesting point. If some JS file changes,
we increment its version no by renaming the file with a versio
number. For example, when our framework.js file gets changed, we
rename the file to Framework1.js, Framework2.js and so on. When we
do that, we need to update the &amp;lt;script
src=&amp;rdquo;Framework.js&amp;rdquo;&amp;gt; in Default.aspx to &amp;lt;script
src=&amp;rdquo;Framework1.js /&amp;gt;. Here&amp;rsquo;s how we do it:&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;updateReferenceWithNewVersion
$FRAMEWORK1_FILENAME $DEFAULT_ASPX $VERSION $srcPath
$deployPath&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;function
updateReferenceWithNewVersion( $fileName, $referenceFile,
$versionNo, $srcPath, $destPath )&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;{&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$filePath
= [System.IO.Path]::Combine( $destPath, $fileName );&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(
[System.IO.File]::Exists( $filePath )
)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;$fileName
exists. Upgrading its version in $referenceFile&amp;quot;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$referencePath
= [System.IO.Path]::Combine( $destPath, $referenceFile );&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(
-not [System.IO.File]::Exists( $referencePath ) )&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Copying
$referenceFile because it&amp;#39;s not updated&amp;quot;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&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;$referenceSrcPath
= [System.IO.Path]::Combine( $srcPath, $referenceFile );&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&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;$result
= copy $referenceSrcPath $referencePath&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$newFileName
= $fileName.Split(&amp;#39;.&amp;#39;)[0] + &amp;quot;-&amp;quot; + $versionNo + &amp;quot;.&amp;quot; +
$fileName.Split(&amp;#39;.&amp;#39;)[1];&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ren
$filePath $newFileName&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$referenceContent
= [System.IO.File]::ReadAllText( $referencePath );&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$referenceContent
= $referenceContent.Replace( $fileName, $newFileName );&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[System.IO.File]::WriteAllText(
$referencePath, $referenceContent );&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;$fileName
not available&amp;quot;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Pretty long script. Basically it checks if the JS file that we
want to increase version exists or not. So, if Framework.js exists
in the deployment folder, then it is changed. So, we know we have
to change default.aspx in order to put the correct reference. Now
what if Default.aspx does not exist in the deployment folder? We
first copy the default.aspx to the deployment folder and then
update all the places where &amp;ldquo;Framework.js&amp;rdquo; has been
referenced.&lt;/p&gt;
&lt;p&gt;Now&amp;rsquo;s even more interesting part, we run 
&lt;a href="http://www.crockford.com/javascript/jsmin.html"&gt;JSMIN&lt;/a&gt;
to compress all .js files that is in the deployment folder. JSMin
is a filter which removes comments and unnecessary whitespace from
JavaScript files. It typically reduces filesize by half, resulting
in faster downloads. It also encourages a more expressive
programming style because it eliminates the download cost of clean,
literate self-documentation.&lt;/p&gt;
&lt;p&gt;So, we launch jsmin.exe and pass input and output JS file name
as argument. Here&amp;rsquo;s how we launch exe files from Power Shell
script:&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$jsFiles =
get-childitem $deployPath -include *.js -Recurse | where { $_ -is
[System.IO.FileInfo] }&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$p = new-object
System.Diagnostics.Process;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$si = new-object
System.Diagnostics.ProcessStartInfo;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$si.FileName =
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$jsminPath;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$si.CreateNoWindow
= [Boolean]&amp;quot;true&amp;quot;;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$p.StartInfo =
$si;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;foreach( $file
in $jsFiles )&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;{&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[string]$filePath
= $file.ToString();&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[string]$newFilePath
= $filePath + &amp;quot;.new&amp;quot;;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$si.Arguments
= $filePath + &amp;quot; &amp;quot; + $newFilePath;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$result
= $p.Start();&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$p.WaitForExit();&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(
$result )&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Minified:
$filePath&amp;quot;;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;copy
$newFilePath $filePath;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;del
$newFilePath;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;del
$newFilePath;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$p.Dispose();&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This saves javascript file size. Now we need to optimize HTML
files also and squeeze them as much as possible in order to save
bandwidth and make site load faster. There&amp;rsquo;s a free utility 
&lt;a href="http://www.alentum.com/ahc/index.htm"&gt;Absolute HTML
Compressor&lt;/a&gt; which has a command line version. We use the ahc.exe
file to compress HTML files in deployment directory the same way we
use JSMIN to cleanup javascript files.&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;quot;Compressing
html files...&amp;quot;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$p = new-object
System.Diagnostics.Process;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$si = new-object
System.Diagnostics.ProcessStartInfo;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$si.FileName =
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$htmlCompressorPath;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$si.CreateNoWindow
= [Boolean]&amp;quot;false&amp;quot;;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$compressorParam
= &amp;quot;`&amp;quot;&amp;quot; + $deployPath + &amp;quot;`&amp;quot; &amp;quot; + $HTML_COMPRESSOR_PARAMS;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;quot;$compressorParam&amp;quot;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$si.Arguments =
$compressorParam;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$p.StartInfo =
$si;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$result =
$p.Start();&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$p.WaitForExit();&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;if( $result
)&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;{&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Compressed&amp;quot;;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;else&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;{&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Error
occured&amp;quot;;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$p.Dispose();&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now&amp;rsquo;s the season finally, we zip up the entire deployment
folder and make one zip file to upload.&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;quot;Zipping
up....&amp;quot;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;# zip the entire
deployment folder and make one zip file&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$zip.CreateZip(
$deployZipFilePath, $deployPath, [Boolean]&amp;quot;true&amp;quot;, [string]::Empty
);&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;$zip.ExtractZip(
$deployZipFilePath, $deployPath+&amp;quot;_Extracted&amp;quot;, [string]::Empty
);&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Courier New;font-size:9;"&gt;&amp;quot;Zipping
done...&amp;quot;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;So, after all these, we have a nice patch that we can apply on
test, beta, production servers. The patch ensures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div&gt;Correct configuration, server specific settings&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;All JS files are compressed as much as possible&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;All HTML files are also compressed.&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hope you enjoy it!&lt;/p&gt;
&lt;img src="http://msmvps.com/aggbug.aspx?PostID=106891" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/powershell/default.aspx">powershell</category></item></channel></rss>