Notes from Daily Encounters with Technology RSS 2.0
 
# Saturday, January 31, 2015

On Tuesday Microsoft Slovenia organized the second TechDays event leading up to the 20th NT conference which is returning to Portorož in May this year. The event consisted of 4 tracks; I had the opening session for the Visual Studio 2015 track.

After the introductory mention of Visual Studio Community 2013, I focused on an overview of new features from the publicly available Visual Studio 2015 Preview:

  • .NET Compiler Platform (formerly known as Roslyn) and changes to the editor
  • first look at NuGet 3
  • improvements to shared projects
  • Smart Unit Tests, a production-ready of Microsoft Research project Pex

The features which I skipped where covered in subsequent sessions by other speakers: support for development in Cordova, diagnostics, debugging, and Visual Studio Online.

As always slides and demos from my session are available for download.

I hope the attendees enjoyed the event as much as I did as a speaker. I'm already looking forward to Portorož.

Saturday, January 31, 2015 3:25:37 PM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Development | C# | NuGet | Testing | Downloads | Presentations | Software | VisualStudio
# Sunday, January 25, 2015

For some reason display drivers for both NVIDIA and AMD graphics cards have a tendency to scale image to full panel size instead of keeping the default aspect ratio. If you don't like to see your image stretched, you can change the behavior in the corresponding control panel (NVIDIA Control Panel or AMD Catalyst Control Center, respectively). The setting also doesn't persist reliably across driver updates, so it needs to be reconfigured occasionally even if it was previously set correctly.

On top of that after recent driver updates both control panel applications got broken somehow on two desktop machines I'm taking care of:

  • The NVIDIA one failed to show most of the settings - only Stereoscopic 3D settings were available in the tree view; nothing else.
  • The AMD one was just reverting the settings to their previous value immediately after applying them.

Today I decided to get to the bottom of the issue and finally correctly configure the driver again.

It seems NVIDIA Control Panel doesn't play well with other display drivers installed on the machine. Based on this information I tried to disconnect my USB monitor and it helped: all of the configuration options were available again. Obviously NVIDIA drivers don't coexist well with DisplayLink ones, required by the USB monitor.

Once the missing settings in the control panel reappeared, configuring them correctly is pretty trivial:

  1. Open Display > Adjust desktop size and position from the tree view.
  2. Select the display you want to configure.
  3. Set scaling mode to aspect ratio.
  4. Set scaling to be performed on GPU.
  5. Override the scaling mode set by games and programs.

This is how the end result in the current version of NVIDIA Control Panel:

Image Scaling Settings in NVIDIA Control Panel

AMD recently released a new generation of their display drivers: AMD Catalyst Omega. After the upgrade changing the scaling settings in AMD Catalyst Control Center didn't seem to have any effect any more. Fortunately I wasn't the only one having this issue. As suggested in the post, I removed my display adapter from Windows Device Manager, selecting to delete the drivers as well.

Reinstalling the latest drivers after doing that fixed the issue, making it possible to apply the required configuration:

  1. Select My Digital Flat-Panels > Properties (Digital Flat-Panel) in the navigation pane on the left.
  2. Select the display you want to configure.
  3. Enable GPU up-scaling.
  4. Select Maintain aspect ratio as Preferred Scaling Mode.

This is a screenshot of the final settings from the current version of AMD Catalyst Control Center:

AmdCatalystControlCenter

Sunday, January 25, 2015 1:49:44 PM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Software | Windows
# Saturday, January 17, 2015

Windows Store apps offer two containers for storing application settings as key-value pairs: ApplicationData.LocalSettings and ApplicationData.RoamingSettings. API for both is the same; the only difference between them is, how the settings are persisted: locally only or are they roamed across all user's devices.

If you've done any Windows Store development, you might already now that all application data from Windows Store apps is saved to Local\Packages inside user's AppData folder (usually C:\Users\Username\AppData). Each application has its own subfolder there; its name is concatenated from the application package name and a signing certificate based postfix. Of course, you can find the settings there as well: there's a settings.dat file inside the Settings subfolder.

