<?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>Codality &#187; Solution</title>
	<atom:link href="http://blog.najmanowicz.com/category/solution/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.najmanowicz.com</link>
	<description>Code and Effect - solving problem with just enough amount of code - by Adam Najmanowicz</description>
	<lastBuildDate>Mon, 23 Jan 2012 16:06:30 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Sitecore PowerShell Console cheat sheet &#8211; Part 2</title>
		<link>http://blog.najmanowicz.com/2012/01/23/sitecore-powershell-console-cheat-sheet-part-2/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sitecore-powershell-console-cheat-sheet-part-2</link>
		<comments>http://blog.najmanowicz.com/2012/01/23/sitecore-powershell-console-cheat-sheet-part-2/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 15:04:26 +0000</pubDate>
		<dc:creator>Adam Najmanowicz</dc:creator>
				<category><![CDATA[.Net Framework]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Sitecore]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Solution]]></category>
		<category><![CDATA[Web applications]]></category>

		<guid isPermaLink="false">http://blog.najmanowicz.com/?p=481</guid>
		<description><![CDATA[Most of this post is also based on the Microsoft’s Windows PowerShell Quick Reference however despite the sharing scripting runtimes the nature of the both shells differ considerably as described in the previous post: Sitecore PowerShell Console cheat sheet – Part 1. In all cases where it made sense I’ve converted the samples to establish [...]]]></description>
			<content:encoded><![CDATA[<p>Most of this post is also based on the Microsoft’s <a title="Windows PowerShell Quick Reference" href="http://www.microsoft.com/downloads/en/details.aspx?FamilyId=DF8ED469-9007-401C-85E7-46649A32D0E0&amp;displaylang=en" target="_blank">Windows PowerShell Quick Reference</a> however despite the sharing scripting runtimes the nature of the both shells differ considerably as described in the previous post: <a href="http://blog.najmanowicz.com/2012/01/11/sitecore-powershell-console-cheat-sheetpart-1/" target="_blank">Sitecore PowerShell Console cheat sheet – Part 1</a>. In all cases where it made sense I’ve converted the samples to establish them in Sitecore scenarios.</p>
<h2>How to Write Conditional Statements</h2>
<p>To write an If statement use code similar to this:</p>
<pre class="ps1">$page = Get-item .;
$changedBy = $page.&quot;__Updated by&quot;;

if ($changedBy -eq &quot;&quot;)
  { &quot;Unspecified author - a system page?&quot; }
elseif ($changedBy -eq $me)
  { &quot;The page has been last edited by me!&quot; }
else
  { &quot;The page has been last edited by &quot;+ $changedBy }</pre>
<p>Instead of writing a series of If statements you can use a Switch statement, which is equivalent to VBScript’s Select Case statement:</p>
<pre class="ps1">$page = Get-Item .;
switch ($page.Language) {
    &quot;en&quot; {&quot;This version is in English&quot;}
    &quot;pl&quot; {&quot;This version is in Polish&quot;}
    &quot;tlh-KX&quot; {&quot;This version is in Klingon?!&quot;}
    default {&quot;No idea what this language is!&quot;}
  }</pre>
<h2>How to Write For and For Each Loops</h2>
<p><span id="more-481"></span>
<p>To write a For statement use code similar to this:</p>
<pre class="ps1">for ($a = 1; $a -le 10; $a++) {$a}</pre>
<p>By comparison, a For Each statement might look like this:</p>
<pre class="ps1">cd master:\content\home
foreach ($i in Get-ChildItem .)
{ write-host $i.TemplateName }</pre>
<h2>How to Write Do Loops</h2>
<p>To write a Do loop use code like the following, replacing the code between the curly braces with the code to be executed on each iteration of the loop. Oh: and replacing the code inside the parentheses with the loop condition:</p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td valign="top" width="47%">
<pre class="ps1">$a = 1
do {$a; $a++}
<b>while</b> ($a -lt 10)</pre>
</td>
<td valign="top" width="6%">&#160;</td>
<td valign="top" width="47%">
<pre class="ps1">$a = 1
do {$a; $a++}
<b>until</b> ($a –gt 10)</pre>
</td>
</tr>
</tbody>
</table>
<h2>How to Use .NET Objects and Classes</h2>
<p>To use a .NET Framework class static method enclose the class name in square brackets, then separate the class name and the method using a pair of colons:</p>
<pre class="ps1">$master = <b>[Sitecore.Configuration.Factory]</b>::GetDatabase(&quot;master&quot;);
$homeItem = $master.GetItem(&quot;/sitecore/content/home&quot;);
$sample = $master.Templates[&quot;sample/sample item&quot;];
$myItem = $homeItem.Add(&quot;MyItem&quot;, $sample);</pre>
<p>To create an object reference to a .NET Framework object use the New-Object cmdlet:</p>
<pre class="ps1">$item = Get-Item &quot;master:\media library\Files\Sample&quot;;
<b>$mediaItem = New-Object `
                   -type Sitecore.Data.Items.MediaItem
                   -argumentlist $item</b></pre>
<p><b>Note</b>. This is a cursory overview of working with .NET. The two techniques shown here will not necessarily work with all .NET classes.</p>
<h2>How to Select Properties</h2>
<p>To work with or display specified properties of a collection, pipe the returned results to the Select-Object cmdlet:</p>
<pre class="ps1">Get-Item master:\content\Home | `
  Select-Object DisplayName, TemplateName</pre>
<h2>How to Sort Data</h2>
<p>To sort data returned by Windows PowerShell simply pipe that data to the Sort-Object cmdlet, specifying the property you want to sort by:</p>
<pre class="ps1">Get-ChildItem -recurse |
    <b>Sort-Object DisplayName</b> |
    Select-Object DisplayName, TemplateName</pre>
<p>You can also add the –descending or -ascending parameters to specify a sort order:</p>
<pre class="ps1">Get-ChildItem -recurse |
    <b>Sort-Object PageSaved -descending</b> |
    Select-Object DisplayName, __Updated, &quot;__Updated By&quot;</pre>
<p>You can even sort by multiple properties:</p>
<pre class="ps1">Get-ChildItem -recurse |
    <b>Sort-Object TemplateName, &quot;__Updated By&quot;</b> |
    Select-Object TemplateName, &quot;__Updated By&quot;, DisplayName</pre>
<h2>How to Work with WMI</h2>
<p>To get computer information using WMI call the Get-WMIObject cmdlet followed by the class name:</p>
<pre class="ps1">Get-WMIObject Win32_BIOS</pre>
<p>If the class you are interested in does not reside in the cimv2 namespace simply include the <b>–namespace</b> parameter:</p>
<pre class="ps1">Get-WMIObject SystemRestore `
    -namespace root\default</pre>
<p>To access data on another computer use the <b>–computername</b> parameter:</p>
<pre class="ps1">Get-WMIObject Win32_BIOS `
    –computername atl-ws-01</pre>
<p>To limit returned data, use a WQL query and the <b>–query</b> parameter:</p>
<pre class="ps1">Get-WMIObject -query `
    &quot;Select * From Win32_Service `
        Where State = 'Stopped'&quot;</pre>
<h2>How to “Interrogate” an Object</h2>
<p>To get information about the properties and methods of an object retrieve an instance of that object and then “pipe” the object to the <b>Get-Member</b> cmdlet. For example, this command returns the properties and methods available when working with processes:</p>
<pre class="ps1">Get-Item . | Get-Member</pre>
<p><strong>More tips coming soon… </strong>In the mean time please download the fresh version of the plugin with the latest improvements:</p>
<h2 align="center"><a title="Sitecore Powershell console on Shared Source" href="http://trac.sitecore.net/SitecorePowershellConsole" target="_blank">[Download &amp; Enjoy]</a></h2>
<p>All feedback appreciated!</p>
<blockquote style="padding-right: 16px !important">
<p><font color="#ff0000"><em><img style="background-image: none; border-right-width: 0px; margin: 3px 20px 0px 7px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Aperture_Science" border="0" alt="Aperture_Science" align="left" src="http://blog.najmanowicz.com/wp-content/uploads/2011/05/Aperture_Science_thumb.png" width="150" height="150" />Science isn&#8217;t about why, it&#8217;s about why not!?</em> </font><font color="#ff0000"><em>You ask: why is so much of our science dangerous? </p>
<p>I say: why not marry safe science if you love it so much. In fact, why not invent a special safety door that won&#8217;t hit you in the butt on the way out, because YOU ARE FIRED!</em></font></p>
<p><font color="#ff0000"><em>Yes you, box your stuff, out the front door, parking lot, car, goodbye. </p>
<p></em></font></p>
<p align="right"><font color="#ff0000">&#8211; <strong><a href="http://apscience.wikia.com/wiki/Cave_Johnson" target="_blank">Cave Johnson</a></strong> </font></p>
</blockquote>
<img src="http://blog.najmanowicz.com/?ak_action=api_record_view&id=481&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.najmanowicz.com/2012/01/23/sitecore-powershell-console-cheat-sheet-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sitecore PowerShell Console cheat sheet &#8211; Part 1</title>
		<link>http://blog.najmanowicz.com/2012/01/11/sitecore-powershell-console-cheat-sheetpart-1/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sitecore-powershell-console-cheat-sheetpart-1</link>
		<comments>http://blog.najmanowicz.com/2012/01/11/sitecore-powershell-console-cheat-sheetpart-1/#comments</comments>
		<pubDate>Wed, 11 Jan 2012 20:36:11 +0000</pubDate>
		<dc:creator>Adam Najmanowicz</dc:creator>
				<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[Downloadable]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Sitecore]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Solution]]></category>
		<category><![CDATA[Web applications]]></category>

		<guid isPermaLink="false">http://blog.najmanowicz.com/?p=473</guid>
		<description><![CDATA[I’m realizing time and time again that the learning curve for PowerShell can be steep without a proper guidance. While most people I talk to are very excited about the concept they become discouraged after a having some tries and not realizing its full potential. Therefore I decided it’s worth spending some time introducing some [...]]]></description>
			<content:encoded><![CDATA[<p>I’m realizing time and time again that the learning curve for PowerShell can be steep without a proper guidance. While most people I talk to are very excited about the concept they become discouraged after a having some tries and not realizing its full potential. Therefore I decided it’s worth spending some time introducing some basic principles to help scripting alleviate some of the initial pains.    </p>
<p>I have <a href="http://tumblr.najmanowicz.com/post/5067261138/free-powershell-ebooks" target="_blank">gathered some literature available for free about the topic of PowerShell in general you might want to read</a>, but I also think that a distillation of the basic concepts is really important so you can have some quick wins while you begin your PowerShell journey.</p>
<p>A great deal of this post is a <a href="http://blog.najmanowicz.com/2011/05/09/powershell-for-episerver-cheat-sheet-part-1/" target="_blank">port of my older post</a> for similar console for EPiServer, but since the differences are significant enough to confuse Sitecore developers if I sent them to the original version, I’ve decided to create a proper Sitecore cheat sheet.&#160;&#160; Most of this is based on the Microsoft’s <a title="Windows PowerShell Quick Reference" href="http://www.microsoft.com/downloads/en/details.aspx?FamilyId=DF8ED469-9007-401C-85E7-46649A32D0E0&amp;displaylang=en" target="_blank">Windows PowerShell Quick Reference</a> however despite the sharing scripting runtimes the nature of the both shells are pretty different (although the differences are not as vast as one might think).</p>
<table border="1" cellspacing="2" cellpadding="12">
<tbody>
<tr>
<th valign="top" width="50%">Windows PowerShell</th>
<th valign="top" width="50%">PowerShell Console for Sitecore</th>
</tr>
<tr>
<td valign="top"><strong>Interactive</strong> – command can ask for confirmations and can be aborted. User can be solicited to provide input.</td>
<td valign="top"><strong>Batch</strong> – all commands are being executed in one go, the script has no chance to ask questions, go or no-go decisions have to be solved within the script.</td>
</tr>
<tr>
<td valign="top">Supports command line arguments for running scripts.</td>
<td valign="top">All arguments are defined directly within the script or derived from context automatically.</td>
</tr>
<tr>
<td valign="top">Can access any file depending on the rights of the user.</td>
<td valign="top">Can only access files the web application identity can write to. Cannot access files on user’s machine but rather operates on the server’s file system. Cannot operate with elevated privileges.</td>
</tr>
</tbody>
</table>
<p>That said, I considered that enough of the Reference document is irrelevant in the Sitecore scenario that it’s beneficial for the users of the console to have a bespoke cheat sheet created especially for the purpose of this plugin.</p>
<p>The content &amp; samples of the original cheat sheet has been adjusted to more closely reflect scenarios usable for an Sitecore admin or developer.</p>
<h2>How to get help</h2>
<blockquote><p align="center"><em>Give a man a fish and you feed him for a day. Teach a man to fish and you feed him for a lifetime.</em></p>
</blockquote>
<p><span id="more-473"></span>
<p>By this principle – PowerShell by itself comes with an extensive help system. And the Sitecore implementation takes nothing away from it. Should you find yourself wondering the following is your friend.</p>
<p>To discover commandlet’s syntax you can use something like:</p>
<table border="0" cellspacing="0" cellpadding="0" width="97%">
<tbody>
<tr>
<td valign="top" width="47%">
<pre class="ps1">Get-Help Get-Item –Full</pre>
</td>
<td valign="top" width="6%">&#160;</td>
<td valign="top" width="47%">
<pre class="ps1">Get-Help ForEach-Object –Verbose</pre>
</td>
</tr>
</tbody>
</table>
<p>You can learn more about the help system by being slightly recursive <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.najmanowicz.com/wp-content/uploads/2012/01/wlEmoticon-smile.png" /></p>
<pre class="ps1">Get-Help Get-Help –Full</pre>
<p>There is a lot of discoverability within the environment. For example to learn about commandlets available to you you can try experimenting with these:</p>
<table border="0" cellspacing="0" cellpadding="0" width="97%">
<tbody>
<tr>
<td valign="top" width="47%">
<pre class="ps1">Get-Command -CommandType Cmdlet</pre>
</td>
<td valign="top" width="6%">&#160;</td>
<td valign="top" width="47%">
<pre class="ps1">Get-Command Get-*</pre>
</td>
</tr>
</tbody>
</table>
<p>You can discover what capabilities an object you got in pipeline possesses by using Get-Member e.g.:</p>
<pre class="ps1">Get-Item master:\ | Get-Member</pre>
<h1>And here go the Sitecore specific tips</h1>
<h2>How to work with items</h2>
<p>To switch to the desired database item you would use the following:</p>
<table border="0" cellspacing="0" cellpadding="0" width="97%">
<tbody>
<tr>
<td valign="top" width="47%">
<pre class="ps1">cd master:\</pre>
</td>
<td valign="top" width="6%">&#160;</td>
<td valign="top" width="47%">
<pre class="ps1">cd core:\content\Applications</pre>
</td>
</tr>
</tbody>
</table>
<p>The environment deliberately skips the “Sitecore” root in the tree as it provides no value to give the script access to the item and in fact unnecessarily lengthens each path so the “Sitecore” root is treated as the drive root. You can still access it as follows:</p>
<pre class="ps1">cd master:\
Get-Item .</pre>
<h2>How to get Current Item</h2>
<p>To get the page for the location you’re in you can use:</p>
<pre class="ps1">Get-Item .</pre>
<h2>How to get Current Page’s children</h2>
<p>To get the children of the page you’re currently in:</p>
<pre class="ps1">Get-ChildItem</pre>
<p>To get the children of the page you’re currently in and all of its children children (whole branch):</p>
<pre class="ps1">Get-ChildItem –recurse</pre>
<h2>How to Modify an item</h2>
<pre class="ps1">Get-Item . | ForEach-Object { $_.Text = “&lt;p&gt;Hello World&lt;/p&gt;” }</pre>
<p>or in short:</p>
<pre class="ps1">Get-Item . |% { $_.Text = “&lt;p&gt;Hello World&lt;/p&gt;” }</pre>
<h2>How to restart the application</h2>
<p>To restart the application use the following command:</p>
<pre class="ps1">Restart-Application</pre>
<h2>How to get system properties and environment variables</h2>
<p>Some more important variables are mapped onto the PowerShell variables by the plugin. Notable variables (value depending on your server configuration):</p>
<table border="1" cellspacing="1" cellpadding="5">
<tbody>
<tr>
<td valign="top" width="34%"><strong>Name</strong></td>
<td valign="top" width="65%">Sample value</td>
</tr>
<tr>
<td valign="top" width="34%">$AppPath</td>
<td valign="top" width="65%">C:\inetpub\wwwroot\CognifideShowcase\</td>
</tr>
<tr>
<td valign="top" width="34%">$AppVPath</td>
<td valign="top" width="65%">/ (app virtual folder)</td>
</tr>
<tr>
<td valign="top" width="34%">$tempPath</td>
<td valign="top" width="65%">C:\Windows\TEMP</td>
</tr>
<tr>
<td valign="top" width="34%">$tmpPath</td>
<td valign="top" width="65%">C:\Windows\TEMP</td>
</tr>
<tr>
<td valign="top" width="34%">$me</td>
<td valign="top" width="65%">sitecore\admin</td>
</tr>
</tbody>
</table>
<p><strong></strong></p>
<p>You can list all PowerShell variables by using:</p>
<pre class="ps1">Get-Variable *</pre>
<p>Additionally you can list all environment variables by using:</p>
<pre class="ps1">[System.Environment]::GetEnvironmentVariables()</pre>
<p>and get the value of a specific variable with e.g.:</p>
<pre class="ps1">[System.Environment]::GetEnvironmentVariable(&quot;ComputerName&quot;)</pre>
<h1>PowerShell Language and environment specific tips</h1>
<h2>How to Insert Comments</h2>
<p>To insert a comment, use the pound sign (#):</p>
<pre class="ps1"># This is a comment, not a line to be run.</pre>
<h2>How to Insert Line Breaks</h2>
<p>To insert a line break into a Windows PowerShell script use the backtick (`) :</p>
<pre class="ps1">$b = `
&quot;This is a continuation of the line.&quot;</pre>
<p>You can also break a line at the pipe separator (|) character (assuming your line uses the pipeline):</p>
<pre class="ps1">Get-ChildItem C:\Scripts |
Sort-Object Length –Descending</pre>
<h2>How to Create Multi-Command Lines</h2>
<p>To put multiple commands on a single line, separate those commands using a semicolon:</p>
<pre class="ps1">$a = 1,2,3,4,5; $b = $a[2]; $b</pre>
<p><strong>Hint.</strong> This script writes-out the value of <strong>$b</strong> which is <strong>3</strong></p>
<h2>How to Make Comparisons</h2>
<p>Windows PowerShell cmdlets (like <strong>Where-Object</strong>) use a special set of comparison operators, including those shown in the following table.</p>
<p>Each of these operators can be made case sensitive by adding a <strong>c</strong> immediately after the hyphen. For example, <strong>-ceq </strong>represents the case-sensitive equals operator; <strong>-clt</strong> is the case-sensitive less than operator.</p>
<table border="1" cellspacing="1" cellpadding="5">
<tbody>
<tr>
<td valign="top" width="34%"><strong>-lt</strong></td>
<td valign="top" width="65%">Less than</td>
</tr>
<tr>
<td valign="top" width="34%"><strong>-le</strong></td>
<td valign="top" width="65%">Less than or equal to</td>
</tr>
<tr>
<td valign="top" width="34%"><strong>-gt</strong></td>
<td valign="top" width="65%">Greater than</td>
</tr>
<tr>
<td valign="top" width="34%"><strong>-ge</strong></td>
<td valign="top" width="65%">Greater than or equal to</td>
</tr>
<tr>
<td valign="top" width="34%"><strong>-eq</strong></td>
<td valign="top" width="65%">Equal to</td>
</tr>
<tr>
<td valign="top" width="34%"><strong>-ne</strong></td>
<td valign="top" width="65%">Not equal to</td>
</tr>
<tr>
<td valign="top" width="34%"><strong>-like</strong></td>
<td valign="top" width="65%">Like (uses wildcards for matching)</td>
</tr>
<tr>
<td valign="top" width="34%"><strong>-notlike</strong></td>
<td valign="top" width="65%">Not like (uses wildcards for matching)</td>
</tr>
</tbody>
</table>
<p><strong></strong></p>
<p><strong></strong></p>
<h2>How to Read a Text File</h2>
<p>To read the contents of a text file into a variable, call the <strong>Get-Content</strong> cmdlet followed by the path to the text file:</p>
<pre class="ps1">$a = Get-Content C:\Scripts\Test.txt</pre>
<p>Each line in the file ends up as an item in the array $a. If you want to access a single line in the file you can simply specify the index number corresponding to that line:</p>
<pre class="ps1">$a[0]</pre>
<p>This command echoes back the <em>last </em>line in $a:</p>
<pre class="ps1">$a[-1]</pre>
<p><strong>Bonus</strong>. To determine the number of lines, words, and characters in a text file use this command:</p>
<pre class="ps1">Get-Content c:\scripts\test.txt |
measure-object -line -word -character</pre>
<h2>How to Write to a Text File</h2>
<p>To save data to a text file use the <strong>Out-File</strong> cmdlet:</p>
<pre class="ps1">Get-Item . | Out-File C:\Scripts\Test.txt</pre>
<p>To append data to an existing file, add the –<strong>append</strong> parameter:</p>
<pre class="ps1">Get-Item . | Out-File C:\Scripts\Test.txt –append</pre>
<p><strong>Attention. </strong>Unlike in the regular Windows PowerShell console you cannot use the MS-DOS redirection characters (&gt; for write, &gt;&gt; for append) when using Sitecore hosted PowerShell.</p>
<p>Another option is to use the <strong>Export-CSV</strong> cmdlet to save data as a comma-separated-values file:</p>
<pre class="ps1">Get-Item . | Export-CSV C:\Scripts\Test.txt</pre>
<p><strong>More tips coming soon… </strong>In the mean time please download the fresh version of the plugin with the latest improvements:</p>
<h2 align="center"><a title="Download Powershell console" href="http://trac.sitecore.net/SitecorePowershellConsole" target="_blank">[Download &amp; Enjoy]</a> </h2>
<p>All feedback appreciated!</p>
<img src="http://blog.najmanowicz.com/?ak_action=api_record_view&id=473&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.najmanowicz.com/2012/01/11/sitecore-powershell-console-cheat-sheetpart-1/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Extending Sitecore ribbon with PowerShell scripts</title>
		<link>http://blog.najmanowicz.com/2011/11/24/extending-sitecore-ribbon-with-powershell-scripts/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=extending-sitecore-ribbon-with-powershell-scripts</link>
		<comments>http://blog.najmanowicz.com/2011/11/24/extending-sitecore-ribbon-with-powershell-scripts/#comments</comments>
		<pubDate>Thu, 24 Nov 2011 10:08:40 +0000</pubDate>
		<dc:creator>Adam Najmanowicz</dc:creator>
				<category><![CDATA[.Net Framework]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[Downloadable]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Sitecore]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Solution]]></category>
		<category><![CDATA[Web applications]]></category>

		<guid isPermaLink="false">http://blog.najmanowicz.com/?p=454</guid>
		<description><![CDATA[Sitecore is built from the grounds up with extendibility in mind. Be that plugging into any place in its internal pipelines or any aspect of its User eXperience, therefore when I’ve managed to extend it’s context menu, I expected to have no problems whatsoever doing the same to its ribbon. Mind you I was right… [...]]]></description>
			<content:encoded><![CDATA[<p>Sitecore is built from the grounds up with extendibility in mind. Be that plugging into any place in its internal pipelines or any aspect of its User eXperience, therefore when I’ve managed to <a title="Context PowerShell scripts for Sitecore" href="http://blog.najmanowicz.com/2011/11/22/context-powershell-scripts-for-sitecore/" target="_blank">extend it’s context menu</a>, I expected to have no problems whatsoever doing the same to its ribbon. Mind you I was right…</p>
<p>Using the <a title="Sitecore PowerShell Console" href="http://trac.sitecore.net/SitecorePowershellConsole" target="_blank">PowerShell Console Module</a> it took me less than 10 minutes total to add a nice piece of functionality that I thought was missing – Publish items I have modified.</p>
<p align="center"><a href="http://blog.najmanowicz.com/wp-content/uploads/2011/11/ContextScriptsRibbon.png" rel="lightbox[454]" title="ContextScriptsRibbon"><img style="background-image: none; border-right-width: 0px; margin: 3px 3px 0px 7px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="ContextScriptsRibbon" border="0" alt="ContextScriptsRibbon" src="http://blog.najmanowicz.com/wp-content/uploads/2011/11/ContextScriptsRibbon_thumb.png" width="327" height="275" /></a></p>
<p>Similarly to <a title="Context PowerShell Scripts" href="http://blog.najmanowicz.com/2011/11/22/context-powershell-scripts-for-sitecore/" target="_blank">extending context menu</a> – first I’ve created the script I wanted to execute that will take the current item and it’s sub-items and publish them by adding a new script item using the <strong><em>/sitecore/templates/Cognifide/PowerShell Script</em></strong> template in the core database. I’ve put it in the same place I store all my my scripts &#8211; in the <strong><em>/sitecore/content/Applications/PowerShell Console/Scripts</em></strong> branch but feel free to store them anywhere in the tree.</p>
<ul>
<li>Filled in the Script body part with my script. </li>
<li>I decided I want to see the publishing results as I want to verify if the items I expected got published. </li>
</ul>
<p><a href="http://blog.najmanowicz.com/wp-content/uploads/2011/11/ContextScriptRibbonBody.png" rel="lightbox[454]" title="ContextScriptRibbonBody"><img style="background-image: none; border-right-width: 0px; margin: 3px auto 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="ContextScriptRibbonBody" border="0" alt="ContextScriptRibbonBody" src="http://blog.najmanowicz.com/wp-content/uploads/2011/11/ContextScriptRibbonBody_thumb.png" width="350" height="191" /></a></p>
<p>Now the UI integration bits…</p>
<p>Since I wanted it nicely integrated with the publish button &#8211; I’ve created a <strong><em>Publish My Items</em></strong> item of template <strong><em>/sitecore/templates/System/Menus/Menu item</em></strong> within the <strong><em>/sitecore/content/Applications/Content Editor/Menues/Publish/</em></strong> branch in the core database, set it’s icon and reference the script item in the <strong><em>Message</em></strong> field using the following pattern:</p>
<pre>item:executescript(id=$Target,script={0937769B-998D-4580-B9FE-730C4CDABECD},scriptDb=core)</pre>
<p>where the <strong><em>script</em></strong> guid is the ID of your script and the <strong><em>scriptDb</em></strong> is the database the script is located in.</p>
<p><a href="http://blog.najmanowicz.com/wp-content/uploads/2011/11/ContextScriptsRibbonBinding.png" rel="lightbox[454]" title="ContextScriptsRibbonBinding"><img style="background-image: none; border-right-width: 0px; margin: 3px auto 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="ContextScriptsRibbonBinding" border="0" alt="ContextScriptsRibbonBinding" src="http://blog.najmanowicz.com/wp-content/uploads/2011/11/ContextScriptsRibbonBinding_thumb.png" width="350" height="232" /></a></p>
<p>That’s it really. You can <a href="http://www.najmanowicz.com/blog_bin/PublishMyItems.zip" target="_blank">download the solution</a> but I would strongly recommend you try the manual approach – it’s really exciting to see the puzzles click in.</p>
<p>The solution requires the <a href="http://trac.sitecore.net/SitecorePowershellConsole" target="_blank">Sitecore PowerShell Console</a> from <a href="http://www.cognifide.com/" target="_blank">Cognifide</a>, available for free from <a href="http://trac.sitecore.net/SitecorePowershellConsole" target="_blank">Sitecore Shared Source</a> site.</p>
<img src="http://blog.najmanowicz.com/?ak_action=api_record_view&id=454&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.najmanowicz.com/2011/11/24/extending-sitecore-ribbon-with-powershell-scripts/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Sample scripts for Sitecore PowerShell Console</title>
		<link>http://blog.najmanowicz.com/2011/11/18/sample-scripts-for-sitecore-powershell-console/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sample-scripts-for-sitecore-powershell-console</link>
		<comments>http://blog.najmanowicz.com/2011/11/18/sample-scripts-for-sitecore-powershell-console/#comments</comments>
		<pubDate>Fri, 18 Nov 2011 12:24:25 +0000</pubDate>
		<dc:creator>Adam Najmanowicz</dc:creator>
				<category><![CDATA[.Net Framework]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Sitecore]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Solution]]></category>
		<category><![CDATA[Web applications]]></category>

		<guid isPermaLink="false">http://blog.najmanowicz.com/?p=427</guid>
		<description><![CDATA[Find out about your configuration: List your available site providers. You will use the name provided in the &#8220;Name&#8221; column in place of where I use &#8220;cms&#8221; in the later samples. get-psdrive ` &#124; where-object { $_.Provider.ToString() -eq "CmsItemProvider"} ` &#124; format-table Name, Root Sample scripts for working with pages: For the same of brevity [...]]]></description>
			<content:encoded><![CDATA[<h2>Find out about your configuration:</h2>
<p style="margin-bottom: 10px;">List your available site providers. You will use the name provided in the &#8220;Name&#8221; column in place of where I use &#8220;cms&#8221; in the later samples.</p>
<pre class="ps1">get-psdrive `
  | where-object { $_.Provider.ToString() -eq "CmsItemProvider"} `
  | format-table Name, Root</pre>
<h2>Sample scripts for working with pages:</h2>
<p style="margin-bottom: 10px;">For the same of brevity I’m assuming your location is already somewhere within a Sitecore tree (e.g. you did something akin to <strong><em>cd master:\content</em></strong> prior to executing the following scripts.</p>
<p style="margin-bottom: 10px;">List all properties &amp; fields available for a particular page (including Sitecore properties defined in the item template).</p>
<pre class="ps1">get-childitem | get-member -memberType property*</pre>
<p style="margin-bottom: 10px;">List all items in the CMS of which template name contains &#8220;Article&#8221;</p>
<pre class="ps1">get-childitem -recurse `
  | where-object { $_.TemplateName -match "Article" } `
  | format-table DisplayName, Name, TemplateName</pre>
<p style="margin-bottom: 10px;">List all subitems and how many days ago were they modified</p>
<pre class="ps1">get-childitem -recurse `
  | format-table Name, `
  @{Label="Days since modified"; Expression={ `
  [datetime]::Now.Subtract([Sitecore.DateUtil]::IsoDateToDateTime($_.Updated)).Days} }</pre>
<p style="margin-bottom: 10px;">Delete all pages that have not been modified for the last 365 days.</p>
<pre class="ps1">get-childitem -recurse `
  | where-object {[datetime]::Now.Subtract([Sitecore.DateUtil]::IsoDateToDateTime($_.Updated)).Days -gt 365 } `
  | remove-item</pre>
<p style="margin-bottom: 10px;">List all items Updated over the last 24 hours and who changed them.</p>
<pre class="ps1">get-childitem -recurse `
  | where-object { [Sitecore.DateUtil]::IsoDateToDateTime($_.Updated) -gt [datetime]::Now.AddDays(-1) } `
  | format-table -property DisplayName, UpdatedBy, {$_.Paths.Path}</pre>
<p style="margin-bottom: 10px;">List all pages that have their &#8220;Text&#8221; field filled in.</p>
<pre class="ps1">get-childitem -recurse `
  | where-object { $_.Text -ne $null } `
  | format-table -property DisplayName, {$_.Paths.Path}</pre>
<p style="margin-bottom: 10px;">Make a nice reviewer&#8217;s comment on all pages with their &#8220;Text&#8221; property filled in.</p>
<pre class="ps1">get-childitem -recurse `
  | where-object { $_.Text -ne $null } `
  | foreach-object { $_.ReviewersComment = "Great job providing content!" }</pre>
<p style="margin-bottom: 10px;">Add a warning to the beginning of &#8220;Text&#8221; property for all pages that have not been saved for the last 180 days.</p>
<pre class="ps1">
get-childitem -recurse `
  | where-object {`
  [datetime]::Now.Subtract([Sitecore.DateUtil]::IsoDateToDateTime($_.Updated)).Days -ge 180 `
  -and $_.Text -ne $null }
  | foreach-object {$_.Text = "&lt;p style='color:red'&gt;Old content. Review pending!&lt;/p&gt;" + $_.Text }</pre>
<p style="margin-bottom: 10px;">Replace a string in a property on all pages with another string (in this sample &#8211; removing the warning the last sample added).</p>
<pre class="ps1">$old_content = "&lt;p style='color:red'&gt;Old content. Review pending!&lt;/p&gt;"
$new_content = "";
get-childitem -recurse `
  | where-object {$_.Text -match $old_content} `
  | foreach-object {$_.Text = $_.Text.Replace($old_content, $new_content) }</pre>
<p style="margin-bottom: 10px;">Display the 10 most recently changed pages ordered in the reverse chronological order or changes. Display the page name, who changed it and when as well as the page status.</p>
<pre class="ps1">get-childitem -recurse `
  | sort-object -property Updated -descending `
  | select-object -First 10 `
  | format-table -property DisplayName, UpdatedBy, Updated</pre>
<h2>Sample scripts for working with Media Library / files:</h2>
<p style="margin-bottom: 10px;">Removes all .xml files from the “Old Xml Files” in Media library.</p>
<pre class="ps1">cd "master:\media library\Old Xml Files"
get-childitem -recurse `
  | where-object { $_.Extension -match "xml" } `
  | remove-item</pre>
<p style="margin-bottom: 10px;">Copy all files from the &#8220;staging&#8221; folder to the &#8220;production&#8221; folder in Media Library.</p>
<p style="margin-bottom: 10px;">Copying files within media library is done as follows. This can also be done for items in the content branch.</p>
<pre class="ps1">copy-item "master:\media library\staging\*" "master:\media library\production\"</pre>
<img src="http://blog.najmanowicz.com/?ak_action=api_record_view&id=427&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.najmanowicz.com/2011/11/18/sample-scripts-for-sitecore-powershell-console/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PowerShell Console for Sitecore &#8211; what can it do for me?</title>
		<link>http://blog.najmanowicz.com/2011/11/17/powershell-console-for-sitecore-what-can-it-do-for-me/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=powershell-console-for-sitecore-what-can-it-do-for-me</link>
		<comments>http://blog.najmanowicz.com/2011/11/17/powershell-console-for-sitecore-what-can-it-do-for-me/#comments</comments>
		<pubDate>Thu, 17 Nov 2011 19:14:31 +0000</pubDate>
		<dc:creator>Adam Najmanowicz</dc:creator>
				<category><![CDATA[.Net Framework]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Sitecore]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Solution]]></category>
		<category><![CDATA[Web applications]]></category>

		<guid isPermaLink="false">http://blog.najmanowicz.com/2011/11/17/powershell-console-for-sitecore-what-can-it-do-for-me/</guid>
		<description><![CDATA[The aim of the PowerShell console for Sitecore is to create a command line interface to your data so you can automate and aggregate mundane tasks ass well as create statistics and a discoverability layer on top of your content. Have you ever found yourself: having to make a mundane change to a large number [...]]]></description>
			<content:encoded><![CDATA[<p>The aim of the PowerShell console for Sitecore is to create a command line interface to your data so you can automate and aggregate mundane tasks ass well as create statistics and a discoverability layer on top of your content.</p>
<p>Have you ever found yourself:</p>
<ul>
<li>having to make a mundane change to a large number of pages? </li>
<li>in need of getting statistics field or template usages? </li>
<li>being curious of e.g. what’s the oldest page on your site? </li>
<li>in need to find out how many authors really create your content and how active they are?
<ul><!--EndFragment--></ul>
</li>
<li>having to copy or move a large number of files from one folder to another? </li>
<li>renaming or deleting files in your file store en-masse? </li>
<li>publish pages that match some specific feature rather than a whole branch? </li>
</ul>
<p><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 3px 21px 0px 7px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top: 0px; border-right: 0px; padding-top: 0px" title="sharp_tool" border="0" alt="sharp_tool" align="left" src="http://blog.najmanowicz.com/wp-content/uploads/2011/11/sharp_tool1.jpg" width="220" height="225" />If the answer to any of those (and more) is something akin to “<strong>yes I did!</strong>”, I believe you might find my little plugin useful.</p>
<p>The idea is to create a scripting environment to work within Sitecore process, being able to make native calls to Sitecore API and modify content on a per-property level. The goal was to make it familiar to your IT and developers so they can reuse their skillset with it or if they rather learn it here, this knowledge will benefit them in the long run as clearly PowerShell is becoming an industry standard. The plugin’s aim is to manipulate not just sites, but files and pages on a large scale or perform statistical analysis of your content using&#160; a familiar and well documented query language. The console allows you to execute and test scripts interactively, but also gives the admin means of exposing scripts to end users within context menus and in the ribbon. I’m sure in the long run I’ll come up with more applications. Scripted pipeline processors? Scripted renderings? Scripting campaigns statistics and engagement workflow steps? You name it…</p>
<p><span id="more-421"></span>
<p>Now there is <a href="http://vsplugins.sitecore.net/Sitecore-PowerShell.ashx" target="_blank">Rocks interface</a> that performs similar task which I think is brilliant, however slightly &#8211; yet significantly different. Rocks integrates with your Windows PowerShell console and allows you to work on your remote website as if it was a file system on your machine. Rocks also features a number of commandlets that help you with some common tasks. The definite bonus of this approach is that you can simply use it in your deployment script and integrate some common content modifications, or clear caches/recycle bins on your server in a timely manner from your monitoring environment. I think the solution is a really needed addition to your Sitecore toolbox, but… it’s somewhat limited. Namely whatever new idea you want to employ in your script, is either supported by the commandlets provided – or impossible. You have access to all the goodies of rocks, but any extension must first be imagined and implemented in Rocks (both server and client side).</p>
<p>The Sitecore Console however works within the process of your Sitecore site and therefore can instantiate and execute any API Sitecore features. The only limit is that of the imagination. this comes at a price too though. The most important thing is security. The PowerShell plugin by itself does not run with elevated privileges, nor does it circumvent the rights, but since you can use any Sitecore API a malicious person could potentially do it themselves – therefore you need to be careful whom do you grant access to the PowerShell Console.</p>
<p>The console comes with some sample scripts when you install it – review the script and press Ctrl+Enter to execute and see some of the interesting use cases for it.</p>
<p>By default the console creates a “drive” for each of your databases so you will definitely have a “core” and “master” drives, and you will most probably have a “web” drive.</p>
<p>Since this is only an introductory post I’ll let you discover the full list of commands by yourself, just use the following script within the console:</p>
<pre class="ps1">get-command `
  | where-object {$_.Implementingtype.FullName -match &quot;Cognifide.PowerShell&quot;} `
  |% {$_.Definition}</pre>
<p>Cool, isn’t it?!</p>
<p>The best thing about it is that you can pipeline the commands so you can make a somewhat sophisticated query for items and publish them in a single line. For example to publish all items under Home that are <strong>created by admin</strong> it’s sufficient to use:</p>
<pre class="ps1">get-childitem master:\content\home\* `
  | where-object {$_.CreatedBy -eq &quot;sitecore\admin&quot;} `
  | publish-item -verbose</pre>
<p>To publish all of items <strong>I (the current user)</strong> have <strong>modified</strong> you would use:</p>
<pre class="ps1">get-childitem master:\content\home\* `
  | where-object {$_.UpdatedBy –eq $me} `
  | publish-item -verbose</pre>
<p>So who edited those pages over the last 7 days?</p>
<pre class="ps1">get-childitem master:\content\home\* `
  | where-object {[datetime]::Now.Subtract([Sitecore.DateUtil]::IsoDateToDateTime($_.Updated)).Days -lt 7} `
  | select-object { $_.Name, $_.UpdatedBy, [Sitecore.DateUtil]::FormatIsoDate($_.Updated) } </pre>
<p>You get the idea…</p>
<p>I’ll try to provide more content regarding the Console and its usage over the coming weeks, stay tuned for much more fun!</p>
<h2 align="center"><a href="http://trac.sitecore.net/SitecorePowershellConsole" target="_blank">[Download &amp; Enjoy]</a></h2>
<p>All feedback appreciated!</p>
<p><font color="#ff0000"><strong>Disclaimer – Responsibility</strong>: With great powers comes great responsibility – this tool can do a lot of good but also bring harm to a lot of content in a very short time – backup your system before using the plugin and never run any untested scripts in a production environment! I will not be held responsible for any use of it. Test your scripts on your development server first! Test on an exact copy of production before running scripts on production content. </font></p>
<p><font color="#ff0000"><strong>Disclaimer – Security</strong>: If you plan to use the tool on your production environment, make sure to set the rights up in a way that an irresponsible users or just those who do&#8217;n’t necessarily need to, have no access to it. You can additionally, protect it with a &lt;location&gt; entry in web.config, to add another layer of security especially if your editor UI is available on a public server. Manage your group memberships &amp; rights responsibly!</font></p>
<img src="http://blog.najmanowicz.com/?ak_action=api_record_view&id=421&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.najmanowicz.com/2011/11/17/powershell-console-for-sitecore-what-can-it-do-for-me/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Enable Sitecore DMS Analytics behind a proxy or a CDN</title>
		<link>http://blog.najmanowicz.com/2011/10/05/enable-sitecore-dms-analytics-behind-a-proxy-or-a-cdn/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=enable-sitecore-dms-analytics-behind-a-proxy-or-a-cdn</link>
		<comments>http://blog.najmanowicz.com/2011/10/05/enable-sitecore-dms-analytics-behind-a-proxy-or-a-cdn/#comments</comments>
		<pubDate>Wed, 05 Oct 2011 19:52:59 +0000</pubDate>
		<dc:creator>Adam Najmanowicz</dc:creator>
				<category><![CDATA[.Net Framework]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[Sitecore]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Solution]]></category>

		<guid isPermaLink="false">http://blog.najmanowicz.com/?p=371</guid>
		<description><![CDATA[Should you put your Sitecore site behind a load balancing proxy you will run into a bit of a problem with analytics where all the Engagement Analytics app would ever report would be your own load balancing proxy&#8217;s IP address. Needless to say that is fairly big loss as you are unable to reap a [...]]]></description>
			<content:encoded><![CDATA[<p>Should you put your Sitecore site behind a load balancing proxy you will run into a bit of a problem with analytics where all the Engagement Analytics app would ever report would be your own load balancing proxy&#8217;s IP address. Needless to say that is fairly big loss as you are unable to reap a host of benefits of the Sitecore CEP like page personalization, automation and reporting.</p>
<p>While our website was running on Sitecore 6.4 this problem was already solved and we have implemented something akin to the solution from <a href="http://sitecore.jeroenveldhuis.nl/post/2011/02/24/Obtaining-visitor-IP-address-in-OMS-behind-load-balancer.aspx" target="_blank">Jeroen’s blog</a>. Meanwhile Sitecore has reimplemented its analytics engine from the grounds up in version 6.5, and I should say they did a great job on that. However in the process the API for the analytics has changed to a degree that made our current solution obsolete, basically what we got logged looked as follows:</p>
<p style="text-align: center;"><a href="http://blog.najmanowicz.com/wp-content/uploads/2011/10/BrokenAnalytics.png" rel="lightbox[371]" title="BrokenAnalytics"><img class="aligncenter" style="background-image: none; margin: 3px 3px 0px 7px; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="BrokenAnalytics" src="http://blog.najmanowicz.com/wp-content/uploads/2011/10/BrokenAnalytics_thumb-300x202.png" alt="BrokenAnalytics" width="300" height="202" border="0" /></a></p>
<p><span id="more-371"></span><br />
Unfortunately, and I suspect it&#8217;s because 6.5 is not a recommended version yet, this is not yet very well documented. Standing on the shoulders of giants, I’ve found a hint on the solution on <a href="http://www.sitecore.net/Community/Technical-Blogs/John-West-Sitecore-Blog/Posts/2011/05/Spoof-an-IP-Address-to-Test-GeoIP-with-the-Sitecore-Customer-Engagement-Platform.aspx" target="_blank">John West’s</a> blog. However after implementing this – the default report still showed the same… no luck… so I started looking in the analytics database. and found that the data in fact is not kept on the <strong>Page Request</strong> level but rather on the <strong>Visit</strong> level. Even better(!)… So there is no need for me to set it on every call to the server like before but instead I can dig into the improved analytics pipeline and plug only once when the first call to a server is made by the visitor. For that purpose I need to inherit a CreateVisitProcessor class and override the following method:</p>
<pre class="brush: csharp; title: ; notranslate">
public override void Process(CreateVisitArgs args)
</pre>
<p>The body of the method is somewhat similar to John’s implementation however for the report to show proper visitor ISP/company name you need to overwrite the RDNS field of the VisitRow object  &#8211; IP/GeoIP is not enough.</p>
<p>The body of my class looks as follows:</p>
<pre class="brush: csharp; title: ; notranslate">
private static string[] headers = { &quot;true-client-ip&quot;, &quot;X-Forwarded-For&quot; };

public override void Process(CreateVisitArgs args)
{
  VisitorDataSet.VisitsRow visit = args.Visit;
  HttpRequest request = args.Request;

  if (visit == null || visit.Ip == null)
  {
    return;
  }

  string forwardedFor = string.Empty;
  string headerUsed = string.Empty;

  // looking through all the headers where the true client IPs might be sent
  // the headers are ordered from highest to lowest priority
  foreach (string header in headers)
  {
    forwardedFor = request.Headers[header];
    if (!string.IsNullOrEmpty(forwardedFor))
    {
      headerUsed = header;
      break;
    }
  }

  if (!string.IsNullOrEmpty(forwardedFor))
  {
  // do the best effort for parsing x-forwarded-for
  // we need to check for multiple coma separates addresses
  // as there can be multiple proxies between the server and the client
  // this might not be 100% reliable as soem proxies and CDN's don't
  // append their IP's in the back but rather put themselves in the front
  string rdns = forwardedFor.Split(',').First().Trim();
  byte[] bForwardedFor = rdns.Split('.').Select(p =&gt; byte.Parse(p)).ToArray();

  var proxyIp = visit.Ip;
  visit.GeoIp = Tracker.Visitor.DataContext.GetGeoIp(bForwardedFor);
  visit.Ip = bForwardedFor;
  // the following needs to be set for the reverse dns lookup done by Sitecore
  // be performed on the right IP
  visit.RDNS = rdns;

  // feel free to eliminate that or change the default logging level to Debug
  // to stop it from poluting your logs
  Sitecore.Diagnostics.Log.Info(String.Format(
    &quot;Proxy overridden IP address: original [{0}.{1}.{2}.{3}] &quot;+
    &quot;replaced by [{4}] from header '{5}'.&quot;,
    proxyIp[0], proxyIp[1], proxyIp[2], proxyIp[3],
    forwardedFor, headerUsed), visit);
  }
}
</pre>
<p>Now you may wonder why do I use more than one signature? The problem is that both CDN-s and proxy servers have a tendency to abuse the &#8220;x-forwarded-for&#8221; header, for example some append their IP in the beginning rather than append it as a last. This, together with potentially having a number of proxies on the way is why we usually configure the CDN instances for our clients to put the real user IP address in an additional field that we can reliably parse.<br />
Pawel Cegielski (our local Cognifide&#8217;s CDN guru) will writing more about that <a href="http://hacqing.com/2011/10/11/sitecore-analytics-and-akamai/" target="_blank">on his blog</a>.</p>
<p>Now to integrate it with the Sitecore CreateVisit pipeline add the reference to your class as the first line in the createVisit section of the sitecore.analytics.config file similarly to the following:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;createVisit&gt;
  &lt;processor type=&quot;Cognifide.SiteCore.Framework.Facilities.Analytics.CreateVisitForProxy,Cognifide.SiteCore.Framework&quot;/&gt;
  ...
&lt;/createVisit&gt;
</pre>
<p>Your analytics should now work as if the proxy or CDN was never there&#8230;</p>
<img src="http://blog.najmanowicz.com/?ak_action=api_record_view&id=371&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.najmanowicz.com/2011/10/05/enable-sitecore-dms-analytics-behind-a-proxy-or-a-cdn/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PowerShell for EPiServer &#8211; cheat sheet &#8211; Part 2</title>
		<link>http://blog.najmanowicz.com/2011/05/10/powershell-for-episerver-cheat-sheet-part-2/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=powershell-for-episerver-cheat-sheet-part-2</link>
		<comments>http://blog.najmanowicz.com/2011/05/10/powershell-for-episerver-cheat-sheet-part-2/#comments</comments>
		<pubDate>Tue, 10 May 2011 09:08:00 +0000</pubDate>
		<dc:creator>Adam Najmanowicz</dc:creator>
				<category><![CDATA[.Net Framework]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[Downloadable]]></category>
		<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Solution]]></category>
		<category><![CDATA[Web applications]]></category>

		<guid isPermaLink="false">http://blog.najmanowicz.com/?p=294</guid>
		<description><![CDATA[&#160; Most of this post is also based on the Microsoft’s Windows PowerShell Quick Reference however despite the sharing scripting runtimes the nature of the both shells differ considerably as described in the previous post: PowerShell for EPiServer &#8211; cheat sheet &#8211; Part 1. In all cases where it made sense I’ve converted the samples [...]]]></description>
			<content:encoded><![CDATA[<p>&#160;</p>
<p>Most of this post is also based on the Microsoft’s <a title="Windows PowerShell Quick Reference" href="http://www.microsoft.com/downloads/en/details.aspx?FamilyId=DF8ED469-9007-401C-85E7-46649A32D0E0&amp;displaylang=en" target="_blank">Windows PowerShell Quick Reference</a> however despite the sharing scripting runtimes the nature of the both shells differ considerably as described in the previous post: <a href="http://blog.najmanowicz.com/2011/05/09/powershell-for-episerver-cheat-sheet-part-1/" target="_blank">PowerShell for EPiServer &#8211; cheat sheet &#8211; Part 1</a>. In all cases where it made sense I’ve converted the samples to establish them in EPiServer scenarios.</p>
<h2>How to Write Conditional Statements</h2>
<p>To write an If statement use code similar to this:</p>
<pre class="ps1">$page = Get-CurrentPage;
$changedBy = $page.ChangedBy;
$me = [EPiServer.Security.PrincipalInfo]::Current;
$myName = $me.Name;

if ($changedBy -eq &quot;&quot;)
  { &quot;Unspecified author - a system page?&quot; }
elseif ($changedBy -eq $myName)
  { &quot;The page has been last edited by me!&quot; }
else
  { &quot;The page has been last edited by &quot;+ $changedBy }</pre>
<p>Instead of writing a series of If statements you can use a Switch statement, which is equivalent to VBScript’s Select Case statement:</p>
<pre class="ps1">$page = Get-CurrentPage;
switch ($page.PageChildOrderRule) {
    0 {&quot;Undefined sort order. &quot;}
    1 {&quot;Most recently created page will be first in list&quot;}
    2 {&quot;Oldest created page will be first in list&quot;}
    3 {&quot;Sorted alphabetical on name&quot;}
    4 {&quot;Sorted on page index&quot;}
    5 {&quot;Most recently changed page will be first in list&quot;}
    6 {&quot;Sort on ranking, only supported by special controls&quot;}
    7 {&quot;Oldest published page will be first in list&quot;}
    8 {&quot;Most recently published page will be first in list&quot;}
    default {&quot;No idea what that means!&quot;}
  }</pre>
<h2>How to Write For and For Each Loops</h2>
<p><span id="more-294"></span><br />
<h2></h2>
<p>To write a For statement use code similar to this:</p>
<pre class="ps1">for ($a = 1; $a -le 10; $a++) {$a}</pre>
<p>By comparison, a For Each statement might look like this:</p>
<pre class="ps1">foreach ($i in Get-ChildItem .)
{ $i.PageTypeName }</pre>
<h2>How to Write Do Loops</h2>
<p>To write a Do loop use code like the following, replacing the code between the curly braces with the code to be executed on each iteration of the loop. Oh: and replacing the code inside the parentheses with the loop condition:</p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td valign="top" width="47%">
<pre class="ps1">$a = 1
do {$a; $a++}
<b>while</b> ($a -lt 10)</pre>
</td>
<td valign="top" width="6%">&#160;</td>
<td valign="top" width="47%">
<pre class="ps1">$a = 1
do {$a; $a++}
<b>until</b> ($a –gt 10)</pre>
</td>
</tr>
</tbody>
</table>
<h2>How to Use .NET Objects and Classes</h2>
<p>To use a .NET Framework class static method enclose the class name in square brackets, then separate the class name and the method using a pair of colons: </p>
<pre class="ps1">$parent = Get-CurrentPage;
$myPage = <b>[EPiServer.DataFactory]::Instance</b>.GetDefaultPageData(
              $parent.PageLink, &quot;[AlloyTech] Standard page&quot;);
$myPage.PageName = &quot;My New Page&quot;;
$myPage.URLSegment = <b>[EPiServer.Web.UrlSegment]::CreateUrlSegment($myPage);</b>
Save-Page($myPage);</pre>
<p>To create an object reference to a .NET Framework object use the New-Object cmdlet: </p>
<pre class="ps1">$page = Get-CurrentPage;
<b>$urlBuilder = New-Object '
                   -type EPiServer.UrlBuilder
                   -argumentlist $page.LinkURL;</b>
[EPiServer.Global]::UrlRewriteProvider.ConvertToExternal(
    $urlBuilder, $page.PageLink, [System.Text.UTF8Encoding]::UTF8);
$currentPath = $urlBuilder.Path</pre>
<p><b>Note</b>. This is a cursory overview of working with .NET. The two techniques shown here will not necessarily work with all .NET classes. </p>
<h2>How to Select Properties</h2>
<p>To work with or display specified properties of a collection, pipe the returned results to the Select-Object cmdlet:</p>
<pre class="ps1">Get-CurrentPage | Select-Object PageName, PageTypeName</pre>
<h2>How to Sort Data</h2>
<p>To sort data returned by Windows PowerShell simply pipe that data to the Sort-Object cmdlet, specifying the property you want to sort by:</p>
<pre class="ps1">Get-ChildItem -recurse |
    <b>Sort-Object PageName</b> |
    Select-Object PageName, PageTypeName</pre>
<p>You can also add the –descending or -ascending parameters to specify a sort order:</p>
<pre class="ps1">Get-ChildItem -recurse |
    <b>Sort-Object PageSaved -descending</b> |
    Select-Object PageName, PageSaved, ChangedBy</pre>
<p>You can even sort by multiple properties:</p>
<pre class="ps1">Get-ChildItem -recurse |
    <b>Sort-Object PageTypeName, ChangedBy</b> |
    Select-Object PageTypeName, ChangedBy, PageName</pre>
<h2>How to Work with WMI</h2>
<p>To get computer information using WMI call the Get-WMIObject cmdlet followed by the class name:</p>
<pre class="ps1">Get-WMIObject Win32_BIOS</pre>
<p>If the class you are interested in does not reside in the cimv2 namespace simply include the <b>–namespace</b> parameter:</p>
<pre class="ps1">Get-WMIObject SystemRestore `
    -namespace root\default</pre>
<p>To access data on another computer use the <b>–computername</b> parameter:</p>
<pre class="ps1">Get-WMIObject Win32_BIOS `
    –computername atl-ws-01</pre>
<p>To limit returned data, use a WQL query and the <b>–query</b> parameter:</p>
<pre class="ps1">Get-WMIObject -query `
    &quot;Select * From Win32_Service `
        Where State = 'Stopped'&quot;</pre>
<h2>How to “Interrogate” an Object</h2>
<p>To get information about the properties and methods of an object retrieve an instance of that object and then “pipe” the object to the <b>Get-Member</b> cmdlet. For example, this command returns the properties and methods available when working with processes: </p>
<pre class="ps1">Get-Item . | Get-Member</pre>
<p><strong>More tips coming soon… </strong>In the mean time please download the fresh version of the plugin with the latest improvements:</p>
<p align="center"><a title="Download Powershell console for Cheat Sheet 1" href="http://www.najmanowicz.com/blog_bin/Cognifide.EPiserverControls.PowerShell.CheatSheet1.zip" target="_blank">[Download &amp; Enjoy]</a> </p>
<p><strong>Get it while it’s hot – still includes 3 bonus script collections!</strong></p>
<h2>How to install?</h2>
<p>Extract the DLL form the ZIP file into the BIN folder of your web application to install the plugin. Remove the DLL to uninstall it.</p>
<p>All feedback appreciated!</p>
<p><span style="color: #ff0000"><strong>In lieu of the regular disclaimer</strong>: </span></p>
<blockquote style="padding-right: 16px !important">
<p><font color="#ff0000"><em><img style="background-image: none; border-right-width: 0px; margin: 3px 20px 0px 7px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Aperture_Science" border="0" alt="Aperture_Science" align="left" src="http://blog.najmanowicz.com/wp-content/uploads/2011/05/Aperture_Science_thumb.png" width="150" height="150" />Science isn&#8217;t about why, it&#8217;s about why not!? </p>
<p></em></font><font color="#ff0000"><em>You ask: why is so much of our science dangerous?<br />
        <br />I say: why not marry safe science if you love it so much. In fact, why not invent a special safety door that won&#8217;t hit you in the butt on the way out, because YOU ARE FIRED!</em></font></p>
<p><font color="#ff0000"><em>Yes you, box your stuff, out the front door, parking lot, car, goodbye.<br />
        <br /></em></font></p>
<p align="right"><font color="#ff0000">&#8211; <strong><a href="http://apscience.wikia.com/wiki/Cave_Johnson" target="_blank">Cave Johnson</a> </p>
<p></strong></font></p>
</blockquote>
<img src="http://blog.najmanowicz.com/?ak_action=api_record_view&id=294&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.najmanowicz.com/2011/05/10/powershell-for-episerver-cheat-sheet-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PowerShell for EPiServer &#8211; cheat sheet &#8211; Part 1</title>
		<link>http://blog.najmanowicz.com/2011/05/09/powershell-for-episerver-cheat-sheet-part-1/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=powershell-for-episerver-cheat-sheet-part-1</link>
		<comments>http://blog.najmanowicz.com/2011/05/09/powershell-for-episerver-cheat-sheet-part-1/#comments</comments>
		<pubDate>Mon, 09 May 2011 08:00:00 +0000</pubDate>
		<dc:creator>Adam Najmanowicz</dc:creator>
				<category><![CDATA[.Net Framework]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Solution]]></category>
		<category><![CDATA[Web applications]]></category>

		<guid isPermaLink="false">http://blog.najmanowicz.com/?p=242</guid>
		<description><![CDATA[Most of this is based on the Microsoft’s Windows PowerShell Quick Reference however despite the sharing scripting runtimes the nature of the both shells are pretty different (although the differences are not as vast as one might think). &#160; Windows PowerShell PowerShell Console for EPiServer Interactive – command can ask for confirmations and can be [...]]]></description>
			<content:encoded><![CDATA[<p>Most of this is based on the Microsoft’s <a title="Windows PowerShell Quick Reference" href="http://www.microsoft.com/downloads/en/details.aspx?FamilyId=DF8ED469-9007-401C-85E7-46649A32D0E0&amp;displaylang=en" target="_blank">Windows PowerShell Quick Reference</a> however despite the sharing scripting runtimes the nature of the both shells are pretty different (although the differences are not as vast as one might think).</p>
<p>&#160;</p>
<table border="1" cellspacing="2" cellpadding="12">
<tbody>
<tr>
<th valign="top" width="50%">Windows PowerShell</th>
<th valign="top" width="50%">PowerShell Console for EPiServer</th>
</tr>
<tr>
<td valign="top"><strong>Interactive</strong> – command can ask for confirmations and can be aborted. User can be solicited to provide input.</td>
<td valign="top"><strong>Batch</strong> – all commands are being executed in one go, the script has no chance to ask questions, go or no-go decisions have to be solved within the script.</td>
</tr>
<tr>
<td valign="top">Supports colouring.</td>
<td valign="top">Supports plain text output only.</td>
</tr>
<tr>
<td valign="top">Supports command line arguments for running scripts.</td>
<td valign="top">All arguments are defined directly within the script or derived from context automatically.</td>
</tr>
<tr>
<td valign="top">Can access any file depending on the rights of the user.</td>
<td valign="top">Can only access files the web application identity can write to. Cannot access files on user’s machine but rather operates on the server’s file system. Cannot operate with elevated privileges.</td>
</tr>
</tbody>
</table>
<p>That said, I considered that enough of the Reference document is irrelevant in the EPiServer scenario that it’s beneficial for the users of the console to have a bespoke cheat sheet created especially for the purpose of this plugin.</p>
<p>The content &amp; samples of the original cheat sheet has been adjusted to more closely reflect scenarios usable for an EPiServer admin or developer.</p>
<h1>So here go the EPiServer specific tips</h1>
<p><span id="more-242"></span><br />
<h2>How to get Current Page</h2>
<p>To get the page for the location you’re in you can use either one:</p>
<table border="0" cellspacing="0" cellpadding="0" width="97%">
<tbody>
<tr>
<td valign="top" width="47%">
<pre class="ps1">Get-Item .</pre>
</td>
<td valign="top" width="6%">&nbsp;</td>
<td valign="top" width="47%">
<pre class="ps1">Get-CurrentPage</pre>
</td>
</tr>
</tbody>
</table>
<h2>How to get Current Page’s children</h2>
<p>To get the children of the page you’re currently in:</p>
<pre class="ps1">Get-ChildItem</pre>
<p>
  <br />To get the children of the page you’re currently in and all of its children children (whole branch): </p>
<p></p>
<pre class="ps1">Get-ChildItem –recurse</pre>
<h2>How to Modify a page</h2>
<p>the modification depends on whether you’re modifying the Page Template defined properties or the PageData (POCO – C#) properties. In case of the former the modification is scripted into the attached property (which I script within the environment to create the writable clone behind the scenes)</p>
<pre class="ps1">Get-CurrentPage |
ForEach-Object { $_.MainBody = “&lt;p&gt;Hello World&lt;/p&gt;” }</pre>
<p>
  <br />but in case of the POCO properties you need to do part of the work yourself: </p>
<p></p>
<pre class="ps1">Get-CurrentPage |
ForEach-Object {
$writable = $_.CreateWritableClone();
$writable.PageName = “Hello World”;
Save-Page($writable);
}</pre>
<h2>How to restart the application</h2>
<p>To restart the application use the following command:</p>
<pre class="ps1">Restart-Application</pre>
<h2>How to get system properties and environment variables</h2>
<p>Some more important variables are mapped onto the PowerShell variables by the plugin. Notable variables (value depending on your server configuration):</p>
<table border="1" cellspacing="1" cellpadding="5">
<tbody>
<tr>
<td valign="top" width="34%"><strong>Name</strong></td>
<td valign="top" width="65%">Sample value</td>
</tr>
<tr>
<td valign="top" width="34%">$AppPath</td>
<td valign="top" width="65%">C:\EPiServer\Sites\ExampleEPiServerSite3\</td>
</tr>
<tr>
<td valign="top" width="34%">$AppVPath</td>
<td valign="top" width="65%">/ (app virtual folder)</td>
</tr>
<tr>
<td valign="top" width="34%">$tempPath</td>
<td valign="top" width="65%">C:\Windows\TEMP</td>
</tr>
<tr>
<td valign="top" width="34%">$tmpPath</td>
<td valign="top" width="65%">C:\Windows\TEMP</td>
</tr>
</tbody>
</table>
<p><strong></strong></p>
<p>Additionally you can list all environment variables by using:</p>
<pre class="ps1">[System.Environment]::GetEnvironmentVariables()</pre>
<p>
  <br />and get the value of a specific variable with e.g.: </p>
<p></p>
<pre class="ps1">[System.Environment]::GetEnvironmentVariable(&quot;ComputerName&quot;)</pre>
<h1>PowerShell Language and environment specific tips</h1>
<h2>How to Insert Comments</h2>
<p>To insert a comment, use the pound sign (#):</p>
<pre class="ps1"># This is a comment, not a line to be run.</pre>
<h2>How to Insert Line Breaks</h2>
<p>To insert a line break into a Windows PowerShell script use the backtick (`) :</p>
<pre class="ps1">$b = `
&quot;This is a continuation of the line.&quot;</pre>
<p>
  <br />You can also break a line at the pipe separator (|) character (assuming your line uses the pipeline): </p>
<p></p>
<pre class="ps1">Get-ChildItem C:\Scripts |
Sort-Object Length –Descending</pre>
<h2>How to Create Multi-Command Lines</h2>
<p>To put multiple commands on a single line, separate those commands using a semicolon:</p>
<pre class="ps1">$a = 1,2,3,4,5; $b = $a[2]; $b</pre>
<p><strong>Hint.</strong> This script writes-out the value of <strong>$b</strong> which is <strong>3</strong></p>
<h2>How to Make Comparisons</h2>
<p>Windows PowerShell cmdlets (like <strong>Where-Object</strong>) use a special set of comparison operators, including those shown in the following table.</p>
<p>Each of these operators can be made case sensitive by adding a <strong>c</strong> immediately after the hyphen. For example, <strong>-ceq </strong>represents the case-sensitive equals operator; <strong>-clt</strong> is the case-sensitive less than operator.</p>
<table border="1" cellspacing="1" cellpadding="5">
<tbody>
<tr>
<td valign="top" width="34%"><strong>-lt</strong></td>
<td valign="top" width="65%">Less than</td>
</tr>
<tr>
<td valign="top" width="34%"><strong>-le</strong></td>
<td valign="top" width="65%">Less than or equal to</td>
</tr>
<tr>
<td valign="top" width="34%"><strong>-gt</strong></td>
<td valign="top" width="65%">Greater than</td>
</tr>
<tr>
<td valign="top" width="34%"><strong>-ge</strong></td>
<td valign="top" width="65%">Greater than or equal to</td>
</tr>
<tr>
<td valign="top" width="34%"><strong>-eq</strong></td>
<td valign="top" width="65%">Equal to</td>
</tr>
<tr>
<td valign="top" width="34%"><strong>-ne</strong></td>
<td valign="top" width="65%">Not equal to</td>
</tr>
<tr>
<td valign="top" width="34%"><strong>-like</strong></td>
<td valign="top" width="65%">Like (uses wildcards for matching)</td>
</tr>
<tr>
<td valign="top" width="34%"><strong>-notlike</strong></td>
<td valign="top" width="65%">Not like (uses wildcards for matching)</td>
</tr>
</tbody>
</table>
<p><strong></strong></p>
<p><strong></strong></p>
<h2>How to Read a Text File</h2>
<p>To read the contents of a text file into a variable, call the <strong>Get-Content</strong> cmdlet followed by the path to the text file:</p>
<pre class="ps1">$a = Get-Content C:\Scripts\Test.txt</pre>
<p>
  <br />Each line in the file ends up as an item in the array $a. If you want to access a single line in the file you can simply specify the index number corresponding to that line: </p>
<p></p>
<pre class="ps1">$a[0]</pre>
<p>
  <br />This command echoes back the <em>last </em>line in $a: </p>
<p></p>
<pre class="ps1">$a[-1]</pre>
<p>
  <br /><strong>Bonus</strong>. To determine the number of lines, words, and characters in a text file use this command: </p>
<p></p>
<pre class="ps1">Get-Content c:\scripts\test.txt |
measure-object -line -word -character</pre>
<h2>How to Write to a Text File</h2>
<p>To save data to a text file use the <strong>Out-File</strong> cmdlet:</p>
<pre class="ps1">Get-CurrentPage | Out-File C:\Scripts\Test.txt</pre>
<p>
  <br />To append data to an existing file, add the –<strong>append</strong> parameter: </p>
<p></p>
<pre class="ps1">Get-CurrentPage | Out-File C:\Scripts\Test.txt –append</pre>
<p><strong>Attention. </strong>Unlike in the regular Windows PowerShell console you cannot use the MS-DOS redirection characters (&gt; for write, &gt;&gt; for append) when using EPiServer hosted PowerShell.</p>
<p>Another option is to use the <strong>Export-CSV</strong> cmdlet to save data as a comma-separated-values file:</p>
<pre class="ps1">Get-Process | Export-CSV C:\Scripts\Test.txt</pre>
<p><strong>More tips coming soon… </strong>In the mean time please download the fresh version of the plugin with the latest improvements:</p>
<p align="center"><a title="Download Powershell console for Cheat Sheet 1" href="http://www.najmanowicz.com/blog_bin/Cognifide.EPiserverControls.PowerShell.CheatSheet1.zip" target="_blank">[Download &amp; Enjoy]</a><br /><strong>Get it while it’s hot – still includes 3 bonus script collections!</strong></p>
<h2>How to install?</h2>
<p>Extract the DLL form the ZIP file into the BIN folder of your web application to install the plugin. Remove the DLL to uninstall it.</p>
<p>All feedback appreciated!</p>
<p><span style="color: #ff0000"><strong>Disclaimer – Responsibility</strong>: <em>With great powers comes great responsibility – this tool can do a lot of harm to a lot of content in a very short time – backup your system before using the plugin! I will not be held responsible for any use of it. Test your scripts on your development server first! Test on an exact copy of production before running scripts on production content. </em></span></p>
<p><span style="color: #ff0000"><strong>Disclaimer – Security</strong>: <em>While the tool requires a membership in either the “WebAdmin” or “Administrators” group, to execute, protect it with a &lt;location&gt; entry in web.config, to add another layer of security especially if your administration UI is exposed to the public. Manage your group memberships &amp; rights responsibly!</em></span></p>
<img src="http://blog.najmanowicz.com/?ak_action=api_record_view&id=242&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.najmanowicz.com/2011/05/09/powershell-for-episerver-cheat-sheet-part-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>EPiServer Admin Mode PowerShell scripts</title>
		<link>http://blog.najmanowicz.com/2011/05/07/episerver-admin-mode-powershell-scripts/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=episerver-admin-mode-powershell-scripts</link>
		<comments>http://blog.najmanowicz.com/2011/05/07/episerver-admin-mode-powershell-scripts/#comments</comments>
		<pubDate>Sat, 07 May 2011 21:23:00 +0000</pubDate>
		<dc:creator>Adam Najmanowicz</dc:creator>
				<category><![CDATA[.Net Framework]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[Downloadable]]></category>
		<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Solution]]></category>
		<category><![CDATA[Web applications]]></category>

		<guid isPermaLink="false">http://blog.najmanowicz.com/?p=272</guid>
		<description><![CDATA[The PowerShell plugin gets an update once again to support Admin mode script collections in addition to the context scripts. How to write an Admin mode script collections? &#60;ContextScriptCollection&#62; &#60;Title&#62;Statistics Scripts&#60;/Title&#62; &#60;Description&#62;This script collection ... &#60;/Description&#62; &#60;Area&#62;Administration&#60;/Area&#62; &#60;Scripts&#62; &#60;ContextScript&#62; &#60;Title&#62;Restart Application&#60;/Title&#62; &#60;Description&#62;The script restarts this instance of EPiServer...&#60;/Warning&#62; &#60;Script&#62;Restart-Application&#60;/Script&#62; &#60;Icon&#62;/App_Themes/Default/Images/Tools/Refresh.gif&#60;/Icon&#62; &#60;Groups&#62; &#60;/Groups&#62; &#60;/ContextScript&#62; &#60;/Scripts&#62; &#60;/ContextScriptCollection&#62; [...]]]></description>
			<content:encoded><![CDATA[<p>The PowerShell plugin gets an update once again to support Admin mode script collections in addition to the context scripts.</p>
<h2>How to write an Admin mode script collections?</h2>
<pre>&lt;ContextScriptCollection&gt;
  &lt;Title&gt;Statistics Scripts&lt;/Title&gt;
  &lt;Description&gt;This script collection ... &lt;/Description&gt;
  <strong>&lt;Area&gt;Administration&lt;/Area&gt;</strong>
  &lt;Scripts&gt;
    &lt;ContextScript&gt;
      &lt;Title&gt;Restart Application&lt;/Title&gt;
      &lt;Description&gt;The script restarts this instance of EPiServer...&lt;/Warning&gt;
      &lt;Script&gt;Restart-Application&lt;/Script&gt;
      &lt;Icon&gt;/App_Themes/Default/Images/Tools/Refresh.gif&lt;/Icon&gt;
      &lt;Groups&gt;
      &lt;/Groups&gt;
    &lt;/ContextScript&gt;
  &lt;/Scripts&gt;
&lt;/ContextScriptCollection&gt;</pre>
<h2>Where can I access that?</h2>
<p align="center"><a href="http://blog.najmanowicz.com/wp-content/uploads/2011/05/image.png" rel="lightbox[272]" title="image"><img style="background-image: none; border-right-width: 0px; margin: 3px 3px 0px 7px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.najmanowicz.com/wp-content/uploads/2011/05/image_thumb.png" width="244" height="200" /></a></p>
<p><span id="more-272"></span>
<p align="center"></p>
<h2 align="left">Additional changes in this version</h2>
<p>Scripts now have access to 3 starting predefined variables:</p>
<table border="1" cellspacing="1" cellpadding="5" width="5">
<tbody>
<tr>
<td valign="top" width="34%">
<p><b>Name</b></p>
</td>
<td valign="top" width="65%">
<p>Sample value</p>
</td>
</tr>
<tr>
<td valign="top" width="34%">
<p>$AppPath</p>
</td>
<td valign="top" width="65%">
<p>C:\EPiServer\Sites\ExampleEPiServerSite3\</p>
</td>
</tr>
<tr>
<td valign="top" width="34%">
<p>$AppVPath</p>
</td>
<td valign="top" width="65%">
<p>/ (app virtual folder)</p>
</td>
</tr>
<tr>
<td valign="top" width="34%">
<p>$tempPath</p>
</td>
<td valign="top" width="65%">
<p>C:\Windows\TEMP</p>
</td>
</tr>
<tr>
<td valign="top" width="34%">
<p>$tmpPath</p>
</td>
<td valign="top" width="65%">
<p>C:\Windows\TEMP</p>
</td>
</tr>
</tbody>
</table>
<p>and 1 more PowerShell Function have been defined: <strong>Reset-Application</strong>.</p>
<p align="center"><a title="Download Powershell console for Cheat Sheet 1" href="http://www.najmanowicz.com/blog_bin/Cognifide.EPiserverControls.PowerShell.AdminMode.zip" target="_blank">[Download &amp; Enjoy]</a></p>
<p align="center"><strong>Includes 3 bonus script collections!</strong></p>
<h2>How to install?</h2>
<p>Extract the DLL form the ZIP file into the BIN folder of your web application to install the plugin. Remove the DLL to uninstall it.</p>
<p>All feedback appreciated!</p>
<p><font color="#ff0000"><strong>Disclaimer – Responsibility</strong>: <em>With great powers comes great responsibility – this tool can do a lot of harm to a lot of content in a very short time – backup your system before using the plugin! I will not be held responsible for any use of it. Test your scripts on your development server first! Test on an exact copy of production before running scripts on production content. </em></font></p>
<p><font color="#ff0000"><strong>Disclaimer – Security</strong>: <em>While the tool requires a membership in either the “WebAdmin” or “Administrators” group, to execute, protect it with a &lt;location&gt; entry in web.config, to add another layer of security especially if your administration UI is exposed to the public. Manage your group memberships &amp; rights responsibly!</em></font></p>
<img src="http://blog.najmanowicz.com/?ak_action=api_record_view&id=272&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.najmanowicz.com/2011/05/07/episerver-admin-mode-powershell-scripts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Context PowerShell Scripts in EPiServer</title>
		<link>http://blog.najmanowicz.com/2011/05/04/context-powershell-scripts-in-episerver/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=context-powershell-scripts-in-episerver</link>
		<comments>http://blog.najmanowicz.com/2011/05/04/context-powershell-scripts-in-episerver/#comments</comments>
		<pubDate>Wed, 04 May 2011 06:00:00 +0000</pubDate>
		<dc:creator>Adam Najmanowicz</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[CMS UX]]></category>
		<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Solution]]></category>
		<category><![CDATA[Web applications]]></category>

		<guid isPermaLink="false">http://blog.najmanowicz.com/?p=225</guid>
		<description><![CDATA[Ok, so I’ve got my shot of endorphins writing about PowerShell last week (damn, it’s nice to be able to code again!), and I got pretty determined on making it usable and achieving all the goals I’ve initially envisioned. and in the process build a usable tool and a library of scripts that people can [...]]]></description>
			<content:encoded><![CDATA[<p>Ok, so I’ve got my shot of endorphins writing about PowerShell last week (damn, it’s nice to be able to code again!), and I got pretty determined on making it usable and achieving all the goals I’ve initially envisioned. and in the process build a usable tool and a library of scripts that people can use either directly or to modify to meet their needs.</p>
<p>The goal for this week: <strong>Context Scripts</strong></p>
<p>Context scripts are the first step to break the scripting out of the admin realm and into the editor’s space. Those scripts will still be written by admins and developers but the goal is for them to be usable by the authors. The goal for those scripts can be as trivial as e.g. syndicating all the great functionality little plugins like this <a title="Unpublish button by Ted" href="http://labs.episerver.com/en/Blogs/Ted-Nyberg/Dates/2009/2/Adding-a-custom-plugin-button-to-unpublish-a-page-in-EPiServer/" rel="nofollow" target="_blank">Unpublish button by Ted</a> in one place and then mix and match them to your liking.</p>
<p>Some of the important bits:</p>
<ul>
<li>Context scripts are something that is visible to users on “Scripts” page. </li>
<li>Scripts can be exposed to everyone or just the groups of your liking… you define it in the script. </li>
<li>Scripts are grouped in collections that are defined in *.psepi files that you drop into your application folder </li>
</ul>
<h2>How do I define a script collection?</h2>
<p><span id="more-225"></span><br />
<h2></h2>
<p>Each script collection is defined within a single .psepi file. A sample script can look as follows:</p>
<pre class="xml" name="code">

&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;ContextScriptCollection&gt;
  &lt;Title&gt;Statistics Scripts&lt;/Title&gt;
  &lt;Description&gt;This is a sample script collection allows for calculating some interesting stats for the branch you're in.&lt;/Description&gt;
  &lt;Scripts&gt;
    &lt;ContextScript&gt;
      &lt;Title&gt;Author Statistics&lt;/Title&gt;
      &lt;Description&gt;Click to Learn more about how many pages under this one were created by which authors.&lt;/Description&gt;
      &lt;Script&gt;get-childitem -recurse | Group-Object  ChangedBy | Sort count -descending | format-table -property count, name&lt;/Script&gt;
        &lt;Icon&gt;/App_Themes/Default/Images/Tools/AddUser.gif&lt;/Icon&gt;
        &lt;Warning&gt;This script only calculates statistics so it does not really need a warning but let’s show it anyway. Do you want to calculate them?&lt;/Warning&gt;
      &lt;Groups&gt;
        &lt;string&gt;WebAdmins&lt;/string&gt;
        &lt;string&gt;Administrators&lt;/string&gt;
      &lt;/Groups&gt;
    &lt;/ContextScript&gt;
  &lt;/Scripts&gt;
&lt;/ContextScriptCollection&gt;

</pre>
<p>What does each of the tags mean?</p>
<ul>
<li><strong>Title</strong> &amp; <strong>Description</strong> on <strong>ContextScriptCollection</strong> are going to appear at the top of the list for the collection – pretty self explanatory. </li>
<li><strong>Scripts</strong> is a container for <strong>ContentScript</strong> tags, it can contain any number of them. </li>
<li>Each <strong>ContentScript</strong> tag represent a single script, where <strong>Title</strong> is what will appear on the button that the user will click to execute the script. </li>
<li><strong>Script</strong> tag contains the script body – this is where you put the code that will get executed </li>
<li><strong>Icon</strong> is a URL to an image that will appear on the button left of the button title. </li>
<li><strong>Warning</strong> tag contains a question that will get presented to the user before the script will be executed. This tag can be omitted in which case no warning will be shown. A rule of thumb would be that you should show a warning before a long running scripts and scripts that modify content so a user can back away from a mistakenly pressed button. </li>
<li><strong>Groups</strong> tag contains the list of groups that will have the right to see the script. if that tag is empty, all users will see the script. If you define at least one group, you need to define all groups that you want to see the button. </li>
</ul>
<h2>What does “Context” in Context scripts mean?</h2>
<p>Basically since we cannot show the editor a console and let them navigate to the page (for various reasons, like complexity and potential destructive powers <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.najmanowicz.com/wp-content/uploads/2011/05/wlEmoticon-smile.png" />) The scripting environment will put your script “in the current page” before releasing control to your script, which in essence is equivalent to typing before your script.</p>
<pre class="ps1">cd MyCMSDrive:\
cd /path/to/my/page/</pre>
<p>That means that your script can get access to the page the user is currently on simply by using the “get-item .” command or enumerate its children by use of “get-childitem” etc. in the case of the script above it calculates author statistics for the branch it is executed in. Pretty cool, huh? ;)</p>
<p>Additionally I’ve realized in the process of duplicating/extending the functionality of <a title="Unpublish button by Ted" href="http://labs.episerver.com/en/Blogs/Ted-Nyberg/Dates/2009/2/Adding-a-custom-plugin-button-to-unpublish-a-page-in-EPiServer/" rel="nofollow" target="_blank">Ted’s plugin</a> that modifying standard EPiServer properties is not necessarily very intuitive, hence I’ve created a few macros to help me with the scripting exercises. While I still need to call “CreateWritableClone” I’ve simplified the saving of a page by defining the “<strong>Save-Page</strong>” function and created a <strong>Get-CurrentPage</strong> as an alias to “get-item .”. So a following script unpublishes the current page:</p>
<pre class="ps1"><b>Get-CurrentPage</b> | foreach-object {
$writable = $_.CreateWritableClone();
$writable.StopPublish = [DateTime]::Now;
Save-Page($writable);
}</pre>
<p>While this one unpublishes all of its children</p>
<pre class="ps1"><b>get-childitem -recurse</b> | foreach-object {
$writable = $_.CreateWritableClone();
$writable.StopPublish = [DateTime]::Now;
Save-Page($writable);
}</pre>
<p>Notice the subtle difference in the script and the major difference in the effect? Pure PowerShell magic!</p>
<p>To be honest I was amused to find out that during the whole process I’ve still not broken the CMS 5 compatibility, but I don’t expect it to stay this way in the future.</p>
<p align="center"><a href="http://blog.najmanowicz.com/wp-content/uploads/2011/05/EPiServer5ContextScript.png" rel="lightbox[225]" title="EPiServer5ContextScript"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="EPiServer5ContextScript" border="0" alt="EPiServer5ContextScript" src="http://blog.najmanowicz.com/wp-content/uploads/2011/05/EPiServer5ContextScript_thumb.png" width="244" height="201" /></a>&#160;&#160;&#160; <a href="http://blog.najmanowicz.com/wp-content/uploads/2011/05/EPiServer6ContextScript.png" rel="lightbox[225]" title="EPiServer6ContextScript"><img style="background-image: none; border-right-width: 0px; margin: 3px 3px 0px 7px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="EPiServer6ContextScript" border="0" alt="EPiServer6ContextScript" src="http://blog.najmanowicz.com/wp-content/uploads/2011/05/EPiServer6ContextScript_thumb.png" width="244" height="204" /></a></p>
<p>Also at this moment you can add and remove the *.psepi files at any moment as the files are parsed on every request, if that proves to be a problem in the future, caching will get introduced. At this moment I don’t find it a problem as it only happens in edit mode.</p>
<p align="center"><a title="Download Powershell console with context script support" href="http://www.najmanowicz.com/blog_bin/Cognifide.EPiserverControls.PowerShell.Context.zip" target="_blank">[Download &amp; Enjoy]</a></p>
<p>Includes 2 bonus script collections!</p>
<h2>How to install?</h2>
<p>Extract the DLL form the ZIP file into the BIN folder of your web application to install the plugin. Remove the DLL to uninstall it.</p>
<p>All constructive feedback appreciated!</p>
<p><font color="#ff0000"><strong>Disclaimer – Responsibility</strong>: <em>With great powers comes great responsibility – this tool can do a lot of harm to a lot of content in a very short time – backup your system before using the plugin! I will not be held responsible for any use of it. Test your scripts on your development server first! Test on an exact copy of production before running scripts on production content. </em></font></p>
<p><font color="#ff0000"><strong>Disclaimer – Security</strong>: <em>While the tool requires a membership in either the “WebAdmin” or “Administrators” group, to execute, protect it with a &lt;location&gt; entry in web.config, to add another layer of security especially if your administration UI is exposed to the public. Manage your group memberships &amp; rights responsibly!</em></font></p>
<style type="text/css">
pre.ps1
{
        padding: 4px; 
        margin: 4px 0 4px 0;
        overflow: auto;
        background-color: #012456; 
        border: thin solid #aaa;
        color:#fff;
        font-weight:900;
        width: 95%;
        border: solid #000 1px;
}
</style>
<img src="http://blog.najmanowicz.com/?ak_action=api_record_view&id=225&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.najmanowicz.com/2011/05/04/context-powershell-scripts-in-episerver/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

