A simple Folder Watcher for windows

Here is a simple file system watcher for windows. I wrote a script to monitor a folder for a specific purpose, but then thought to make this a generic tool so someone will benefit if I host in GitHub.

FolderWatcher

 

Find full project at https://github.com/ninethsense/FolderWatcher

 

Source Code:

private void Form1_Load(object sender, EventArgs e)
{
    toolStripLabel.Text = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);

    StartMonitoring();
}

private void StartMonitoring()
{
    watcher = new FileSystemWatcher(toolStripLabel.Text)
    {
        IncludeSubdirectories = true,
        EnableRaisingEvents = true
    };
    watcher.Created += Watcher_Handler;
    watcher.Deleted += Watcher_Handler;
    watcher.Renamed += Watcher_Handler;
    watcher.Changed += Watcher_Handler;
}

private void Watcher_Handler(object sender, FileSystemEventArgs e)
{
    Invoke(new Action(() =>
    {
        listBoxLog.Items.Add($"[{DateTime.Now}][{e.ChangeType}] {e.FullPath}");
    }));
}

private void ToolStripClearButton_Click(object sender, EventArgs e)
{
    listBoxLog.Items.Clear();
}

private void ToolStripChooseFolderButton_Click(object sender, EventArgs e)
{
    watcher.EnableRaisingEvents = false;
    folderBrowserDialog.SelectedPath = toolStripLabel.Text;
    var dlg = folderBrowserDialog.ShowDialog();

    if (dlg == DialogResult.OK)
    {
        string OldPath = toolStripLabel.Text;

        try
        {
            watcher.Path = folderBrowserDialog.SelectedPath;
            watcher.EnableRaisingEvents = true;
        } catch (FileNotFoundException ex)
        {
            toolStripLabel.Text = OldPath;
            watcher.Path = OldPath;

            MessageBox.Show($"Seems you don't have permission to access folder        {folderBrowserDialog.SelectedPath}. Try starting this app as Administrator\n\nDetails:\n{ex.Message}", "Error", MessageBoxButtons.OK);
            watcher.EnableRaisingEvents = true;
        }
            toolStripLabel.Text = watcher.Path;

    }

}

Create AWS Lambda function with .NET Core / C# and create a HTTP API Gateway trigger | Part #2

In this Part #2 of blog I will be creating a new .NET Core function in local machine and will upload to AWS using console interface. There are different ways you can develop and deploy but I will be talking in this blog only about the CLI way.

I am assuming you know how to create a Lambda function in AWS console already and if not, please read the Part #1 first.

Open the Command prompt and follow below steps:

Step 1: Install Lambda Templates for .NET Core

dotnet new -i Amazon.Lambda.Templates

Step 2: Create an empty function

dotnet new lambda.EmptyFunction –name MyTestLambdaFun


You should be able to see a folder structure like this is created.

image

under src\projectname you can see a Function.cs file which is our starting point.

Code will look like this:

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

using Amazon.Lambda.Core;

// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace MyTestLambdaFun
{
     public class Function
     {
        
         /// <summary>
         /// A simple function that takes a string and does a ToUpper
         /// </summary>
         /// <param name="input"></param>
         /// <param name="context"></param>
         /// <returns></returns>
         public string FunctionHandler(string input, ILambdaContext context)
         {
             return input?.ToUpper();
         }
     }
}

Step 3 – Modify the code to return HTTP 200 status code.

It is necessary for lambda functions to return 200 status code, or else the function will work in AWS console when you “Test”, but the API Gateway endpoint will not.

After adding the StatusCode property, the function will look like this:

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

using Amazon.Lambda.Core;

using Amazon.Lambda.APIGatewayEvents;

// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace MyTestLambdaFun
{
     public class Function
     {
        
         /// <summary>
         /// A simple function that takes a string and does a ToUpper
         /// </summary>
         /// <param name="input"></param>
         /// <param name="context"></param>
         /// <returns></returns>
         public APIGatewayProxyResponse FunctionHandler(ILambdaContext context)
         {
             return new APIGatewayProxyResponse
             {
                 Body = "Hello Lambda, from Praveen",
                 StatusCode = 200
             };

            
         }
     }
}

