<?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>Huddled Masses &#187; Localization</title>
	<atom:link href="http://huddledmasses.org/tag/localization/feed/" rel="self" type="application/rss+xml" />
	<link>http://huddledmasses.org</link>
	<description>You can do more than breathe for free...</description>
	<lastBuildDate>Fri, 27 Apr 2012 05:42:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
<cloud domain='huddledmasses.org' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
		<item>
		<title>(Mis)using &#8220;Localizable Data&#8221; to force users to set variables</title>
		<link>http://huddledmasses.org/misusing-powershell-localizable-data/</link>
		<comments>http://huddledmasses.org/misusing-powershell-localizable-data/#comments</comments>
		<pubDate>Sun, 13 Jul 2008 02:49:22 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Configuration]]></category>
		<category><![CDATA[Data]]></category>
		<category><![CDATA[Localization]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://HuddledMasses.org/?p=566</guid>
		<description><![CDATA[Have you ever written a program or a script where there&#8217;s a setting which has to be set by the user the first time the app is run? With applications, we just show the configuration UI when it&#8217;s run for the first time, but how about with PowerShell scripts? Well, in PowerShell 2 (CTP2), there [...]]]></description>
			<content:encoded><![CDATA[	<p>Have you ever written a program or a script where there&#8217;s a setting which <strong>has</strong> to be set by the user the first time the app is run?  With applications, we just show the configuration UI when it&#8217;s run for the first time, but how about with PowerShell scripts?  Well, in <span class="em2">PowerShell 2 (CTP2), there is a way&#8230;</span></p>

	<h4>Back Story (or, An Example)</h4>

	<p>I&#8217;ve written a <a href="http://poshcode.org/464">Authenticode.psm1</a> script module for PowerShell which is primarily a wrapper which causes the Set-AuthenticodeSignature and Get-AuthenticodeSignature cmdlets to work the way I think they should.  Basically, they take files from the pipeline without complaining, and if they accidentally hit a folder, they throw an error <strong>but keep on processing</strong> other pipeline elements (the built-in cmdlets throw an exception and die in such an ugly way that they stop the whole pipeline).</p>

	<p>Anyway, I also added a couple of features: a <code>Test-Signature</code> filter which returns true if a cert has a valid hash-match &#8212; even if the certificate can&#8217;t be traced to a valid CA(Certificate Authority), and a <code>Select-Signed</code> filter which has about 7 different switches to let you pick out scripts and files which are signed by you, by other, signed but broken, signed by trusted certs, signed by untrusted certs, etc.  I use that filter to re-sign the scripts in my <a href="http://huddledmasses.org/getting-started-with-powershell-2-part-2/">AutoModules directory</a> when I&#8217;ve touched a bunch of files, so I can re-sign just the ones that I&#8217;ve previously signed, but which are currently broken.</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #660033;">ls</span> <span style="color: #660033; font-weight: bold;">$ProfileDir</span>\AutoModules <span style="color: #000066;">-recurse</span> <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Select-<span style="font-style: normal;">Signed</span></span> <span style="color: #000066;">-mine</span> <span style="color: #000066;">-broken</span> <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Set-<span style="font-style: normal;">AuthenticodeSignature</span></span><br />
&nbsp;</div>

	<p>Of course, on my computer, I don&#8217;t want to have to specify the certificate path every time, so in my wrapper scripts, I created a $DefaultCertificate variable, which I need each user to to set when they take my script to their computer.  In the <a href="http://poshcode.org/456">previous version</a> I just set it as a variable, and considered that good enough, but it occurred to me that if people forgot to change it, they would see scripts signed by me as &#8220;valid&#8221; &#8212; which was not my intention.</p>

	<h3>Localizable Scripts</h3>

	<p>In version 2 (CTP2), PowerShell introduced the concept of a subset of the languages called the PowerShell Data language.  Basically, it&#8217;s just like PowerShell script, except you&#8217;re only allowed to use a couple of cmdlets, and non-expanding variables.  Essentially, this means you can set some variables to predefined values, and not a whole lot else.</p>

	<p>To make this data language localizable, there are a couple of data cmdlets: <code>ConvertFrom-StringData</code> and <code>Import-LocalizedData</code> &#8230; I&#8217;ll leave it up to you to read the help on those (use &#8220;Get-Help&#8221; in the PowerShell command line) and also the <strong>About_Script_Internationalization</strong> and <strong>About_Data_Section</strong> ...</p>

	<p>The simplest way to explain it is this: if your script uses Import-LocalizedData, PowerShell attempts to load a data file with the same name as your script, from a subfolder named the same as the output of <code>(Get-UICulture).Name</code>  (for US English, that is &#8220;en-US&#8221;), or <code>(Get-UICulture).Parent.Name</code> (again, for US English, that is &#8220;en&#8221;) ... if no file can be found, then it writes an error explaining where the file should have been located (but doesn&#8217;t throw an exception).</p>

	<p><span class="em2b">We can use this to create translatable text messages in our scripts, but we can also abuse it to require a settings file to be created</span>, although we&#8217;ll need to explain to the users what should go into that file.</p>

	<h4>Wrapping it up</h4>

	<p>In my Authenticode script module, I ended up forcing Import-LocalizedData to throw an error by setting it&#8217;s ErrorAction to &#8220;Stop&#8221; and then trapping the error to write a more verbose description of what the setting(s) are that the script needs.  I&#8217;m pretty sure there&#8217;s a better way to do this using the PSD1 data files, I just don&#8217;t know what it is.</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">trap</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;The authenticode script module requires a configuration file to function fully!&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;You must put the path to your default signing certificate in the configuration&quot;</span>`<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&quot;file before you can use the module's Set-Authenticode cmdlet or to the 'mine'&quot;</span>`<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&quot;feature of the Select-Signed or Test-Signature. To set it up, you can do this:&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;MkDir $(Join-Path $PsScriptRoot $(Get-Culture)) |&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot; &nbsp; Join-Path -Path {<span style="color: #000099; font-weight: bold;">`$</span>_} 'Authenticode.psd1' &nbsp; &nbsp;|&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot; &nbsp; New-Item &nbsp;-Path {<span style="color: #000099; font-weight: bold;">`$</span>_} -Type File -Value '<span style="color: #000099; font-weight: bold;">`&quot;</span>ThePathToYourCertificate<span style="color: #000099; font-weight: bold;">`&quot;</span>'&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;If you load your certificate into your 'CurrentUser\My' store, or put the .pfx file&quot;</span>`<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&quot;into the folder with the Authenthenticode module script, you can just specify it's&quot;</span>`<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&quot;thumprint or filename, respectively. Otherwise, it should be a full path.&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">return</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span> &nbsp; <br />
&nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Import-<span style="font-style: normal;">LocalizedData</span></span> <span style="color: #000066;">-bindingVariable</span> CertificatePath <span style="color: #000066;">-EA</span> <span style="color: #009900;">&quot;STOP&quot;</span><br />
&nbsp;</div>

	<p>As a postscript, I should mention: Although I only had a single value I wanted in the settings file, it&#8217;s simple to put more, just read those help files I mentioned earlier and you&#8217;ll see a lot of examples of it. It&#8217;s basically a matter of using the ConvertFrom-StringData cmdlet with a sort of hashtable &#8230; </p>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/misusing-powershell-localizable-data/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

