Friday, 12 August 2016

Problems installing Microsoft .Net Core 1.0.0 VS 2015 Tooling Preview 2

Problem

I had a funky installation of Visual Studio. Everything seemed to be working but when I came to install the Microsoft .Net Core 1.0.0 VS 2015 Tooling it refused to install:

core-001

Repeated attempts to repair or reinstall Visual Studio 2015 Enterprise just wasn’t getting anywhere and I wasn’t in a position to flatten the machine and start again. What was I to do?

Solution

I managed to run the installer and force it not to check Visual Studio using a command line switch:

ukafr02@UKSTOL0079 C:\Users\ukafr02\Downloads
$ DotNetCore.1.0.0-VS2015Tools.Preview2.exe SKIP_VSU_CHECK=1

core-002

core-003

core-004

Happy days!

Friday, 3 June 2016

Enter RSA passphrase once when using Git bash

When using Git bash it can become annoying if you have to enter your RSA passphrase every time you perform a remote operation. You can easily prevent this by using ssh-agent and running it when Git bash first runs.

Open a text editor and create a new text file. Paste the following bash script into the file:

#! /bin/bash 
eval `ssh-agent -s` 
ssh-add ~/.ssh/*_rsa

Note that my RSA key file is called id_rsa and is stored in the .ssh folder in my user’s home directory.

Save the file created above as .bashrc in your user’s home directory. Now, when you start a Git bash session you should be prompted for your passphrase. This will remain active for the duration of the session and you won’t have to enter it again.

conemu

See Saving an SSH key when using Git for info on generating the RSA key file.

Thursday, 2 June 2016

Git recipies

This post is a quick aide-mémoire for basic command-line Git operations. Well worth reading is the Git Getting Started documentation.

Clone a remote repository for the first time

To get started crack open Git bash and go to your source folder. You can then clone a remote repository into a new folder simply by running the following command:

someuser@mymachine MINGW64 ~
$ cd c:

someuser@mymachine MINGW64 /c
$ cd Source/

someuser@mymachine MINGW64 /c/Source
$ git clone git@some:repo/Some.Project.git
Cloning into 'Some.Project'...
Enter passphrase for key '/c/Users/someuser/.ssh/id_rsa':
remote: Counting objects: 1402, done.
remote: Compressing objects: 100% (1311/1311), done.
emote: Total 1402 (delta 1018), reused 87 (delta 59)Receiving objects:  87% (1220/1402), 580.00 KiB | 1.08 MiB/s

Receiving objects: 100% (1402/1402), 1.15 MiB | 1.08 MiB/s, done.
Resolving deltas: 100% (1018/1018), done.
Checking connectivity... done.

someuser@mymachine MINGW64 /c/Source
$                                                            

See the Git - git-clone Documentation.

List branches

The following command lists all local and remote branches:

someuser@mymachine MINGW64 /c/Source/Some.Project (master)
$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/develop
  remotes/origin/feature/IntialLoggingIntegration
  remotes/origin/master

See Git – git-branch Documentation.

To see remote branches only use the –r switch. For local only use the –l branch.

someuser@mymachine MINGW64 /c/Source/Some.Project (master)
$ git branch -r
  origin/HEAD -> origin/master
  origin/develop
  origin/feature/IntialLoggingIntegration
  origin/master

someuser@mymachine MINGW64 /c/Source/Some.Project (master)
$ git branch -l
* master                                                           

Getting more information about the remote repository

someuser@mymachine MINGW64 /c/Source/Some.Project (master)
$ git remote -v
origin  git@some:repo/Some.Project.git (fetch)
origin  git@some:repo/Some.Project.git (push)

someuser@mymachine MINGW64 /c/Source/Some.Project (master)
$ git remote show
origin

someuser@mymachine MINGW64 /c/Source/Some.Project (master)
$ git remote show origin
Enter passphrase for key '/c/Users/someuser/.ssh/id_rsa':
* remote origin
  Fetch URL: git@some:repo/Some.Project.git
  Push  URL: git@some:repo/Some.Project.git
  HEAD branch: master
  Remote branches:
    develop                          tracked
    feature/IntialLoggingIntegration tracked
    master                           tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':
    master pushes to master (up to date)

Checkout a remote branch

To switch to a new remote branch and check its status:

someuser@mymachine MINGW64 /c/Source/Some.Project (master)
$ git checkout develop
Branch develop set up to track remote branch develop from origin.
Switched to a new branch 'develop'

someuser@mymachine MINGW64 /c/Source/Some.Project (develop)
$ git status
On branch develop
Your branch is up-to-date with 'origin/develop'.
nothing to commit, working directory clean

Create a new branch

This example shows how to create a feature branch off develop:

someuser@mymachine MINGW64 /c/Source/Some.Project (develop)
$ git checkout -b feature/test develop
Switched to a new branch 'feature/test'

See the Git - git-checkout Documentation. Also see the Git Branching - Basic Branching and Merging.

Delete a branch

The following example shows how to delete a branch. Note you can’t be on the branch you’re deleting.

someuser@mymachine MINGW64 /c/Source/Some.Project (develop)
$ git branch -D feature/test
Deleted branch feature/test (was 2647fba).

See the Git - git-branch Documentation. Also see the Git Branching - Basic Branching and Merging.

Revert changes to a file

You can see which files have been modified locally using the “git status” command and then undo the changes with “git checkout”:

someuser@mymachine MINGW64 /c/Source/Some.Project (develop)
$ git status
On branch develop
Your branch is up-to-date with 'origin/develop'.
Changes not staged for commit:
  (use "git add ..." to update what will be committed)
  (use "git checkout -- ..." to discard changes in working directory)

        modified:   src/Some.Project/App.config
        modified:   src/Some.Other.Project/config/App.config

no changes added to commit (use "git add" and/or "git commit -a")

someuser@mymachine MINGW64 /c/Source/Some.Project (develop)
$ git checkout -- src/Some.Project/App.config

Merge the develop branch into a feature branch

If you are using Git Flow and you are working on a feature branch you might want to merge develop into your feature branch from time to time to minimise conficts once your feature is complete. The basic commands to use would be:

someuser@mymachine MINGW64 /c/Source/Some.Project (develop)
$ git checkout feature/test
Switched to branch 'feature/test'
Your branch is up-to-date with 'origin/feature/test'.

someuser@mymachine MINGW64 /c/Source/Some.Project (feature/test)
$ git merge develop

See the Git – git-merge Documentation.

Checking to see what might be committed (dry-run)

An easy one - how can you see what will be committed without actually doing so? Like this:

someuser@mymachine MINGW64 /c/Source/Some.Project (develop)
$ git commit --dry-run

See the Git – git-commit Documentation.

Thursday, 19 May 2016

Diagnosing log4Net issues in an ASP.Net web application

The Problem

I was trying to get a legacy web application up-and-running on a development workstation but log4Net was not generating any log files. The application was being run from a local instance of IIS 7.5 and built using Visual Studio 2013.

Stepping through the code did not reveal anything relevant and the code to initialise log4Net was being called. So, the problem was how to see what log4Net was doing internally to identify any errors during initialisation.

The Solution

The solution was to enable log4Net’s internal debugging. To do so I modified the web.config file to include a couple of new entries. Firstly, a new appSettings entry:

<appsettings>
    <!-- other settings omitted -->
    <add value="true" key="log4net.Internal.Debug" />
</appsettings>

Then add a new trace listener to system.diagnostics:

<system.diagnostics>
    <trace autoflush="true">
      <listeners>
        <add
            name="textWriterTraceListener"
            type="System.Diagnostics.TextWriterTraceListener"
            initializeData="C:\log4net.txt" />
      </listeners>
    </trace>
  </system.diagnostics>

Starting the application now created a log4net.txt file in the root of my C-drive. A quick scan of that log file revealed the issue:

log4net:ERROR [RollingFileAppender] ErrorCode: GenericFailure. Unable to acquire lock on file D:\applog\_root_20160518.0.log. The device is not ready.

As it happens there's no D-drive on my machine! Further investigation revealed that the machine image used to build my workstation included a machine-level web.config file that contained the offending log file location (yes, horrible I know). I changing the entry, restarted the web application and log4Net started working.

References

Monday, 16 May 2016

Creating a SQL Server alias

The Problem

I have a laptop with a SQL Server Express 2012 installed and configured as a named instance (localhost\SQLEXPRESS2012). I’ve cloned a code repository and want to be able to run the applications it contains but they are all configured with connection strings that look for a different instance name (localhost\dev_2012).

I could start modifying connection strings but there are multiple applications and therefore connection strings to modify. I’d prefer to be able to create an alias to the database that matches the one in the configuration files so I don’t need to modify them at all.

The Solution

The solution is to create an alias to the named instance using the SQL Server Configuration Manager.

Open the SQL Server Configuration Manager (Start Menu > All Programs > Microsoft SQL Sever 2012 > Configuration Tools).

Check that TCP/IP is enabled for the instance you are creating an alias for. Enable it if it is not.

sql-alias-001

Once TCP/IP is enabled we can create an alias to the instance for the SQL Native Client. In my case this was for the 32-bit version. Expand the SQL Native Client 11.0 Configuration element and right-click on Aliases. Select New Alias… from the context menu.

Use the new instance name as the Alias Name and set the Server value to the original named instance.

2016-05-16 11_03_01-localhost_dev_2012 Properties

Note the Port No field. By default SQL Server uses 1433 but you can check your setup using the SQL Server Configuration Manager. Open the SQL Server Network Configuration element again and select the protocols for the named instance. Right-click on TCP/IP and view the Properties.

2016-05-16 11_13_10-TCP_IP Properties

If Listen All is enabled on the Protocol tab move to the IP Addresses tab and scroll down to the IPAll section. If Listen All is not enabled you will need to look for the appropriate IP section.

If SQL Server is configured to use a static IP address it will appear in the TCP Port value. If is is configured to use a dynamic port the port in use will appear as the TCP Dynamic Port value. In either case this is the port number to use when creating the alias.

2016-05-16 11_15_22-TCP_IP Properties

Click OK to close any open dialog. Restart SQL Server.

The new instance name will now get routed to the actual instance (calls to localhost\dev_2012 will get routed to localhost\SQLEXPRESS2012 in this case).

You can check everything works by connecting the SQL Server Management Studio to the new instance name.

Tuesday, 12 April 2016

UKMail customer service – FAIL!

We are living the dream. As a family we take full advantage of online retailing but there’s one aspect of the process that seems to be in need of improvement: delivery. 

A company that I’ve had a few unsatisfactory dealings with recently is UKMail. I’ve had disappearing deliveries where either they didn’t try to deliver or – more likely – they did but the driver decided not to leave a card.

Phone system – FAIL

On one such occasion I tried calling by phone and got bounced through the usual impenetrable audio menus until I encountered an option to arrange for a re-delivery. I dutifully pressed 1 as instructed only to be told “Thank you for calling UKMail. Goodbye.” after which I was immediately cut off.

via GIPHY

Happy? No. Really, no.

Contact Us – FAIL

Having tried and failed to use their phone system I decided to raise a complaint using the online Contact Us form. It seems UKMail were ahead of me there and seem to have created a form that you can’t actually submit.

image

Try as I might I couldn’t identify what the erroneous character was. I suspect there’s a proud customer services manager gleefully including in his weekly report the fact that no one is complaining via the website. Now we know why.

I pointed this out on Twitter but I think they missed the point. The following Tweet did result in contact from customer services but only to try and rearrange delivery of the parcel, which I’d already managed to do.

SNAGHTML2f1e3d49

Delivery notification – FAIL

So today, I get home to find yet another UKMail card lying on the door mat but this time annotated by a clearly irritated UKMail delivery man.

image

Loving the “Again”. It didn’t irritate the hell out of me at all.

It might be stating the obvious but if you keep trying to deliver at the same times and there’s never anyone in then you might be trying at the wrong times.

But let’s look a bit closer. This card suggests we’ve been notified in advance in order to give us the change to choose “option 1”. So I checked my email and this is what I found.

SNAGHTML2f266627

This email arrived at 09:42hrs on the day of delivery, only 2 hours ahead of the earliest delivery time given.

What do UKMail expect here? Do they expect us all to be monitoring personal email while at work and filling in online forms to arrange delivery at another time? I’m pretty sure my boss wouldn’t be too happy about that.

UKMail, if you insist on sending these emails at least give us a chance to answer them. Two hours isn’t enough notice. And perhaps point this out to your delivery men so they don’t get snippy on your cards.

Sorry we missed you email – FAIL

This one speaks for itself.

SNAGHTML2f2ef570

Option 1 – FAIL

OK, so the card says quite clearly to visit www.ukmail.com and to select ‘Manage My Delivery’. I did just that, entered the card number and postcode as directed and ended up here.

SNAGHTML2f488989

Can’t see an option 1, 2, 3 or 4 there… Definitely can’t see a “Leave in a safe place option”… Not sure what to do now.

I give up. I think I’ll be looking out for UKMail as a delivery option when making online purchases and selecting something else!

Collect from depot – FAIL

OK, let’s try the Collect from depot option.

SNAGHTML2f667cd5 

Right. No idea what times I can collect then. Not even a default “between 9am and 5pm”. Remember I’m working so what are the chances of them being open after I finish work (i.e. after 5pm)? Nil, I suspect. Do I risk it..?

Well I do as it happens and I end up with this:

SNAGHTML2f6a785d

They don’t like times at UKMail do they - unless it’s giving you 2 hours notice of a delivery.

Conclusion

As a consumer I very often don’t even know which delivery company will deliver any given online purchase. Even if I do, it’s usually the case that I don’t get the chance to specify delivery options such as ‘leave in a safe place’. That seems like a failing to me.

If you leave instructions on a card make sure those instructions can actually be completed by the customer.

Notifications of impending deliveries 2 hours beforehand is a waste of time where people can be expected to be at work.

And why try to deliver during the day at all? Surely most people are out at that time, at least as far as domestic customers are concerned. Wouldn’t evening deliveries by less wasteful in time and resources, not to mention creating better customer relationships?

Online forms that are difficult to submit will aggravate end users, especially when they are already aggravated. Emails that refer to buttons that aren’t there are plain sloppy.

Any individual item given above wouldn’t mean much but when combined result in reduced customer satisfaction and loss of confidence in the service.

Now, let’s try and rearrange delivery of that parcel…

Update – 13/04/2015

After contacting UKMail via Twitter I received the following message:

SNAGHTML16bbb3

So even though I’ve said it’s OK to leave the parcel in a safe place they won’t do it. This illustrates the problem with deliveries and online purchasing. If I as the consumer am not able to specify delivery options like this at the point of sale and if delivery companies won’t allow deliveries outside normal working hours it makes life difficult for all concerned.

It also occurred to me that I hadn’t shown what happens if you try to get your parcel redelivered.

SNAGHTML1cb732

You can’t specify a time of delivery, not even morning or afternoon let alone after 5pm. What are the options here? Only one: take the day off and sit around all day waiting for a delivery. For large or expensive deliveries that might be a viable option but for most of what I do it’s not.

Update – 14/04/2016

As you can see from the screenshots in the Collect from depot – FAIL section above I used the online system to arrange collection from the depot. Imagine my surprise to be sent the following email:

ukmail

As usual the email arrived just 2 hours before the scheduled delivery time (at 10:03hrs actually). So, UKMail have ignored my instruction that I’d be picking the parcel up from the depot and I can expect another crappy card with some suitably irksome message from an irritated delivery driver waiting for me at home.

Just pathetic.

And will the parcel be waiting for me at the depot? Should I waste my time trying to pick it up as I’d arranged?

Update - 15/04/2016

I don’t know why I bothered but I tried collecting the parcel as previously arranged. No surprises here – the result was a big fat “Sorry mate. Bad news I’m afraid…” from the UKMail man in reception. It seems the parcel was still on the van and wouldn’t be back at the depot until 7pm.

So I had to make another journey to collect the parcel after 7pm taking an hour out of my evening. I have the parcel now but that’s it for me. If an online vendor owns up to using UKMail I’m shopping elsewhere.

Saturday, 2 April 2016

Google shows us what user experience shouldn’t look like

I received an email from Google saying that my credit card was expired and asking me add a new one. What ensued was an example of really bad user experience.

Here’s the original email:

SNAGHTML7b873a

There are a few links in the email. Let’s try following the Sign in link. You end up at a web page that looks like this:

image

Now, I don’t think I’ve got a Google for Work account so let’s click the Add account button. I’m asked for sign-in details so I add my usual Google account details and click through.

SNAGHTML6debf4  SNAGHTML6e3fd0 

I click the final Sign in button and end up here:

image

Hang on. That looks familiar. No matter how many times I tried, it was always the same. I went round in a circle and ended up in the same place without an account having been ‘added’.

Back to the email. What happens if I click the Add payment methods link? This does, every time:

image

Wow.

OK, back to first principles. I Google “google for work” and find the http://apps.google.com site. I click Sign in and use the domain I’m administering (this blog) and my usual account details again.

SNAGHTML76c9e9

I click Go and end up here:

image

Hmmm… Looks familiar again but at least we’ve now got a domain mentioned. Can you guess what trying to add an account does? Yes, it does nothing and goes in a circle again.

So, what was the real problem? It seems that because the ‘organisation’ is andyfrench.info I had a separate account in that domain that I had setup to manage the site. I ended up logging in with that account – resetting the password on the way – to get in to the Google at Work admin site. One in it still took me a while to navigate my way to change the credit card details. Whew.

Anyway, it may be secure to not leak any information at all about failed login attempts but really? Is this right?