Jun 21

Currently I am developing an application with C# which uses the Facebook API. I will keep posting about this but now I’d like to write about an error that I came across and post the solution.

If you are familiar with the Facebook API you know how it works. You can write an application which uses any features of the facebook API but when you are actually requesting data a built-in login window appears which asks for your login details to Facebook. If you provide the correct username and password the data you requested from your application is being displayed (or rather you can use the requested data as you wish).
It was between the login and the data display when my application gave me the error message “requested value ‘UnitedKingdom’ was not found” and it crashed. To resolve this error, this is what you should do:

Open the original Facebook API project (if you downloaded it from Microsoft’s website, the default installation directory is C:\Program Files\Coding4Fun\Facebook\Source). Look for the file “location.cs” which contains an enum list of all countries, states (US) and so on.

Facebook API - Location.cs

Simply open that file for editing and search for the enum called public enum Country. Add the value UnitedKingdom to this list, recompile the project and you are done. Don’t forget to add the newly created dlls as references to your project.

Dec 20

Before continue reading please note that this article doesn’t intend to call upon you to create nasty applications. If you use this code it should be for your own fun or for learning purposes.

After doing some research on disabling keys or key combinations I found out that there are several ways of achieving the before mentioned key combos. CTRL-ALT-DEL combo is part of the SAS (Secure Attention Sequence) thus the solution to disable this is to write your own gina.dll (Graphical Identification and Authentication).

Don’t worry, I’m not looking into that as for now, I’m going to show you the work around. We will use C#’s Registry editing possibilities to set/change the group policy for the CTRL-ALT-DEL key sequence. Let’s see what we are about to do without programming anything. Open Start Menu > Run and enter gpedig.msc. Navigate to: User Configuration > Administrative Templates > System > CTRL+ALT+DELETE Options.This is the place where you normally set the behaviour of the key combo. Select Remove Task Manager > Double-click the Remove Task Manager option.

If you change it’s value, the following registry entry gets created/modified: Software\Microsoft\Windows\CurrentVersion\Policies\System and the value of DisableTaskMgr gets set to 1.

Now, the task is set. Let’s get down to business and start coding:

Important thing, don’t miss out this line:

using Microsoft.Win32;

