Thứ Ba, 11 tháng 5, 2010

Block phím start của win

Add a new class to your project and paste this code:

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;

public class KeyboardFilter {
  private Keys[] mFilter;
  private IntPtr mHook;
  private LowLevelKeyboardProc mProc;

  public KeyboardFilter(Keys[] keysToFilter) {
    // Install hook
    mFilter = keysToFilter;
    ProcessModule mod = Process.GetCurrentProcess().MainModule;
    mProc = new LowLevelKeyboardProc(KeyboardProc);   // Avoid garbage collector problems
    mHook = SetWindowsHookEx(13, mProc, GetModuleHandle(mod.ModuleName), 0);
    if (mHook == IntPtr.Zero) throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to set hook");
  }
  public void Dispose() {
    // Release hook
    if (mHook != IntPtr.Zero) {
      UnhookWindowsHookEx(mHook);
      mHook = IntPtr.Zero;
    }
  }
  private IntPtr KeyboardProc(int nCode, IntPtr wp, IntPtr lp) {
    // Callback, filter key
    if (nCode >= 0) {
      KBDLLHOOKSTRUCT info = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lp, typeof(KBDLLHOOKSTRUCT));
      foreach (Keys key in mFilter)
        if ((key & Keys.KeyCode) == info.key && CheckModifier(key)) return (IntPtr)1;
    }
    return CallNextHookEx(mHook, nCode, wp, lp);
  }
  private bool CheckModifier(Keys key) {
    // Check if modifier key in required state
    if ((key & Keys.Control) == Keys.Control &&
      GetAsyncKeyState(Keys.LControlKey) == 0 && GetAsyncKeyState(Keys.RControlKey) == 0) return false;
    if ((key & Keys.Shift) == Keys.Shift &&
      GetAsyncKeyState(Keys.LShiftKey) == 0 && GetAsyncKeyState(Keys.RShiftKey) == 0) return false;
    if ((key & Keys.Alt) == Keys.Alt &&
      GetAsyncKeyState(Keys.LMenu) == 0 && GetAsyncKeyState(Keys.RMenu) == 0) return false;
    return true;
  }

  // P/Invoke declarations
  [StructLayout(LayoutKind.Sequential)]
  private struct KBDLLHOOKSTRUCT {
    public Keys key;
    public int scanCode;
    public int flags;
    public int time;
    public IntPtr extra;
  }
  private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
  [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  private static extern IntPtr SetWindowsHookEx(int id, LowLevelKeyboardProc callback, IntPtr hMod, uint dwThreadId);
  [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  private static extern bool UnhookWindowsHookEx(IntPtr hook);
  [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  private static extern IntPtr CallNextHookEx(IntPtr hook, int nCode, IntPtr wp, IntPtr lp);
  [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  private static extern IntPtr GetModuleHandle(string name);
  [DllImport("user32.dll", CharSet = CharSet.Auto)]
  private static extern short GetAsyncKeyState(Keys key);
}

Add this line to your main form:

    KeyboardFilter filter = new KeyboardFilter(new Keys[] { Keys.LWin, Keys.RWin, Keys.Escape | Keys.Control }); 

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.

Chủ Nhật, 9 tháng 5, 2010

String Format for DateTime [C#]

String Format for DateTime [C#]

This example shows how to format DateTime using String.Format method. All formatting can be done also using DateTime.ToString method.

Custom DateTime Formatting

There are following custom format specifiers y (year), M (month), d (day), h (hour 12), H (hour 24), m (minute), s (second), f (second fraction), F (second fraction, trailing zeroes are trimmed),t (P.M or A.M) and z (time zone).
Following examples demonstrate how are the format specifiers rewritten to the output.
[C#]
// create date time 2008-03-09 16:05:07.123
DateTime dt = new DateTime(2008, 3, 9, 16, 5, 7, 123);

String.Format("{0:y yy yyy yyyy}", dt);  // "8 08 008 2008"   year
String.Format("{0:M MM MMM MMMM}", dt);  // "3 03 Mar March"  month
String.Format("{0:d dd ddd dddd}", dt);  // "9 09 Sun Sunday" day
String.Format("{0:h hh H HH}",     dt);  // "4 04 16 16"      hour 12/24
String.Format("{0:m mm}",          dt);  // "5 05"            minute
String.Format("{0:s ss}",          dt);  // "7 07"            second
String.Format("{0:f ff fff ffff}", dt);  // "1 12 123 1230"   sec.fraction
String.Format("{0:F FF FFF FFFF}", dt);  // "1 12 123 123"    without zeroes
String.Format("{0:t tt}",          dt);  // "P PM"            A.M. or P.M.
String.Format("{0:z zz zzz}",      dt);  // "-6 -06 -06:00"   time zone

You can use also date separator / (slash) and time sepatator : (colon). These characters will be rewritten to characters defined in the current DateTimeForma tInfo.DateSepa rator andDateTimeForma tInfo.TimeSepa rator.
[C#]
// date separator in german culture is "." (so "/" changes to ".")
String.Format("{0:d/M/yyyy HH:mm:ss}", dt); // "9/3/2008 16:05:07" - english (en-US)
String.Format("{0:d/M/yyyy HH:mm:ss}", dt); // "9.3.2008 16:05:07" - german (de-DE)

Here are some examples of custom date and time formatting:
[C#]
// month/day numbers without/with leading zeroes
String.Format("{0:M/d/yyyy}", dt);            // "3/9/2008"
String.Format("{0:MM/dd/yyyy}", dt);          // "03/09/2008"

// day/month names
String.Format("{0:ddd, MMM d, yyyy}", dt);    // "Sun, Mar 9, 2008"
String.Format("{0:dddd, MMMM d, yyyy}", dt);  // "Sunday, March 9, 2008"

// two/four digit year
String.Format("{0:MM/dd/yy}", dt);            // "03/09/08"
String.Format("{0:MM/dd/yyyy}", dt);          // "03/09/2008"

Standard DateTime Formatting

In DateTimeForma tInfo there are defined standard patterns for the current culture. For example property ShortTimePattern is string that contains value h:mm tt for en-US culture and value HH:mm for de-DE culture.
Following table shows patterns defined in DateTimeForma tInfo and their values for en-US culture. First column contains format specifiers for the String.Format method.

SpecifierDateTimeFormatInfo propertyPattern value (for en-US culture)
tShortTimePatternh:mm tt
dShortDatePatternM/d/yyyy
TLongTimePatternh:mm:ss tt
DLongDatePatterndddd, MMMM dd, yyyy
f(combination of D and t)dddd, MMMM dd, yyyy h:mm tt
FFullDateTimePatterndddd, MMMM dd, yyyy h:mm:ss tt
g(combination of d and t)M/d/yyyy h:mm tt
G(combination of d and T)M/d/yyyy h:mm:ss tt
mMMonthDayPatternMMMM dd
yYYearMonthPatternMMMM, yyyy
rRRFC1123Patternddd, dd MMM yyyy HH':'mm':'ss 'GMT' (*)
sSortableDateTi mePatternyyyy'-'MM'-'dd'T'HH':'mm':'ss (*)
uUniversalSorta bleDateTimePat ternyyyy'-'MM'-'dd HH':'mm':'ss'Z' (*)
  (*) = culture independent

Following examples show usage of standard format specifiers in String.Format method and the resulting output.
[C#]
String.Format("{0:t}", dt);  // "4:05 PM"                         ShortTime
String.Format("{0:d}", dt);  // "3/9/2008"                        ShortDate
String.Format("{0:T}", dt);  // "4:05:07 PM"                      LongTime
String.Format("{0:D}", dt);  // "Sunday, March 09, 2008"          LongDate
String.Format("{0:f}", dt);  // "Sunday, March 09, 2008 4:05 PM"  LongDate+ShortTime
String.Format("{0:F}", dt);  // "Sunday, March 09, 2008 4:05:07 PM" FullDateTime
String.Format("{0:g}", dt);  // "3/9/2008 4:05 PM"                ShortDate+ShortTime
String.Format("{0:G}", dt);  // "3/9/2008 4:05:07 PM"             ShortDate+LongTime
String.Format("{0:m}", dt);  // "March 09"                        MonthDay
String.Format("{0:y}", dt);  // "March, 2008"                     YearMonth
String.Format("{0:r}", dt);  // "Sun, 09 Mar 2008 16:05:07 GMT"   RFC1123
String.Format("{0:s}", dt);  // "2008-03-09T16:05:07"             SortableDateTime
String.Format("{0:u}", dt);  // "2008-03-09 16:05:07Z"            UniversalSor