A couple of times I've already wondered about the format of this file, but a recent question on Stack Overflow has encouraged me to finally get to the bottom of this mystery. The question already hinted at the file being a registry hive file and soon enough I found a blog post describing its contents in detail. You can read all the details there; here are just the most important bits for this blog post:

  • Settings are stored as values, grouped under two separate keys: LocalState and RoamingState.
  • The values are encoded as binary data; strings are null terminated and use UTF-16 encoding.
  • All values have an 8 bytes long postfix - a timestamp of some kind.
  • Value types are non-standard and include information about the data type.

Based on this information you can change the settings from outside the Windows Store app, as long as you have access to its settings.dat file:

  • Run Windows Registry Editor (regedit.exe).
  • Select HKEY_LOCAL_MACHINE or HKEY_USERS in the tree view, navigate to the File > Load Hive... menu item and select the settings.dat file you're interested in. Type in the name of the root key for the hive to be loaded.
  • For each setting you want to change, navigate to it, double click it and enter its new value.
  • Once you're done, select the root key of the hive you have loaded and navigate to the File > Unload Hive... menu item to unload it.

As already mentioned, the values are unfortunately binary encoded which makes them difficult to edit by hand. Having a way to do it programmatically would make it much easier.

There doesn't seem to be a way to modify a registry hive file, without having it loaded in the registry. This means the first step of the programmatic solution will be loading the file into the registry and the last step will be unloading it again. This can be done using the Reg command:

reg load HKLM\_Settings .\settings.dat
reg unload HKLM\_Settings

Both PowerShell and .NET Framework have APIs for reading and writing registry values. They probably both use the same underlying APIs as they both have problems with non-standard value types:

  • Trying to read the values fails; the method just returns the default value passed to it as a parameter.
  • Writing a value succeeds but changes the value type to REG_SZ, i.e. string. This breaks the code inside the Windows Store app.

The only way I've found to manipulate values of non-standard types, takes advantage of .reg registry files for exchanging registry settings in text format. To export our settings into a .reg file and to import the modified file back into registry, Reg command can be used again:

reg load HKLM\_Settings .\settings.dat
reg unload HKLM\_Settings

If you take a look at the exported file, it looks very familiar to an .ini file:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\_TMP]

[HKEY_LOCAL_MACHINE\_TMP\LocalState]
"Test"=hex(5f5e10c):4f,00,6c,00,64,00,20,00,76,00,61,00,6c,00,75,00,65,00,00,\
  00,42,fe,6f,ec,38,32,d0,01

[HKEY_LOCAL_MACHINE\_TMP\RoamingState]

After a closer look it becomes obvious, this is not the case. There's a non-comment line at the top and values can span across multiple lines. Using existing APIs for handling .ini files is therefore not an option.

Creating a fully fledged parser for .reg files is not a trivial task, but if you only want to change a single value inside it, this can be done in only a few simple steps:

  • Read the file line by line until you get to the value you want to change. Copy them verbatim to the output.
  • The corresponding line will start with the value name in quotes, followed by an equality sign. Change the value in this line as required.
  • Copy all the remaining lines to the output unchanged.

Here's a simple PowerShell script to do this:

$fileContents = Get-Content .\settings.reg

