Wednesday, July 25, 2018

How to close a RDP session but leave original user logged on

It's annoying when you make a Remote Desktop Connection (RDP) to a PC that it does not automatically reconnect the original user once your remote session has finished. I often need to do this to remotely control a Windows based bit of test equipment. I developed this script to place a button on the Taskbar of the controlled machine to close the RDP session. Provided you use this button the desktop is returned to the original user as the remote session terminates. However, if you simply close the session (as you do normally by closing the RDC window) this code does not help and the machine will, as normal,  prompt for a password before returning to the desktop.

Firstly you need to create this .bat file. I've Created mine in a folder called C:\Temp\Shutdown RDP and named my .bat file "CloseRDP.bat".

set MY_SESSION_ID=unknown
for /f "tokens=3-4" %%a in ('query session') do @if "%%b"=="Active" set MY_SESSION_ID=%%a
tscon %MY_SESSION_ID% /DEST:console /Password:YourTopSecretPassword

Firstly let me explain what this does. The second line runs the command 'query session' and extracts the session ID that is active. It puts the session ID into an environment variable called MY_SESSION_ID. The third line closes the active session (based on it's session ID number from line 2) and redirects to the console. You will have to replace YourTopSecretPassword with the password for the desktop user. Now, this is a bit of a security risk as the password is in plain text inside the .bat file but I'm afraid it does not work if you leave it out.

However there is a problem with this .bat file...it must be run with Administrator privileges otherwise it does not work. So from File Explorer right click on CloseRDP.bat and select "Copy". Then right click in some empty space in the same folder and select "Paste Shortcut". My shortcut is now called "CloseRDP.bat - Shortcut". Right click on this and select "Properties", click on the "Advanced" button and tick "Run as administrator" and click OK twice to return to File Explorer. You have now created a shortcut that runs as Administrator. You can click on this to close the RDC session and return to the desktop. Because it runs as an Administrator you will be prompted to enter the Administrator password.

In an ideal world you would be able to drag this shortcut directly to the Taskbar for it to appear as a clickable program. However for some weird reason this does not work.

To fix this a second shortcut is required! Don't ask me why just do it! In File Explorer right click on "CloseRDP.bat - Shortcut" and select "Copy". Now right click in some empty space again and select "New > Shortcut". In the "Type the location of the item box" manually type "explorer " and then press Ctrl+V to paste the name copied earlier. It should look like this:
Click "Next" and give the shortcut a name. I've called mine "Pinable CloseRDP". There are now three files in the folder that should look like this

Now the icon for "Pinable CloseRDP" has the normal boring File Explorer icon. I like to change this to something that stands out better so right click on "Pinable CloseRDP" and select "Properties". Click on the "Change Icon..." button and select one of the default icons. I normally go with the red cross. Click OK twice to return to File Explorer. File Explorer should now have three files that look like this:

Now, after all these steps, you can finally drag the "Pinable CloseRDP" and drop it onto the Taskbar. You should now have a nice clear button that you can click to close the remote session and return the desktop to the original user.

If you are really keen you could design a custom icon to make it even clearer. When you click on you new icon you will be prompted for the Administrator password, the remote session will close and the desktop will return to the local user session without any password prompt.

Good luck, there are quite a few steps but it does work well if you follow them carefully.


Friday, March 02, 2018

WPF Blurry Pixels

Today I needed to create a small control for the status bar of my app. It needs to be small to show the pass/fail status of 96 items.

I had an ItemControl displaying the 96 items as 4 rows of 24. I started with this code but it was horribly blurry and irregularly spaced.

<Rectangle Width="4" Height="4" Margin="1,1,0,0" Fill="Green" />





 
To get it to display nicely with no blurry edges I changed the code to this...
<Rectangle Width="3.84" Height="3.84" Margin="0.96,0.96,0,0" Fill="Green" />
 
 
 
 
 
It's because WPF assumes 96 pixels per inch. By changing the size to be multiple of 0.96 you can trick WPF into drawing complete pixels.








 

Saturday, February 24, 2018

UK Government Gateway 2FA/2SV

The UK Government Gateway now requires two factor authentication, which they call two step verification (2SV), when you login. This is a very good thing. You can download the HMRC app, receive SMS text messages (very insecure) or receive an automated phone call (quite insecure). They push you to download the HMRC app for your phone. However, I've discovered they are using industry standard Time-Based One-Time Password (TOTP) passwords (another very good thing). As a result you can use the standard Google Authenticator or Microsoft Authenticator on your iPhone instead of the HMRC app.
Simply select "Mobile App" as your authentication method in the HMRC web site to display a QR code. Scan the QR code from your mobile authenticator app and you will be up and running in seconds. No need to download the HMRC app. Generally TOTP mobile phone authentication is much more secure than text messages or phone calls. Two factor authentication by SMS text message, used by many banks, should be banned as it's highly insecure due to serious vulnerabilities with the SS7 protocol used between mobile networks. It's so insecure that NIST (US Standards body) are no longer recommending SMS text messages a part of a two factor authentication scheme. For more details see https://www.schneier.com/blog/archives/2016/08/nist_is_no_long.html. It's a shame the UK Government even offer SMS based authentication as it lends credibility to an insecure authentication method.

Monday, November 27, 2017

HP Officejet Pro 8600 Plus prints web pages very small from IOS 11

We have an HP Officejet Pro 8600 Plus which has been printing from our IOS devices perfectly well for many years. However, since upgrading to IOS 11 web pages print as a tiny image (3x5") at the top left on the page (although I suppose it does save loads of ink!). Interestingly PDF's print without any problem, the problem seems to be limited to printing from web pages. Any of the older iPhones or iPads, which cannot be upgraded to IOS 11, continue to print without any problems. Here is an example showing the IOS 11 printing on the left and IOS10 printing on the right.



 
I'm pleased to report that I've found a solution. Find the IP address of your printer (by pressing the network icon on the touch screen on the printer) and use a web browser to connect to the IP address shown.

Switch to the Network tab and select "Network Protocol" on the left hand side under General. Change the setting to "Enable IPV4 only", click the "Apply" button.


Now, restart the printer (I unplugged mine) and restart your IOS devices. Once you have done this you should find that you can once again print web pages at full size!

It's clearly a bug in IOS 11 with IPV6 (as IOS 10 works just fine). Come on Apple get it sorted! It's been months now and there are thousands of people reporting the same problem on the Apple and HP forums. As normal both companies are blaming each other and sending people off to perform a load of useless tests rather than admitting to there being a problem in IOS 11.

Let me know if this fixes it for you too.

Wednesday, November 08, 2017

Vodafone Sure Signal - No smoking please!

I've just had my Vodafone Sure Signal V3 blow up with a little puff of smoke. Fortunately I was sitting right next to the thing when it popped and I was able to unplug it pretty quickly! It rattled once unplugged! I opened it up and found a capacitor that had blown itself off the board. The interior was filled with smoke, see burn marks in the photos below.

I've contacted Vodafone via Twitter. Let's see what they do about it. Hopefully it's not a fire risk for others!

The label says it's an Alcatel-Lucent Model Number : 9361 Home Cell p3.0, Part Number : 3JR09113ABBA

I notice there is a big thread on the Vodafone UK Sure Signal forums with loads of people who have had exactly the same problem.




10 Nov Update
I am pleased to report that Vodafone have agreed to send a replacement SureSignal free of charge (regardless of the warranty status). It'll apparently be delivered within 3 days. Given the unit does not have a replaceable fuse I'll be plugging it into an extension block with a very small fuse fitted to the plug. In my case the old unit tripped the downstairs circuit breaker (which also has the fridge and freezer attached). Had it blown when I was not at home it could have had far greater and more costly consequences (not to mention the potential fire risk). I'm not totally comfortable with the design of the SS3 as it runs very hot, this will always shorten the life of any electronic components. However, I have no Vodafone mobile phone signal where I live (high tech Cambridgeshire) and need to use the phone for work so I have little choice but to use one. I think powering it from a power strip with a very low current quick blow fuse will be the best way to reduce the risk associated with using this product.

13 Nov Update
A free of charge replacement unit was delivered today. I've reported the fault to Trading Standards and they are contacting Vodafone to report another failed unit.

16 Nov Update
I've made a short extension lead and fitted a small 1A fuse to the plug. Hopefully this will stop the whole power circuit tripping out if (when) this new SureSignal fails.


Monday, July 03, 2017

Dell XPS 15 (9550) swollen battery

I have had a problem with a swollen battery on my Dell XPS 15 (9550). The battery swells as it fills with gas. This swollen battery pushes the trackpad up 3 or 4 mm beyond the case (see photo). The trackpad then stops working. Dell advised me to stop using the laptop and remove power from it. For safety I have removed the battery until a replacement is received. See video below









Sunday, June 05, 2016

Simple WPF app using Task and Await with .NET 4.5

Here is a simple example showing how to create background tasks in a WPF app with .NET 4.5 and above. This is so much easier than the old BackgroundWorker approach.

<Window x:Class="TestAsyncTasks.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TestAsyncTasks"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
 <Grid Margin="4">
  <Grid.RowDefinitions>
   <RowDefinition Height="Auto"></RowDefinition>
   <RowDefinition Height="*"></RowDefinition>
  </Grid.RowDefinitions>
  <StackPanel Grid.Row="0" Orientation="Horizontal">
   <Button x:Name="ButtonStart" Content="Start" Click="Start_Click" Padding="4"/>
   <Button x:Name="ButtonCancel" Content="Cancel" Click="Cancel_Click" Padding="4"/>
  </StackPanel>
  <TextBox Grid.Row="1" x:Name="Label1"></TextBox>
 </Grid>
</Window>
 
 
 
 
 
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
 
namespace TestAsyncTasks
 {
 /// <summary>
 /// Interaction logic for MainWindow.xaml
 /// </summary>
 public partial class MainWindow : Window
  {
  public MainWindow()
   {
   InitializeComponent();
   }
 
 
  // To allow background task to be cancelled with cts.Cancel()   
  CancellationTokenSource cts;
 
 
  private async void Start_Click(object sender, RoutedEventArgs e)
   {
   // Disable button so it can't be clicked again until finished  
   ButtonStart.IsEnabled = false;
   Label1.Text = "Start\r\n";
 
   // Setup the function to be called with updates     
   var progressUpdate = new Progress<int>(ReportProgressOnUIThread);
 
   // Create a new CancellationTokenSource and optionally set a time 
   // when the task will automatically cancel if it has not already 
   // finished.              
   int AutoCancelAfterMS = 50000;
   cts = new CancellationTokenSource(AutoCancelAfterMS);
 
   // Must be in Try/Catch to trap the OperationCanceledException  
   try
    {
    int loopTo = 10;
    int result = await MyBackgroundTaskAsync(loopTo, progressUpdate, cts.Token);
 
    // This code does not run until MyBackgroundTaskAsync finishes 
    Label1.Text += $"Final result : {result}\r\n";
    }
   catch (OperationCanceledException ex)
    {
    // Do stuff to handle the cancellation exception    
    Label1.Text +=  "CANCELLED\r\n";
    }
   catch (Exception ex)
    {
    //Do stuff to handle other exceptions       
    Label1.Text += $"Exception : {ex.Message}\r\n";
    }
 
   // Reenable Start button           
   ButtonStart.IsEnabled = true;
   Label1.Text += "Finished\r\n";
   }
 
 
  private void Cancel_Click(object sender, RoutedEventArgs e)
   {
   cts.Cancel();
   }
 
 
  async Task<int> MyBackgroundTaskAsync(int DataFromParent, IProgress<int> progress, CancellationToken ct)
   {
   int result = await Task.Run<int>(async () =>
    {
    for (int n=0; n< DataFromParent; n++)
     {
     //You cannot do this because it's running on a non UI thread
     // Label1.Text += $"{n} I don't work!\r\n";
 
     // Throw OperationCanceledException if cts.Cancel() called 
     ct.ThrowIfCancellationRequested();
 
     // Report progress back to UI thread      
     progress.Report(n);
 
     // Do the slow things in the background     
     await SlowStuff();
     }
 
    // result gets this value which is returned as final result 
    return 42;
    }, ct);
 
   return result;
   }
 
 
  async Task SlowStuff()
   {
   // Simulate some slow code. This runs on a background thread.  
   await Task.Delay(1000);
   }
 
 
  void ReportProgressOnUIThread (int value)
   {
   // This runs on the UI thread so it can update the WPF controls 
   Label1.Text += value.ToString() + "\r\n";
   }
  }
 }