And now the method I have created looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public void KillCtrlAltDelete()
        {
            RegistryKey regkey;
            string keyValueInt = "1";
            string subKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
 
            try
            {
                regkey = Registry.CurrentUser.CreateSubKey(subKey);
                regkey.SetValue("DisableTaskMgr", keyValueInt);
                regkey.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

If you run the method and try to press CTRL-ALT-DEL the following screen should come up:

CTRL ALT DEL

So the CTRL-ALT-DEL combo has been taken care of, let’s see the rest. You might have found this a bit difficult, so here’s an easy one. How to disable ALT+F4. 5 lines of code alltogether:

1
2
3
4
5
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            base.OnClosing(e);
        }

Okay. As for the rest I was reading many many articles, and they gave a lot of help. I can’t name one, as I was looking into at least 15 which all held some useful peace of information. I will give you the the source of the method called hooks. The code snippet uses the LowLevelKeyboardProc which is:

The LowLevelKeyboardProc hook procedure is an application-defined or library-defined callback function used with the SetWindowsHookEx function. The system calls this function every time a new keyboard input event is about to be posted into a thread input queue. The keyboard input can come from the local keyboard driver or from calls to the keybd_event function. If the input comes from a call to keybd_event, the input was “injected”. However, the WH_KEYBOARD_LL hook is not injected into another process. Instead, the context switches back to the process that installed the hook and it is called in its original context. Then the context switches back to the application that generated the event.

Again, dont forget:

using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Diagnostics;

Here’s the rest what you need:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
[DllImport("user32", EntryPoint = "SetWindowsHookExA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
        public static extern int SetWindowsHookEx(int idHook, LowLevelKeyboardProcDelegate lpfn, int hMod, int dwThreadId);
        [DllImport("user32", EntryPoint = "UnhookWindowsHookEx", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
        public static extern int UnhookWindowsHookEx(int hHook);
        public delegate int LowLevelKeyboardProcDelegate(int nCode, int wParam, ref KBDLLHOOKSTRUCT lParam);
        [DllImport("user32", EntryPoint = "CallNextHookEx", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
        public static extern int CallNextHookEx(int hHook, int nCode, int wParam, ref KBDLLHOOKSTRUCT lParam);
        public const int WH_KEYBOARD_LL = 13;
 
        /*code needed to disable start menu*/
        [DllImport("user32.dll")]
        private static extern int FindWindow(string className, string windowText);
        [DllImport("user32.dll")]
        private static extern int ShowWindow(int hwnd, int command);
 
        private const int SW_HIDE = 0;
        private const int SW_SHOW = 1;
public struct KBDLLHOOKSTRUCT
        {
            public int vkCode;
            public int scanCode;
            public int flags;
            public int time;
            public int dwExtraInfo;
        }
        public static int intLLKey;
 
        public int LowLevelKeyboardProc(int nCode, int wParam, ref KBDLLHOOKSTRUCT lParam)
        {
            bool blnEat = false;
 
            switch (wParam)
            {
                case 256:
                case 257:
                case 260:
                case 261:
                    //Alt+Tab, Alt+Esc, Ctrl+Esc, Windows Key,
                    blnEat = ((lParam.vkCode == 9) && (lParam.flags == 32)) | ((lParam.vkCode == 27) && (lParam.flags == 32)) | ((lParam.vkCode == 27) && (lParam.flags == 0)) | ((lParam.vkCode == 91) && (lParam.flags == 1)) | ((lParam.vkCode == 92) && (lParam.flags == 1)) | ((lParam.vkCode == 73) && (lParam.flags == 0));
                    break;
            }
 
            if (blnEat == true)
            {
                return 1;
            }
            else
            {
                return CallNextHookEx(0, nCode, wParam, ref lParam);
            }
        }
public void KillStartMenu()
        {
            int hwnd = FindWindow("Shell_TrayWnd", "");
            ShowWindow(hwnd, SW_HIDE);
        }
private void Form1_Load(object sender, EventArgs e)
        {
            intLLKey = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, System.Runtime.InteropServices.Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]).ToInt32(), 0);
        }

Quite obviously you can programmatically reset these values. Here’s the code to re-enable everything:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static void ShowStartMenu()
        {
            int hwnd = FindWindow("Shell_TrayWnd", "");
            ShowWindow(hwnd, SW_SHOW);
        }
public static void EnableCTRLALTDEL()
        {
            try
            {
                string subKey = "Software\Microsoft\Windows\CurrentVersion\Policies\System";
                RegistryKey rk = Registry.CurrentUser;
                RegistryKey sk1 = rk.OpenSubKey(subKey);
                if (sk1 != null)
                    rk.DeleteSubKeyTree(subKey);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            UnhookWindowsHookEx(intLLKey);
        }

I hope you enjoyed my article and that you found some useful bits. I tried to collect all the information I managed to find during my research on this topic.

Oct 17

Today we received a task –create a TreeView Control in C# and list all files and directories within. Fair enough. You start off with grabbing the TreeView control onto your form, then you start writing your code, recursive directory calls…etc. You put it together. You start it off and the first thing that hits you in the face is the amount of time that you have to wait for your application to populate the TreeView.

My first thing was to modify the exercise; I added a ComboBox Control, populated it with the available drives and then created the SelectedIndexChanged() event which launched the population of the TreeView.

Life is easy, this exercise is easy - one might say. If you run this program on your local machine (or even better, on a laptop) you have no problem at all.

The first problem you might come across is the fact that older machines still have the precious “A:\” drive. Why is that a problem? When you populate your ComboBox it will check whether the drive is available. “A:\” drive is active and available, therefore it wants to go deeper into it and well, the drive is empty. Two possibilities exist to eliminate this error.

1. Try-catch :) But we definetly don’t want to go for the usual solution.

2. Instead of creating a string array to display the drives:

string[] drives = Environment.GetLogicalDrives();

you could create a DriveInfo array as shown below:

DriveInfo[] drives = DriveInfo.GetDrives();

(note that if you don’t use the System.IO namespace you need to write System.IO.DriveInfo.GetDrives();).

You then use a foreach loop to populate your ComboBox and you use the .IsReady() method to determine whether a drive is ready.

foreach (DriveInfo aDrive in drives)
{
 if (aDrive.IsReady == true)
 {
  comboBox1.Items.Add(aDrive);
 }
}

Okay, now you got rid of the problem, your code runs smoothly. Again, life is not that easy :)

When I tried to run my code at the uni, it keept throwing me a SecuritException. As you can imagine there are various policies used on the machines back there, with different permissions, etc. After doing some research I managed to find a great article on how to avoid this error message.

Let me introduce the procedure in brief. What you have to do first, is to create a Strong Name Key Pair. You can achieve this by running Visual Studio 2005 Command Prompt. There simply enter sn -k mykey.snk“. This will create the appropriate file (mykey.snk) for you. Don’t forget to copy this to your actual project folder!!! If the file is at the correct location open the AssemblyInfo.cs file within Visual Studio. (This file can be found in the Solution Explorer, under the “Properties”). Add the following line to your code:

[assembly: AssemblyKeyFile("mykey.snk")]

(note, you don’t put a semicolon after this line!)

Now you need to modify your security policy with the Microsoft .NET Framework Configuration utility. To start this up, enter “mscorcfg.msc” to your Visual Studio 2005 Command Prompt. Navigate to the following: .NET Framework X(version) Configuration > Runtime Security Policy > Machine > Code Groups > All_Code. (as shown on picture)
.NET Framework 2.0 Configuration
Here do the following:

  1. Right click on All_Code, and select New
  2. Create a new code group for your strong name, and hit next
  3. Select a strong name membership condition from the drop down box
  4. Hit the import button, and select your assembly. The configuration tool will import your public key. If you want to trust everything you sign with this key, leave the name and version boxes unchecked
  5. Select the FullTrust permission set

(at step 4 please note that an assembly is a .dll or a .exe file).

After you are done with the previous steps continue with these:

  1. Expand the All_Code code group
  2. Right click the LocalIntranet_Zone code group, and select properties
  3. Switch to the Permission Set tab, and select FullTrust

If you now compile and run your program, the SecurityException won’t appear! For further information and detailed explanation I recommend that you read the article previously mentioned.