$finalContents = @()
Foreach ($line in $fileContents)
{
    If ($line.StartsWith("""SettingName""="))
    {
        # set the new value 
        $finalContents += """SettingName""=$newValue"
    }
    Else
    {
        $finalContents += $line
    }
}

$finalContents | Out-File .\settings.reg

Since a value can span multiple lines, this needs to be taken into account: all lines belonging to the value we're changing need to be replaced by a single line with the new value. There's no need to write a value in multiple lines even if it is long. To achieve this, the loop now needs to keep track whether the lines belong to the one we're changing or not (for brevity irrelevant parts of the script above are skipped):

$processing = $false
Foreach ($line in $fileContents)
{
    If (-Not ($processing))
    {
        # scanning for first line of the value
        If ($line.StartsWith("""SettingName""="))
        {
            # found - switch mode and start reading the old value 
            $processing = $true
            $oldValue = $line.Replace("""SettingName""=", "")
        }
        Else
        {
            # not found yet - copy to output
            $finalContents += $line
        }
    }
    Else
    {
        # non-first lines have leading spaces
        $oldValue += $line.TrimStart(" ")
    }

    If ($processing)
    {
        # scanning for last line of the value
        If ($oldValue.EndsWith("\"))
        {
            # strip trailing backslash; the value continues
            $oldValue = $oldValue.TrimEnd("\")
        }
        Else
        {
            # no backslash; the value is complete
            $finalContents += """SettingName""=$newValue"
            $processing = $false
        }
    }
}

The new serialized value will need to keep the value type and the last 8 bytes containing the timestamp; that's why we needed to read the old value:

$match = $oldValue -match '(.*:)(.*)'

$valueType = $matches[1]
$timestamp = $matches[2].Substring($matches[2].Length - 23)

# serialize the new value and compose it with the extracted prefix and postfix
$newValue = $valueType + $serializedValue + $timestamp

The only remaining part of the script is the serialization of the new value. Here's how to do it for strings; numeric data types are even simpler:

$utfEncoded = [System.Text.Encoding]::Unicode.GetBytes("New value")

Foreach ($byte in $utfEncoded)
{
    $serializedValue += [System.Convert]::ToString($byte, 16).PadLeft(2, "0") + ","
}

# append null terminator
$serializedValue += "00,00,"

I've wrapped all the code in an easy to use PowerShell function and published it as a Gist. It's still a bit rough and doesn't work in all cases, so feel free to fork it and improve it further. Don't forget to run it as administrator or reg load will fail due to insufficient privileges.

Saturday, January 17, 2015 4:43:08 PM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Development | Metro | Scripting | Windows Store
# Monday, January 12, 2015

Simon Timms: Mastering JavaScript Design PatternsIn the latest batch of new books from Packt Publishing, Mastering JavaScript Design Patterns by Simon Timms attracted my attention the most and as such warranted my review. Now that I finished the book, I don't regret my decision even a little, the author did a great job and this well written book exceeded my expectations.

I was really glad to see that it's actually more than just a book about design patterns. It does a great job at introducing JavaScript as a language from all aspects. From a brief history of this controversial language it quickly dives into its most important specifics which tend to elude the developers coming from other languages such as Java or C#. This serves as a great way to make the book easier to follow even for those with less experience in JavaScript.

The title makes it clear that the majority of the book is focusing on software design patterns. The first part is dedicated to the well known patterns from the classical "Gang of Four" book, but instead of just rehashing its contents, the author takes a different approach and reevaluates the meaning of the same design patterns in a dynamic language like JavaScript in contrast to the object oriented languages from the original book.

The reading gets even more interesting in the second part, which moves on to the more recent design patterns, grouped into different fields of interest: functional programming, automated testing, user interface, web and messaging. Each and every design pattern is introduced in a broader context, with a discussion of its advantages and drawbacks. Most of them are even accompanied by interesting examples from the lively world of A Song of Ice and Fire. At the very end a couple of words are dedicated to the broader topic of dependency injection, aspect-oriented programming and macros, each one of them deserving a book of its own.

With brief mentions interspersed throughout the book, the author also managed to give an overview of the libraries and tools in the current JavaScript ecosystem, without really favoring any of them. A special place among them is reserved toTypeScript and Traceur, 2 languages which extend the current JavaScript with features from its future version ECMAScript 6, but can be compiled back to valid JavaScript of today.

I can recommend the book not only to JavaScript developers, but also to others who want to refresh or expand their knowledge of design patterns. Learning some JavaScript in the process is just an additional benefit.

The book is available on Amazon and sold directly by the publisher.

Monday, January 12, 2015 6:45:09 AM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Development | JavaScript | Personal | Reviews
# Monday, January 5, 2015

AWStats is one of the most popular tools for generating web site statistics from server logs, and it's also the one I have selected as a replacement for Google Analytics. In spite of its extensive documentation, I've hit a couple of stumbling blocks while setting it up in my environment. As is often the case, I'm writing this blog post for future reference.

Since the application is written in Perl, it makes sense to install it first. There are a couple of distributions available for Windows. I decided to use ActiveState Perl. It's available as a standard MSI Installer package; which you only need to run with default settings. If perl.exe is available from command line after the installation, you can be sure it completed successfully.

The next step is downloading the latest version of AWStats. It's available in a couple of different formats, zip archive probably being the most handy of them in Windows. You only need to unpack it to a location, where IIS has access it. I've put it inside my C:\WWW folder. Now its time to go into AWStats' wwwroot\cgi-bin subfolder, make a copy of awstats.model.conf named awstats.damirscorner.conf (where damirscorner is the name of the site I'm generating statistics for), and start following AWStats' instructions on how to change it for your needs. I only had to change 2 settings:

  • Set LogFile to C:\WWW\_Logs\W3SVC4\u_ex%YY-4%MM-4%DD-4.log; this matches the location and the name pattern for the log files, created by IIS (e.g. u_ex150105.log for today). The -4 part for years, months and days makes AWStats look for a file matching the date from 4 hours ago. I chose this offset because I'm processing the logs for the previous day at 3 in the morning.
  • Set DirData to C:\WWW\awstats-7.3\wwwroot\stats\damirscorner; that's the location where I'm storing my processed statistics data. The target folder must be created manually.

AWStats can parse logs in almost any format, but its best to just select W3C log file format in IIS and include all the required fields, as shown in the following screenshot:

IIS Log Settings

If you have old log files you want to parse, now is the right time to do it. With the help of this StackOverflow answer, I've come up with the following steps:

  • Copy old log files into a separate folder (e.g. C:\OldLogs). Skip the log file for today as it will get parsed the next morning.
  • Open command prompt and go into tools subfolder of your AWStats installation.
  • Merge all old files into a single one by calling logresolvemerge.pl: perl logresolvemerge.pl C:\OldLogs\*.log > C:\OldLogs\merged.log
  • The resulting file will have all the comment lines removed, including the one specifying the order of columns in the log. You'll need to insert it at the top of the created file yourself or AWStats will fail to parse it. You can copy it from one of the original log files which you have just merged. It should be near the top of the file and starts with #Fields:.
  • Now you can process the generated log file with AWStats by overriding the log file path from its settings. Change your command prompt current dir to wwwroot\cgi-bin subfolder and type: perl awstats.pl -config=damirscorner -LogFile=C:\OldLogs\merged.log. Replace damirscorner with the site name which you have used when naming your *.conf file.

The statistics are now generated. You only need to configure a new web site or web application in IIS which will serve the newly generated data. Just point it to the wwwroot subfolder of your AWStats installation. Because IIS doesn't know anything about Perl, you'll need to open the Handler Mappings and Add Script Map... as shown in the following screenshot (make sure the path to PerlEx30.dll is correct):

Add Script Map...

You might also want to add a index.html file inside the wwwroot folder which will redirect you to the correct URL when you navigate to the web application root from your browser:

Again, replace damirscorner in all 3 occurrences with your own site name.

<!DOCTYPE HTML>
<html lang="en-US">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="refresh" content="1;url=cgi-bin/awstats.pl?config=damirscorner">
        <script type="text/javascript">
            window.location.href = "cgi-bin/awstats.pl?config=damirscorner"
        </script>
        <title>Page Redirection</title>
    </head>
    <body>
        If you are not redirected automatically, follow 
        <a href='cgi-bin/awstats.pl?config=damirscorner'>this link</a>.
    </body>
</html>

You still need to setup a schedule for updating the statistics with new data. AWStats can only parse each log file once, so you'll need to match the schedule with your IIS settings. As you can see from the first screenshot, I have configured my Log File Rollover to happen Daily, therefore I'll need to process the log files daily as well, once they won't change any more. I used Windows Task Scheduler to create a job which runs at 3 in the morning every day and runs Perl (C:\Perl\bin\perl.exe, to be exact) with the following arguments: C:\WWW\awstats-7.3\wwwroot\cgi-bin\awstats.pl -config=damirscorner -update.

That's it. AWStats has been working flawlessly since I've set it up and I can now check fresh statistics for my blog every morning.

Monday, January 5, 2015 6:44:28 AM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Personal | Website | Software | IIS
My Book

NuGet 2 Essentials

About Me
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

All Content © 2015, Damir Arh, M. Sc. Send mail to the author(s) - Privacy Policy - Sign In
Based on DasBlog theme 'Business' created by Christoph De Baene (delarou)
Social Network Icon Pack by Komodo Media, Rogie King is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.