Do:

dotnet build


Now, if you are getting an error on APIGatewayProxyResponse, then you will have to install the dependency. Below command will help you:


dotnet add package Amazon.Lambda.APIGatewayEvents 

(Refer to nuget page)

Try again dotnet build, and I am expecting to have the build succeeded.

image

Step 4 – Package the function

If you have not installed Lambda tools, then install it first:

dotnet tool install -g Amazon.Lambda.Tools

Then use the command:

dotnet lambda package

image

Notice the last line, you will get path to a zip file which you have to upload to AWS Lambda.

Step 5 – Upload the package to AWS console

Login to AWS Console and navigate to your lambda function. In this example I am going to use the same function we created in Part #1.

Scroll up and you should see a “Function Code” section like this:

image

Upload your ZIP file by clicking the upload button.

Next, you have to do one important task. Go to the source code folder again and open a file named “aws-lambda-tools-defaults.json”.  You will have to copy the function-handler property value to the “Handler” textbox in “Function code” section.

image

image

image

Then click “Save” button.

Step 6 – Test the function

Click “Test”. You should see the test result like this: (Our function is not expecting an input parameter so you can create a dummy test event)

image

As a bonus, let us see how we can create a HTTP endpoint to this function.

Step 7 – Create API Gateway

Click “Trigger” button:

image

In the next screen, make these selections and click “Add”:

image

You will be redirected back to the dashboard. Scroll up and you will see a new section “API Gateway” with a new API endpoint URL. Use the link in browser to test.

image

image

Happy Lambda development!

You have noticed that I was rushing to finish the blog by not explaining in detail each step. I am leaving the rest to you as home work intentionally.

Refer to official .NET Core CLI documentation here.

Clone/Copy SQL Server Database with timestamp in name

This script works on Azure SQL Database also.

 DECLARE @cmd nvarchar(255) SET @cmd = N'CREATE DATABASE ' + CONCAT('MyDB_', REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR(16), GETDATE(), 120), '-', ''),':',''),' ','_')) + ' AS COPY OF MyDB' EXECUTE sp_executesql @cmd 

Loop multiple videos in HTML5 video tag

<video id="v" autoplay>
       <source src="1.mp4" type="video/mp4">
     </video>

    <script>
         var c = 0;
         f = [
                 "1.mp4",
                 "2.mp4",
                 "3.webm"
             ];
         var v = document.getElementById('v');
         v.addEventListener('ended', function(e) {
             c = (c < f.length-1)?++c:0;
             v.src = f[c];
             v.play();
         });
     </script>

Ajax file uploader using jQuery

Here is a sample code to upload multiple files using ajax, and without using the traditional <form> tags. Find the full source code in GitHub – https://github.com/ninethsense/code-share/tree/master/jQuery-File-Upload .

<body>
    <input type="button" value="Choose file" id="fup" />

    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>    

    <script>
            $(function() {

                // Show file upload dialog on click of button
                $("#fup").click(function(){

                    //Create File component
                    var fu = document.createElement("input");
                    fu.type = "file";
                    fu.id="fuc";
                    $(fu).attr("multiple","");

                    // Trigger file selection event
                    $(fu).change(function(){
                        var fd = new FormData();
                        $.each($(fu)[0].files, function(i, file){
                            fd.append('file[]', file);
                        });

                        // Send fd to server
                        $.ajax({
                            url:"FileUpload.php",
                            type: 'POST',
                            data:fd,
                            cache: false,
                            contentType: false,
                            processData: false,
                            success: function(d) {
                                console.log(d);
                            }
                        });
                    });

                    // To invoke the file selection dialog box
                    $(fu).click();

                });
            });
    </script>
</body>

Sample server code in PHP for the reference:

foreach ($_FILES['file']['tmp_name'] as $k => $v) {
move_uploaded_file(
$_FILES['file']['tmp_name'][$k],
$_FILES['file']['name'][$k]
);
}

Join two XML files using XSL Transformation

This blog demonstrates how you can JOIN (yes, like in SQL) two xml (datasets) to one using a common ID (relationship).

shop.xml


