Tuesday 15 November 2016

How to host WCF service in IIS manager

To host the WCF service, follow the below steps:
  1. Add virtual directory in "IIS Manager"
    1. PC Name -> Sites -> Default Web Site -> Add virtual directory
    2. Type in the alias (name) and browse to the physical path (where .svc file resides).
  2. Right click on the added application, select "Convert to application".
  3. Test the hosted application by clicking the "Browse button".

Possible issues:
  1. HTTP Error 404.3 - Not Found The page you are requesting cannot be served because of the extension configuration. If the page is a script, add a handler. If the file should be downloaded, add a MIME map.
Solution:
Turn on/off windows features: Make sure that the below features are turned on:
  • .net framework 3.5 and 4.5.
  • IIS


  1. If you can't access WCF service hosted on IIS remotely but can access it locally
Solution: 
Make sure firewall on the hosted machine is OFF.

Wednesday 28 September 2016

How to Enable, Disable and Start the task of task scheduler in C#.Net

Below function demonstrates how to enable, disable and run the already created scheduled task. It will first check if the task exists in task scheduler:

public static void updateUserTaskInScheduler(string action)
        {
            try
            {
                ProcessStartInfo startInfo = new ProcessStartInfo();
                startInfo.FileName = "cmd.exe";
                startInfo.Arguments = "/C schtasks /query /TN <<TaskNameWithQuotes>>; //Check if task exists
                startInfo.RedirectStandardOutput = true;
                startInfo.UseShellExecute = false;
                startInfo.CreateNoWindow = true;
                startInfo.WindowStyle = ProcessWindowStyle.Hidden;
                if (System.Environment.OSVersion.Version.Major < 6)
                {
                    startInfo.Verb = "runas";
                }
                using (Process process = Process.Start(startInfo))
                {
                    // Read in all the text from the process with the StreamReader.
                    using (StreamReader reader = process.StandardOutput)
                    {
                        string stdout = reader.ReadToEnd();
                        if (stdout.Contains("<<TaskName>>")) //If task exists
                        {
                            startInfo.RedirectStandardOutput = false;
                            startInfo.UseShellExecute = true;
                            switch (action)
                            {
                                case "Enable":
                                    startInfo.Arguments = "/C schtasks /Change /TN <<TaskNameWithQuotes>>  /Enable";
                                    break;

                                case "Disable":
                                    startInfo.Arguments = "/C schtasks /Change /TN <<TaskNameWithQuotes>> /Disable";
                                    break;

                                case "Run":
                                    startInfo.Arguments = "/C schtasks /RUN /TN <<TaskNameWithQuotes>> ";
                                    break;
                            }
                            Process.Start(startInfo).WaitForExit();
                        }
                        else
                        {
                             //Task doesnot exist
                        }
                        stdout = null;
                        reader.Close();
                        reader.Dispose();
                    }
                }
                startInfo = null;
            }
            catch (Exception ex)
            {
                    MessageBox.Show(ex.Message);
            }
        }


The above function can be called in the below manner:

1. To run the task:
            updateUserTaskInScheduler("Run");

2. To enable the task:
            updateUserTaskInScheduler("Enable");

3. To disable the task:
            updateUserTaskInScheduler("Disable");

Friday 26 August 2016

How to load registry hive of logged off users in C#.Net

In HKEY_USERS, SIDs of only logged in users are present by default. If you need to make changes in any user's registry in logged off state, you will have to load the registry hive of that particular user.

Registry hive can be loaded by using NTUser.dat file loacted in "C:\Users\{Username}". {Username} is the name of the logged off user.

Following is the sample code required for this task:

 internal static readonly IntPtr HKEY_USERS = new IntPtr(unchecked((int)0x80000003));

[DllImport("advapi32.dll", SetLastError = true)]
static extern Int32 RegLoadKey(IntPtr hKey, string lpSubKey, string lpFile);

Create a below function:

 public static void loadUserRegistryHive(string username, string keyName)
        {
            try
            {
                string path ="C:\Users\{Username}\NTUSER.DAT";
                FileInfo fi = new FileInfo(path);
                if (fi.Exists)
                {
                    int retVal = RegLoadKey(HKEY_USERS, keyName, path);
                    if (retVal  == 0)
                            MessageBox.Show("Success");
                    else
                            MessageBox.Show("Failure");                  
                }
                else
                {
                    MessageBox.Show("NTUSER.DAT file does not exist in path");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

General Exception:

While using RegLoadKey in the above function, you may get 1314 as the return value. This is the indication that you don't have the necessary privileges to load the registry hive. To do so, use the below code:

public static void adjustPriviledge()
        {
            try
            {
                // Access token handle reused within the using block.
                using (AccessTokenHandle accessTokenHandle =
                    Process.GetCurrentProcess().GetAccessTokenHandle(
                        TokenAccessRights.AdjustPrivileges | TokenAccessRights.Query))
                {
                    // Enable privileges using the same access token handle.
                    AdjustPrivilegeResult backupResult = accessTokenHandle.EnablePrivilege(Privilege.Backup);
                    AdjustPrivilegeResult restoreResult = accessTokenHandle.EnablePrivilege(Privilege.Restore);
                }
            }
            catch (Exception ex)
            {
                      MessageBox.Show(ex.Message);
            }
        }

The above function will add the SE_BACKUP_NAME and SE_RESTORE_NAME privileges required to load the registry hive.

To use the function above you will have to include the below dll:
ProcessPrivileges.dll

You can download it from here:
https://processprivileges.codeplex.com/

It's an open source dll:
License details: https://processprivileges.codeplex.com/license

You will have to call function "adjustPriviledge" in function "loadUserRegistryHive" just before calling function "RegLoadKey" as shown below:

 adjustPriviledge();
 int retVal = RegLoadKey(HKEY_USERS, keyName, path);

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.