Tag Archives: powershell

Manage your DNS records with PowerShell

In my video course PowerShell 5 Recipes, I used the Dnsimple API as an example of writing PowerShell modules. In the course, I uploaded and made the library available in the PowerShell gallery. Even though it is not feature-complete with respect to the DNSimple API, it is still usable for the core parts of the API.

Getting started

In order to access the Dnsimple API, you need an access token. In order to create one, log in to the web page and generate one under

https://dnsimple.com/a/<account id>/account/access_tokens

For simplicity going forward, create a PowerShell object to hold the account id and the access token:

$account = [pscustomobject]@{Account=27928;AccessToken=(
convertto-securestring 'G2uiIZLhsHNWt4BFNq6Y8VnF1iRz2sB1' -asplaintext -for
ce)}

Then, the next step is to install the module from the PowerShell Gallery, and load it into the current PowerShell instance:

Find-Module DnsimplePS | Install-Module -Scope CurrentUser
Import-Module DnsimplePS

In order to check the available cmdlets, list them:

Get-Command -Module DnsimplePS

Listing, adding and removing Zone records

The simplest thing you can do, is to list the records for your domain:

$account | Get-ZoneRecord -Zone kongs.li

You can also search for records of a certain type (case-sensitive):

$account | Get-ZoneRecord -Zone kongs.li -RecordType MX

Or, you can get a certain record by name

$account | Get-ZoneRecord -Zone kongs.li -Name www

Or, you can match records by prefix using -NameLike:

$account | Get-ZoneRecord -Zone kongs.li -NameLike w

You can also add a record:

