C# A folder sync tool

January 26, 2017

Hi guys!

I’ve been busy with so many developments recently. Few projects for Oracle E-Business Suite R12 & few others for learning C#. I can say I’ve “learned” how to copy, paste, correct and useĀ it with my projects to produce beautiful results!

My recent C# projects include a WPF solution that uses WMI classes to generate hardware details for entire Windows Domain (Linux boxes are not dealt) & today I’ve decided to build a small solution that could synchronize my C# projects with our file server.

This small project can,

  • Replicate source Directory, subdirectories & files to destination folder
  • While re-ran, check whether the destination files are older than the source files and, if yes, overwrite the old ones with newer ones.

Interested to try it yourself? here comes the code

(This project uses codes copied from both MSDN & http://www.stackoverflow.com. RecursiveFileProcessor is a MSDN example, while File exists snippet was copied from stackoverflow)

using System;
using System.IO;
using System.Collections;

//http://stackoverflow.com/questions/58744/copy-the-entire-contents-of-a-directory-in-c-sharp
//

namespace RecursiveFileProcessor
{
    class Program
    {
        public static void Main(string[] args)
        {
            string sourceDirectory = @"D:\MyProjects";
            string targetDirectory = @"\\network_share_location\MyProjects";
            Copy(sourceDirectory, targetDirectory);
            Console.WriteLine();
            Console.WriteLine("Task Completed. Press any key to continue");
            Console.ReadLine();

        }

        public static void Copy(string sourceDirectory, string targetDirectory)
        {
            DirectoryInfo diSource = new DirectoryInfo(sourceDirectory);
            DirectoryInfo diTarget = new DirectoryInfo(targetDirectory);

            CopyAll(diSource, diTarget);
        }

        public static void CopyAll(DirectoryInfo source, DirectoryInfo target)
        {

            Directory.CreateDirectory(target.FullName);

            // Copy each file into the new directory.
            foreach (FileInfo fi in source.GetFiles())
            {

                DateTime created = fi.CreationTime;
                DateTime lastmodified = fi.LastWriteTime;

                if (File.Exists(Path.Combine(target.FullName, fi.Name)))
                {
                    string tFileName = Path.Combine(target.FullName, fi.Name);
                    FileInfo f2 = new FileInfo(tFileName);
                    DateTime lm = f2.LastWriteTime;
                    Console.WriteLine(@"File {0}\{1} Already Exist {2} last modified {3}", target.FullName, fi.Name, tFileName, lm);

                    try
                    {
                        if (lastmodified > lm)
                        {
                            Console.WriteLine(@"Source file {0}\{1} last modified {2} is newer than the target file {3}\{4} last modified {5}",
                                fi.DirectoryName, fi.Name, lastmodified.ToString(), target.FullName, fi.Name, lm.ToString());
                            fi.CopyTo(Path.Combine(target.FullName, fi.Name), true);
                        }
                        else
                        {
                            Console.WriteLine(@"Destination File {0}\{1} Skipped", target.FullName, fi.Name);
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }

                }
                else
                {
                    Console.WriteLine(@"Copying {0}\{1}", target.FullName, fi.Name);
                    fi.CopyTo(Path.Combine(target.FullName, fi.Name), true);
                }

            }

            // Copy each subdirectory using recursion.
            foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
            {
                DirectoryInfo nextTargetSubDir =
                    target.CreateSubdirectory(diSourceSubDir.Name);
                CopyAll(diSourceSubDir, nextTargetSubDir);
            }
        }

    }
}

Thumb rules:

  1. Do not set your source and destination folders the same.

This project uses Framework 4.5 & I am sure versions above 2.0 should support the classes referred.

If you are new to .net developments, create a project with the name “RecursiveFileProcessor”, which will let you copy and paste the whole code as it is to your project.

Do let me know whether you enjoyed your new sync toy!

regards,

rajesh


C# (CSharp, C-Sharp) Windows Active Directory last logon

January 7, 2017

Hi guys

Please note, many threads were referred in order to compile the script attached below & all I did was re-arranging in order for better reading/formatting

(And I insure that the script works under following scenarios:

  1. You are a domain administrator
  2. You are administrating Windows 2003 onwards Windows domain
  3. Your puter is connected to the domain network ;)

)

Referenced websites/threads

  1. http://stackoverflow.com/questions/15775264/searching-for-lastlogon-attribute-of-user-in-multiple-domain-servers
  2. https://www.codeproject.com/kb/security/lastlogonacrossallwindows.aspx#_comments
  3. http://codebeautify.org/csharpviewer (for formatting the C# code)

How to test the code

Start Visual Studio (I am using 2013 Professional edition, you can use any of the community editions to test the scripts)

Create a new C# Console Application and name it llogon (else you need to change the namespace name “llogon” according to the name you have chosen for your new project.

Add the following references to your project

  1. “Framework -> System.DirectoryServices”
  2. “Browse and add -> C:\Windows\System32\activeds.tlb”

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

//Added by Rajesh

//using System.Management;
//using System.Data;
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
//http://stackoverflow.com/questions/33274162/the-namespace-of-iadslargeinteger
//ActiveDS namespace
using ActiveDs; // Namespace added via ref to C:\Windows\System32\activeds.tlb
//https://www.codeproject.com/kb/security/lastlogonacrossallwindows.aspx

namespace llogon
{
    class Program
    {
        static void Main(string[] args)
        {
            // Get the root entry
            DirectoryEntry rootDSE = new DirectoryEntry("LDAP://RootDSE");
            string configurationNamingContext =
             (string)rootDSE.Properties["configurationNamingContext"].Value;
            string defaultNamingContext =
             (string)rootDSE.Properties["defaultNamingContext"].Value;
            Dictionary<string, Int64> lastLogons = new Dictionary<string, Int64>();
            // Get all the domain controllers
            DirectoryEntry deConfig = new DirectoryEntry("LDAP://" + configurationNamingContext);
            DirectorySearcher dsConfig = new DirectorySearcher(deConfig);
            dsConfig.Filter = "(objectClass=nTDSDSA)";
            foreach (SearchResult srDomains in dsConfig.FindAll())
            {
                DirectoryEntry deDomain = srDomains.GetDirectoryEntry();
                if (deDomain != null)
                {
                    string dnsHostName =
                     deDomain.Parent.Properties["DNSHostName"].Value.ToString();
                    // Get all the users for that domain
                                   DirectoryEntry deUsers =
                     new DirectoryEntry("LDAP://" + dnsHostName + "/" + defaultNamingContext);
                    DirectorySearcher dsUsers = new DirectorySearcher(deUsers);
                    dsUsers.Filter = "(&(objectCategory=person)(objectClass=user))";
                    foreach (SearchResult srUsers in dsUsers.FindAll())
                    {
                        DirectoryEntry deUser = srUsers.GetDirectoryEntry();
                        if (deUser != null)
                        {
                            // Get the distinguishedName and lastLogon for each user
                            // Save the most recent logon for each user in a Dictionary object
                            string distinguishedName = deUser.Properties["distinguishedName"].Value.ToString();
                            Int64 lastLogonThisServer = new Int64();
                            if (deUser.Properties["lastLogon"].Value != null)
                            {
                                IADsLargeInteger lgInt =
                                 (IADsLargeInteger)deUser.Properties["lastLogon"].Value;
                                lastLogonThisServer = ((long)lgInt.HighPart << 32) + lgInt.LowPart;
                            }

                            // Save the most recent logon for each user in a Dictionary object
                            if (lastLogons.ContainsKey(distinguishedName))
                            {
                                if (lastLogons[distinguishedName] < lastLogonThisServer)
                                {
                                    lastLogons[distinguishedName] = lastLogonThisServer;
                                }
                            }
                            else
                            {
                                lastLogons.Add(distinguishedName, lastLogonThisServer);
                            }
                            string readableLastLogon = DateTime.FromFileTime(lastLogonThisServer).ToString();
                            Console.WriteLine("User: " + distinguishedName + "Last logon: " +readableLastLogon);
                        }
                    }
                    Console.ReadLine();
                }
            }

        }
    }
}

Try the code & if you are stuck somewhere, do let me through the comments. I am working on a WPF C# project for a simple Active Directory Reporter / Asset Management System using WMI. Stay tuned & I will soon post the entire solution here :)

regards,

rajesh

 


It’s been long time!

April 19, 2016

Hello guys!

I know, there were NOT much to post throughout last few months about Oracle as I am nose down into one of the development platforms that I hardly desired for developing business applications.

For me, it was always Oracle forms and reports. The easiest, the most robust development tools for BUSINESS applications which is supported by the ease of SQL, PL/SQL

I am doing loads of research with C# & SQL database, which will be the main technologies behind our next proposed ERP suite. After spending almost 15 years with Forms and reports, I don’t see Oracle is too keen about modernizing their most loved development tools & the latest release lacks loads of features those would have helped to reclaim the desktop based business applications.

Wondering whether there is still room for desktop applications, especially for businesses? dude! there is, and there will be!

 

So stay tuned, I will start posting my “findings” about C#, who knows may be some sample applications using Windows forms or WPF & Oracle database in near future!

regards,

rajesh