<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type='text/xsl' href='main.xsl'?>
<shop>
<product>
<id>100</id>
<title>hello</title>
</product>

<product>
<id>101</id>
<title>world</title>
</product>
<product>
<id>102</id>
<title>praveen</title>
</product>
</shop>

price.xml

<?xml version="1.0" encoding="UTF-8"?>
<shop>
<product>
<id>100</id>
<price>10.0</price>
</product>
<product>
<id>101</id>
<price>10.1</price>
</product>
<product>
<id>102</id>
<price>10.2</price>
</product>
<product>
<id>103</id>
<price>10.3</price>
</product>

</shop>

main.xsl


<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />

<xsl:param name="fileName" select="'price.xml'" />

<xsl:variable name="updateItems" select="document($fileName)/shop/product" />

<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
<xsl:copy-of select="$updateItems[id=current()/id]/price" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

Resulting XML, after transformation should look like:


<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type='text/xsl' href='main.xsl'?>
<shop>
<product>
<id>100</id>
<title>hello</title>
<price>10.0</price>
</product>
<product>
<id>101</id>
<title>world</title>
<price>10.1</price>
</product>
<product>
<id>102</id>
<title>praveen</title>
<price>10.2</price>
</product>
</shop>

Bonus code, if some .net developers want a transformation code:


XslTransform xslt = new XslTransform();
xslt.Load(@"D:\Websites\xmltest\main.xsl");
xslt.Transform(@"D:\Websites\xmltest\shop.xml", @"D:\Websites\xmltest\out.xml");
textBox1.Text = System.IO.File.ReadAllText(@"D:\Websites\xmltest\out.xml");

Programming Puzzle #2 – Leet Converter

Write a program in a computer language of your choice to convert any given text to “leet format” in real time.

Leet (or “1337”), is a system of modified spellings used primarily on the Internet.

Input: “Translator” Output:”Tr4nsl4t0r”
Input: “leet”, Output: “l33t”
Input: “Good Morning”, Output: “G00d M0rn1ng”

Evaluation criteria:

  1. Code Quality Standards
  2. OOAD/Object-Oriented Analysis & Design
  3. Application Logic
  4. Exception Handling
  5. Simplicity and Effectiveness of code

Time: 0-30 minutes max.

Programming Puzzle #1–Find the critical path

Write a program in a language of your choice to find the critical path from a given set of tasks.

A critical path is determined by identifying the longest stretch of dependent activities and measuring the time required to complete them from start to finish.

image

Each circle (A-G) are tasks with specific duration (in Hours).

Input:

Array of task names and duration given in the diagram.

Output

1. Longest path (Critical path) is A+G+B+F+C+D (42Hrs)
2. Shortest path is A+B+C+D (26 Hrs)

T-SQL script to create SQL Job for daily database backup

This script will create an SQL Server Agent job, which will take daily database backup to a folder with date appended in the filename.


DECLARE @job varchar(100) = 'Backup_testdb_daily' -- Name of Job
DECLARE @db varchar(100) = 'testdb' -- DB to backup
DECLARE @bakfile varchar(100) = 'd:\_temp\' + @db -- Backup file path

DECLARE @date varchar(8) = '20180720' -- Job Start date
DECLARE @time varchar(8) = '135400' -- Job run time. Eg: Run At 23rd hour

--------------------------------------------------------------------

DECLARE @cmd varchar(200) = CONCAT ('DECLARE @bakfile varchar(200) = ''' , @bakfile , ''' + ''_'' + convert(varchar(100),GetDate(),112) + ''.bak'';') +

CONCAT('BACKUP DATABASE ', @db, ' TO DISK = @bakfile');

USE msdb

EXEC dbo.sp_add_job
@job_name = @job;

EXEC sp_add_jobstep
@job_name = @job,
@step_name = 'Backup database',
@subsystem = 'TSQL',
@command = @cmd

EXEC sp_add_jobschedule
@job_name = @job,
@name = 'DB Backup Schedule',
@freq_type = 4, -- daily
@freq_interval = 1,
@active_start_date = @date,
@active_start_time = @time

EXEC dbo.sp_add_jobserver
@job_name = @job,
@server_name = @@SERVERNAME