Wednesday, 4 May 2016

How to clear clipboard text using C#.Net

Known exceptions:

Case 1:
It you use Clipboard.SetText(string.Empty) to clear clipboard text, you will get an ArgumentNullException exception: "Value cannot be NULL".

It is because you cannot set empty string or null using Clipboard.SetText function.

Case 2:
If you use Clipboard.Clear() function, you will get the below error:

"An unhandled exception of type 'System.Threading.ThreadStateException' occurred in System.Windows.Forms.dll

Additional information: Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it."

To fix the above 2 exceptions, use the following code:

 public void deleteClipboardText()
        {
            try
            {
                Thread th = new Thread(new ThreadStart(clearClipboardText));
                th.SetApartmentState(ApartmentState.STA);
                th.Start();
                th.Join();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        public void clearClipboardText()
        {
            System.Windows.Forms.Clipboard.Clear();
        }

Friday, 29 April 2016

How to get Clipboard data and its size in C#.Net

Following function will get the clipboard data:

        [DllImport("user32.dll")]
        static extern IntPtr GetClipboardData(uint uFormat);
        [DllImport("user32.dll")]
        static extern bool IsClipboardFormatAvailable(uint format);
        [DllImport("user32.dll", SetLastError = true)]
        static extern bool OpenClipboard(IntPtr hWndNewOwner);
        [DllImport("user32.dll", SetLastError = true)]
        static extern bool CloseClipboard();
        [DllImport("kernel32.dll")]
        static extern IntPtr GlobalLock(IntPtr hMem);
        [DllImport("kernel32.dll")]
        static extern bool GlobalUnlock(IntPtr hMem);

        const uint CF_UNICODETEXT = 13;
        public static string GetText()
        {
            if (!IsClipboardFormatAvailable(CF_UNICODETEXT))
                return null;
            if (!OpenClipboard(IntPtr.Zero))
                return null;

            string data = null;
            var hGlobal = GetClipboardData(CF_UNICODETEXT);
            if (hGlobal != IntPtr.Zero)
            {
                var lpwcstr = GlobalLock(hGlobal);
                if (lpwcstr != IntPtr.Zero)
                {
                    data = Marshal.PtrToStringUni(lpwcstr);
                    GlobalUnlock(lpwcstr);
                }
            }
            CloseClipboard();

            return data;
        }


In order to get the size of clipboard text, you would need to copy the text in a file and then get the size of file as shown in the below code:

public long getClipboardTextSize()
        {
                string text = GetText();
                System.IO.File.WriteAllText("C:\\ClipboardText.txt", text);
                FileInfo fi = new FileInfo(path);
                if (fi.Exists)
                {
                    return fi.Length;
                }
                else
                {
                    return 0;
                }
            }
        }

Thursday, 28 April 2016

Get startup programs of all users using C#.Net

The below code will demonstrate how to list all the startup programs (also listed in msconfig) using C#.Net.

A custom class (cStartupPrograms) is added to store a startup program and it's relevant properties.

 public class cStartupPrograms
    {
        public int StartupProgramId { get; set; }
        public int ComputerId { get; set; }
        public int StartupClassificationId { get; set; }
        public string StartupClassificationName { get; set; }
        public string ProgramName { get; set; }
        public string ProgramPath { get; set; }
        public bool? IsEnabled { get; set; }
        public bool? IsDeleted { get; set; }
        public string StartupType { get; set; }
        public string Publisher { get; set; }
        public string startupUserName { get; set; }
}

Below are the locations from where the startup programs are retrieved:

public static List<string> startupProgramsRegistryNames_Enabled = new List<string>()
        {
            @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", //HKLM, HKCU
            @"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run",  //HKLM
            @"SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce"
        };

        public static List<string> startupProgramsRegistryNames_Disabled = new List<string>()
        {
            @"SOFTWARE\Microsoft\Shared Tools\MSConfig\startupfolder",  //HKLM
            @"SOFTWARE\Microsoft\Shared Tools\MSConfig\startupreg"  //HKLM          
        };

        public static List<string> startupProgramsRegistryNames_Enabled_OtherUsers = new List<string>()
        {
            @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", //HKEY_USERS
            @"SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce"
        };

        public static string startupProgramPath = @"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup";


Below function will retrieve the list of startup program of all users:
private void getAllStartupPrograms()
        {
            List<cStartupPrograms> cStartupProgramList = null;

            RegistryInfo rInfo1 = new RegistryInfo();
            rInfo1.registryKey = Registry.CurrentUser;

            RegistryInfo rInfo2 = new RegistryInfo();
            rInfo2.registryKey = Registry.LocalMachine;

            List<RegistryInfo> rInfoList = new List<RegistryInfo>();
            rInfoList.Add(rInfo1);
            rInfoList.Add(rInfo2);

            try
            {
                cStartupProgramList = new List<cStartupPrograms>();
                //Enabled programs
                //All users
                string[] files = Directory.GetFiles(startupProgramPath, "*");
                foreach (string fileName in files)
                {
                    if (File.Exists(fileName))
                    {
                        string target = GetShortcutTargetFile(fileName);
                        if (!String.IsNullOrEmpty(target))
                        {
                            cStartupPrograms startupProgram = new cStartupPrograms();

                            startupProgram.ComputerId = Convert.ToInt32(frmPreferences.ComputerId);
                            startupProgram.IsDeleted = false;
                            startupProgram.IsEnabled = true;
                            startupProgram.ProgramName = System.IO.Path.GetFileName(fileName);
                            startupProgram.ProgramPath = target;
                            startupProgram.StartupClassificationName = cEnum.eStartupClassification.Windows.ToString();
                            startupProgram.startupUserName = "All Users";
                            startupProgram.StartupType =startupProgramPath;
                           
                            //if (!cStartupProgramList.Exists(p => p.ProgramName == fileName && p.ProgramPath == target))
                            cStartupProgramList.Add(startupProgram);
                        }
                    }
                }

                //All users
                foreach (RegistryInfo rInfo in rInfoList)
                {
                    RegistryKey regKey = rInfo.registryKey;
                    foreach (string registryName in startupProgramsRegistryNames_Enabled)
                    {
                        string runOrRunOnceString = null;
                        int n = registryName.LastIndexOf("\\");
                        runOrRunOnceString = registryName.Substring(n + 1);
                        using (RegistryKey startupKey = regKey.OpenSubKey(registryName))
                        {
                            if (startupKey == null)
                                continue;

                            var valueNames = startupKey.GetValueNames();
                            foreach (var name in valueNames)
                            {
                                cStartupPrograms startupProgram = new .cStartupPrograms();

                                startupProgram.ComputerId = Convert.ToInt32(frmPreferences.ComputerId);
                                startupProgram.IsDeleted = false;
                                startupProgram.IsEnabled = true;
                                startupProgram.ProgramName = name;
                                startupProgram.ProgramPath = Convert.ToString(startupKey.GetValue(name));
                                startupProgram.StartupClassificationName = cEnum.eStartupClassification.Windows.ToString();
                                startupProgram.startupUserName = "All Users";
                                startupProgram.StartupType = startupKey.ToString();

                                //if (!cStartupProgramList.Exists(p => p.ProgramName == name && p.ProgramPath == startupProgram.ProgramPath))
                                cStartupProgramList.Add(startupProgram);
                            }
                        }
                    }
                }

                //Other users
                string[] hkeyUserNames = Registry.Users.GetSubKeyNames();
                foreach (string key in hkeyUserNames)
                {
                    string userName = GetOwnerName(key);
                    if (string.IsNullOrEmpty(userName))
                        continue;

                    RegistryKey startupKey = Registry.Users.OpenSubKey(key);
                    if (startupKey == null)
                        continue;

                    foreach (string registryName in startupProgramsRegistryNames_Enabled_OtherUsers)
                    {
                        string runOrRunOnceString = null;
                        int n = registryName.LastIndexOf("\\");
                        runOrRunOnceString = registryName.Substring(n + 1);

                        using (RegistryKey userKey = startupKey.OpenSubKey(registryName))
                        {
                            if (userKey == null)
                                continue;

                            var valueNames = userKey.GetValueNames();
                            foreach (var name in valueNames)
                            {
                                cStartupPrograms startupProgram = new cStartupPrograms();
                                startupProgram.ComputerId = Convert.ToInt32(frmPreferences.ComputerId);
                                startupProgram.IsDeleted = false;
                                startupProgram.IsEnabled = true;
                                startupProgram.ProgramName = name;
                                startupProgram.ProgramPath = Convert.ToString(userKey.GetValue(name));
                                startupProgram.StartupClassificationName = cEnum.eStartupClassification.Windows.ToString();
                                startupProgram.startupUserName = userName;
                                startupProgram.StartupType = userKey.ToString();
                                //if (!cStartupProgramList.Exists(p => p.ProgramName == name && p.ProgramPath == startupProgram.ProgramPath && p.startupUserName==userName))
                                cStartupProgramList.Add(startupProgram);
                            }
                        }
                    }
                }

                //Disabled programs
                foreach (string registryName in startupProgramsRegistryNames_Disabled)
                {
                    using (RegistryKey hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)) //
                    {
                        using (RegistryKey startupkey = hklm.OpenSubKey(registryName))
                        {

                            if (startupkey == null)
                                continue;

                            foreach (string key in startupkey.GetSubKeyNames())
                            {
                                using (RegistryKey rk = startupkey.OpenSubKey(key))
                                {
                                    cStartupPrograms startupProgram = new cStartupPrograms();

                                    startupProgram.ComputerId = Convert.ToInt32(frmPreferences.ComputerId);
                                    startupProgram.IsDeleted = false;
                                    startupProgram.IsEnabled = false;
                                    startupProgram.ProgramName = Convert.ToString(rk.GetValue("item"));
                                    startupProgram.ProgramPath = Convert.ToString(rk.GetValue("command"));
                                    startupProgram.StartupClassificationName = cEnum.eStartupClassification.Windows.ToString();
                                    var hkeyVal = rk.GetValue("hkey");
                                    if (hkeyVal != null)
                                    {
                                        string keyVal = Convert.ToString(rk.GetValue("key"));
                                        string runOrRunOnceString = null;
                                        int n = keyVal.LastIndexOf("\\");
                                        runOrRunOnceString = keyVal.Substring(n + 1);

                                        if (hkeyVal.ToString() == "HKLM")
                                        {
                                            startupProgram.StartupType = Registry.LocalMachine.ToString() + "\\" + keyVal;
                                           
                                        }
                                        else if (hkeyVal.ToString() == "HKCU")
                                        {
                                            startupProgram.StartupType = Registry.CurrentUser.ToString() + "\\" + keyVal;
                                         
                                        }
                                    }
                                    else
                                    {
                                        startupProgram.StartupType = Convert.ToString(rk.GetValue("location"));
                                    }
                                    startupProgram.startupUserName = "All Users";
                                 
                                    //if (!cStartupProgramList.Exists(p => p.ProgramName == startupProgram.ProgramName && p.ProgramPath == startupProgram.ProgramPath))
                                    cStartupProgramList.Add(startupProgram);

                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
               
                return;
            }
        }

Wednesday, 13 April 2016

Convert content of XML file to JSON string in C#.Net

The below function will convert the content of XML file to JSON string:

private string convertXMLToJSON()
        {
            string xmlLogPath = "<<Path to the xml file>>";

            // Load the XML file
            var xDocument = System.Xml.Linq.XDocument.Load(xmlLogPath);

            // Read the XML file content and write it to string
            string xml = xDocument.ToString();

            // Load the XML string
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml);

            // Convert the XML string to JSON string
            string jsonText = JsonConvert.SerializeXmlNode(doc);

            //Release the memory
            doc = null;
            xmlLogPath = null;
            xml = null;
            xDocument = null;
     
            //Return the JSON string
            return jsonText;

        }

IMPORTANT NOTE:

Releasing object memory is very important. Even if your object went out of scope, it is not removed from the garbage collection. It happens because the variable still has some value in it. So Garbage collector think that the variable is in use and it doesn't remove it from the memory.

Setting it to NULL, tells the garbage collector that the object is no longer in use and can be removed from the garbage collection.

Tuesday, 12 April 2016

Start and stop a console application using C#

Start a console application:


System.Diagnostics.Process aspProcess = null;
private void start_console_app()
        {
            try
            {
                string pathToExe = @"<<Path to the exe >> ";
                
                if (aspProcess == null)
                {
                    aspProcess = new System.Diagnostics.Process();
                }
                
                //Path and file name of command to run
                aspProcess.StartInfo.FileName = pathToExe;
                aspProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

                //Parameters to pass to program
                aspProcess.StartInfo.Arguments = "<<arguments you want to pass>>";

                aspProcess.StartInfo.UseShellExecute = true;
                aspProcess.StartInfo.CreateNoWindow = true;

                //Start the process
                aspProcess.Start();

                //Wait for process to finish
                aspProcess.WaitForExit();
                aspProcess = null;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

1. For starting a console application, you would need to create an object of class "System.Diagnostics.Process".
2. "FileName" is the path of the exe (console application).
3.  "Arguments" - It will send arguments to your console application.
4.  ProcessWindowStyle.Hidden will hide the console window.
5. Start () method will start the process.

Stop a console application by sending "Control + C" Signal:


public void stop_console_app()
        {
            // Release the current console, as you cannot attach 2 consoles at the same time
            if (aspProcess != null)
            {
                uint pid = (uint)aspProcess.Id;
                FreeConsole();

                // This does not require the console window to be visible.
                if (AttachConsole(pid))
                {
                    // Disable Ctrl-C handling for our program
                    SetConsoleCtrlHandler(null, true);
                    GenerateConsoleCtrlEvent(CtrlTypes.CTRL_C_EVENT, 0);

                    // Must wait here. If we don't and re-enable Ctrl-C
                    // handling below too fast, we might terminate ourselves.
                    Thread.Sleep(2000);

                    FreeConsole();

                    // Re-enable Ctrl-C handling or any subsequently started
                    // programs will inherit the disabled state.
                    SetConsoleCtrlHandler(null, false);
                }
            }
        }

You can add "Console_CancelKeyPress" event in your console application to nicely terminate it. If you want to call this method from another application (from where you've started your console application), add the above method.

Thursday, 26 November 2015

How to make the Windows Desktop application work well on High-DPI Displays and Fix Blurry Fonts

If you change the DPI of your machine from 100% to any other higher value, your desktop applications may appear somewhat blurry when you compare them with other applications on the screen. Alternately, display problems may exist such as truncated text.



In order to fix this issue, you would need to Disable DPI virtualization for the application. To do this, right-click the application’s shortcut and then click Properties. On the Compatibility tab, select Disable Display Scaling on High DPI Settings, and then click OK.




Alternatively, you may also disable this setting using the below Registry keys.

Registry key: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers

String: “Path to your application exe”
Value:   ~ HIGHDPIAWARE
Please note there is a space between ‘tilde’ and ‘HIGHDPIAWARE’.



There are number of ways to set a value in the registry. Below steps will show the process to set this value in registry using Inno setup:

var
str_MyAppFullExePath: String;

str_MyAppFullExePath := ExpandConstant('{app}') ;

RegWriteStringValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers', str_MyAppFullExePath + '\' + '{#MyAppExeName}' , '~ HIGHDPIAWARE');

Possible Issues:

If your application is 32 bit, then the above command will set the value at

“HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers” 

instead of 

“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers”. 

This will not set the “Disable Display Scaling on High DPI Settings” property. This can be fixed by using the below command:

if IsWin64 then
 begin
 RegWriteStringValue(HKLM64, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers', str_MyAppFullExePath + '\' + '{#MyAppExeName}' , '~ HIGHDPIAWARE');
 end
 else
 begin
 RegWriteStringValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers', str_MyAppFullExePath + '\' + '{#MyAppExeName}' , '~ HIGHDPIAWARE');
 end ;

It will force the setup to store value in 64 bit registry.

Monday, 23 November 2015

How to extract the associated icon of any file in C#.Net

To extract icon of any file, define the below class and the structure:

[StructLayout(LayoutKind.Sequential)]
        public struct SHFILEINFO
        {
            public IntPtr hIcon;
            public IntPtr iIcon;
            public uint dwAttributes;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
            public string szDisplayName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
            public string szTypeName;
        };


class Win32
        {
            public const uint SHGFI_ICON = 0x100;
            public const uint SHGFI_LARGEICON = 0x0;    // 'Large icon
            public const uint SHGFI_SMALLICON = 0x1;    // 'Small icon

            [DllImport("shell32.dll")]
            public static extern IntPtr SHGetFileInfo(string pszPath,
                                        uint dwFileAttributes,
                                        ref SHFILEINFO psfi,
                                        uint cbSizeFileInfo,
                                        uint uFlags);

            [DllImport("User32.dll")]
            public static extern int DestroyIcon(IntPtr hIcon);
        }

Now define the following function:

SHFILEINFO shinfo = new SHFILEINFO();
/* Define it globally so that you can use the same object for all  the files. */
public Bitmap extractAssociatedIcon(string fName)
        {
            Icon myIcon = null;
            try
            {
                IntPtr hImgSmall;    //the handle to the system image list              

                hImgSmall = Win32.SHGetFileInfo(fName, 0, ref shinfo,
                                 (uint)Marshal.SizeOf(shinfo),
                                  Win32.SHGFI_ICON |
                                  Win32.SHGFI_SMALLICON);

                if (shinfo.hIcon != IntPtr.Zero)
                    myIcon = Icon.FromHandle(shinfo.hIcon);              

            }
            catch (Exception ex)
            {
                // Handle any exception here
            }
            return myIcon.ToBitmap();
        }


Get the icon by calling the above defined function.

Bitmap image = extractAssociatedIcon("fullPath to the file");

Once you get the icon, make sure you destroy the icon. This is very important, else you will run into memory issues.

Win32.DestroyIcon(shinfo.hIcon);