Contact

Subscribe via Email

Subscribe via RSS/JSON

Categories

Recent Posts

Creative Commons Attribution 4.0 International License
© Rakhesh Sasidharan

Elsewhere

Windows ignores the hosts file

If you find that Windows ignores your hosts file try the following: open the file, select save as, and while saving it change encoding from Unicode (or whatever it is) to ANSI. Be sure to select the file type as “All files” so Notepad doesn’t append a “.txt” to the file name (and double check after saving as sometimes Notepad still appends a “.txt”).

How is this PowerShell related?

I was using Out-File to put something into the hosts file. Windows expects the hosts file to be in ANSI encoding – and seems to ignore it otherwise – but Out-File uses Unicode encoding by default; so the net result is that Windows ignores the resulting hosts file. Even if I removed all the entries in it and made fresh ones for testing, since the file is still in Unicode encoding Windows ignores it. Finally, thanks to a great post I figured a workaround which led to realizing the problem.

Moral of the story: when writing to the hosts file using Out-File specify the encoding as ASCII. Like thus:

And if you are a PowerShell geek, you can avoid the longish method above of changing the hosts file type to ANSI through something like this:

Easy peasy!

Convert a bunch of VHD files to VHDX

Here’s how to convert a bunch of VHD files in a directory to VHDX. The actual conversion process uses the Convert-VHD cmdlet so you need to be on Windows 8 or Windows Server 2012.

I am storing all the VHDX files at “C:\Hyper-V\Virtual Hard Disks” which is why I put the path there. If you’d rather put the VHDX files in the same location as the VHD files use the following instead:

Note to self: If you convert the objects returned by Get-Item to string (by doing $_) you get the file name with the full path (this is equivalent to $_.FullName). If you want just the file name, use $_.Name. If you want the file name only, without the extension, use $_.BaseName; and if you want the extension only but not the file name use $_.Extension.

Extract a variable from a bunch of files

I have a couple of TXT files. They contain some text, along with a line like this:

The version number keeps changing.

I want to list all these files along with the value of $version in that file. Here’s how:

The result is something like this:

It’s pretty straight-forward what I am doing. I use Get-Item to get all the TXT files. Pipe it to a ForEach-Object loop. Within that I use the Get-Content cmdlet to get the contents of the file. I could have stored the contents in a variable and then done the remaining bits, instead I send it directly to the -match operator to get out lines that contain the pattern I am looking for. After this I replace the line to extract the numbers between double-quotes and store that in a variable. Finally I output the file name and the version (only if a version was found).

The two patterns pattern took me a while to figure out so I’ll delve a bit more into it here. I use a similar pattern for the -match and -replace operators so my comments here apply to both. The patterns are pretty straight-forward but for the fact that I need to match symbols such as dollar ($) and double-quotes (“). That in itself is not a hassle as I can escape them and match as $ or ” but that didn’t work in my case. I kept getting errors like this:

Why does this happen? Thanks to a Stack Overflow post I got the answer. What happens is that although I escape the $ as $ within the regular expression, since $ is a special character for PowerShell (variable names) it clubs the $ with the word “version” and treats it as a variable $version. And since this variable isn’t defined, it expands to an empty string which PowerShell passes to the -match operator as the pattern “^”. This pattern doesn’t make sense and so we get the error above.

Workaround is to double escape the $ symbol. As `$. If we do that I get the following error:

Not sure why I get an error here. The period character is an operator in PowerShell, and since the error points to that something roundabouts the period operator is confusing PowerShell. Ideally the whole pattern ^`$version = ".*" should be passed to the -match operator, but PowerShell only seems to be passing ^`$version = and using the period as a deference operator to that string. Which of course will not work because the left hand side is a string and not an object, but also because the right hand side *"$" is not a property name. So again it looks to be similar to the earlier error. The double quotes are being usurped by PowerShell first, before passing to the -match operator, and so they too need to be double escaped.

Hence I use the pattern ^`$version.* for the -match operator and the pattern ^`$version = `"(.+)`"$ for the -replace operator. Double-escaping the $ and ” characters.