$account | Add-ZoneRecord -Zone kongs.li -RecordType URL `
  -Name dnsimple -Content https://dnsimple.com/

And you can delete a record:

$account | Remove-ZoneRecord -Zone kongs.li -Id 11601106

Storing your access token securely

In the getting started section above, I directed you to go to the DNSimple web page to get an access token. This is often not practical in automated scripts, so I provided a couple of cmdlets to store and retrieve an access token from a file, encrypted under the current user’s Windows credentials.

So, when you have retrieved the token from the web page, you can store it securely like so:

Write-AccessToken -AccessToken $t -Account 27928

This will create a file named .dnsimple.tokens next to your $PROFILE. The file will look something like this:


  
    
      Deserialized.System.Collections.Hashtable
      Deserialized.System.Object
    
    
      
        27928
        01000000d08c9ddf0115d1118c7a00c04fc297eb01000000fff8656bc71ed747aa82e30ddd65735a00000000020000000000106600000001000020000000e7dfc8caf9534e51b2e2eb56b6968171ceb6c6ce9c8a7d55193791a207ffc56a000000000e800000000200002000000066c532a677f69c0c478733114d01b4371577340b0051160d95a3728d07c466ca500000005bbf59cee4314675324296591beeadef7970fc4e8589fce2b5bd80c6b5368e5198da424d1554a269921da4f0c6ef02e50db416fe2b7cbe63f187eb91d94d759da11e63121142f7e8794079e1ea74040d40000000d3f2a0be38aaa111ce20eeba05bcabb594e62400658486ed1c4ec2fe027e5d7e0916bc797aba0a0c1325fd7d0043ba9c9754782f695bdafab8a627f2259636f4
      
    
  

If you want to place the file somewhere else, point to it using the -Path parameter.

Extra: URL-shortener

In order to show off PowerShell modules being dependent on other modules, I created a second module that was dependent on the DnsimplePS module. This module has one cmdlet which is a short-hand for the special case I showed above for adding a record.

It creates a URL type record, which is basically a redirect record that allows the creation of short urls.

Example:

$account | Add-ShortUrl -Zone kongs.li -Name dnsimple -Url https://dnsimple.com/

In the same vain, you can delete the url:

$account | Remove-ShortUrl -Zone kongs.li -Name dnsimple

My PowerShell video course is available!

For the last months, I have been working on my PowerShell 5 recipes video course. It is now finally published!

Why?

Why make a video course? – you might ask. I come from a system development background, having worked with many development platforms in my time (Java, .NET, Lotus Notes, JavaScript, etc.) Back in 2011, after resisted for a while, I decided to learn PowerShell. So I dived in, head first. Why? Because I realized that in order to get a better delivery process for software, we need a broader scope than just the development per se. We need to get a holistic view of the environment the applications will run in, and we need to automate the deployment. This has become more and more evident with the coming of DevOps and is key to continuous delivery.

I am first and foremost a PowerShell user, and I do not consider myself an expert. Maybe a little more advanced than the average user, though. When the opportunity came to create a video course, the temptation to do something new to me as too hard to resist. I hope I have been able to keep the view of the user, resulting in a pragmatic, hands-on, course.

For whom?

The course is thought to be a smorgasbord of relevant topics in PowerShell that is relevant to the daily work of developers as well as IT. For people new to PowerShell, it will get you started by installing, and/or upgrading to the latest versions (even on Linux), customize, and set up the environment for your preferences. For developers, it gives you hands-on guidance to set up automated build and deployment. For DevOps (and IT), it guides you in provisioning Azure resources. For more advanced users, it gives you recipes on how to develop reusable scripts, handle modules and publishing your scripts to repositories.

Enjoy!

Slå opp i ordbøkene fra Powershell

Å bruke kommandolinjen er kjapt. Hvis du ønsker å slå opp i Bokmålsordboka eller Nynorskordboka på nett, kan du nå gjøre det fra Powershell. Slik konfigurerer du dette:

Hvis du ikke har det fra før, installér programvarepakkesystemet Scoop:

iex (new-object net.webclient).downloadstring('https://get.scoop.sh')

Neste steg er å legge til denne kilden til programvare:

scoop install git-with-openssh
scoop bucket add vidars https://github.com/vidarkongsli/vidars-scoop-bucket.git

Dernest installerer du pakken `norskord`:

scoop install norskord

Når du har gjort dette, er du klar! Slik slår du opp i Bokmålsordboka:

bokm omkostning

Tilsvarende kan du søke i Nynorskordboka:

nyn bevegelse

Språk-nerd? Ja.

(Edit: fikset installeringsskript etter innspill fra Discus:@yngvar)

Hello, Azure Scheduler

The Scheduler is one of the new kids on the block in Azure Land. With Scheduler you can set up triggers for some sort of event in your system. It is currently in preview. I took some time to get to know the basics of it, and I wrote up a three part series of articles. You can find the articles in my company’s blog:

Powershell gotchas: calling a function

Consider the following code:

function f($a, $b, $c) {
	"f: `$a=$a, `$a.GetType()=$($a.GetType())"
	"f: `$b=$b, `$b.GetType()=$($b.GetType())"
	"f: `$c=$c, `$c.GetType()=$($c.GetType())"
}
f 1 2 3   # call f with three integers as parameters
f 1,2,3   # call f with an array of three integers
f (1,2,3) # as above

The gotcha here is not to fall into the trap to use a C#-like or Java(Script)-like syntax where parameters are separated by commas. The comma in Powershell is always an array constructor operator, and takes precedence over function application. (Which also means that adding paranthesis will yield the same result). The code above will result in:

f: $a=1, $a.GetType()=int
f: $b=2, $b.GetType()=int
f: $c=3, $c.GetType()=int
f: $a=1 2 3, $a.GetType()=System.Object[]
You cannot call a method on a null-valued expression.
At ...function-application.ps1:4 char:11
+ $b.GetType <<<< ()
    + CategoryInfo          : InvalidOperation: (GetType:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull
f: $b=, $b.GetType()=
You cannot call a method on a null-valued expression.
At ...function-application.ps1:5 char:11
+ $c.GetType <<<< ()
    + CategoryInfo          : InvalidOperation: (GetType:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull
f: $c=, $c.GetType()=
f: $a=1 2 3, $a.GetType()=System.Object[]
You cannot call a method on a null-valued expression.
At ...function-application.ps1:4 char:11
+ $b.GetType <<<< ()
    + CategoryInfo          : InvalidOperation: (GetType:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull
f: $b=, $b.GetType()=
You cannot call a method on a null-valued expression.
At ...function-application.ps1:5 char:11
+ $c.GetType <<<< ()
    + CategoryInfo          : InvalidOperation: (GetType:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull
f: $c=, $c.GetType()=

Powershell gotchas: standard out breaks lines to fit console

When Powershell writes to standard out, and there is now redirection in the Powershell script itself, it will assume that it writes to a console. Because of this, it kindly breaks lines if they are longer than 80 characters. So, given the following powershell file (.ps1):

# line-gunk.ps1
"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"

If you run this Powershell file from the Windows command line, and redirects output to a file:

C:>@powershell -file .line-gunk.ps1 > foo.txt

Then you will get:

1234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890

However, if you do the redirection in Powershell, it’s fine:

PS C:> .line-gunk.ps1 > bar.txt

A näive fix to this, would be to change your script to use Write-Host to explicity write the text to the console. However, I consider this a bad practice because it would restrict the usage of your script as you could not manipulate the output further if reusing the script. I found this entry on stackoverflow which provides a better solution. Going back to the original script, here is a fixed one that worked for me:

# line-gunk-fixed.ps1
$Host.UI.RawUI.BufferSize = New-Object Management.Automation.Host.Size(500, 25)
"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"

Notice that I used the simplifed version from the stackoverflow entry, which might not work in all circumstances.

Backstory

How did I come across this problem? I running Powershell build scripts in TeamCity and I was trying to report the build progress back to TeamCity. However, it somehow did not work. I then discovered that the status messages written by my script were broken by the line breaks, rendering them useless…

Running chocolatey behind an authenticating firewall

I long grappled with a problem installing applications using chocolatey. Specifically, all installations that required downloading an MSI (or similar) file outside the .nupkg caused the following error message:

The remote server returned an error: (407) Proxy Authentication Required.

Yes, I am behind a firewall that requires authentication. I found several references to this error message on the chocolatey forums, but they all seemed to be fixed in the latest chocolatey version.

Through some googling I was able to track down the problem. Acutally, it is a problem with the .NET 3.5 runtime that causes the System.Net.WebClient to give up on an NTLM authentication challenge from proxies. Chocolatey uses Powershell, and indeed the System.Net.WebClient to download installation packages (all though not the package manifest itself, where it uses NuGet). As you my or may not know, Powershell uses the .NET 3.5 runtime per default.

Hence, the fix was to make Powershell use the .NET 4.0 runtime, where this bug is fixed. I figured out how to do this based on this entry on stackoverflow.

I then wrote this little Powershell snippet which changes Powershell on my machine to use .NET 4.0 instead of .NET 3.5:

if ([Environment]::Version.Major -lt 4) {
	$configFile = Join-Path $PSHOME -ChildPath '.powershell.exe.config'
	if (-not(Test-Path $configFile)) {
		@'
<?xml version="1.0"?>
<configuration>
  <startup useLegacyV2RuntimeActivationPolicy="true">
    <supportedRuntime version="v4.0.30319" />
    <supportedRuntime version="v2.0.50727" />
  </startup>
</configuration>
'@ | Out-File -FilePath $configFile -Encoding UTF8
		"Created $configFile"
	}
	'Restart powershell in order to make it run in .NET 4'
}

Powershell: another alternative to ternary operator

In C# (as well as in Java and C++), you can use the ternary operator (?:) for a shorthand notation for conditionally assigning a value:

var index = (a == "a") ? 1 : 2;

In Powershell, such an operator is (to my knowledge) not available. One solution is described here. As an alternative without having to create a function and alias, I suggest:

$index = @{$true=1;$false=2}[$a -eq 'a']

Mmmmm, one-liner FTW 🙂