Joseph Michael Pesch
VP Programming

C# Name Tuple Items

by 1. February 2018 14:29

To name tuple items in C#, first install the NuGet package: Install-Package System.ValueTuple

Syntax: (string ItemName, DateTime ItemName, etc.) vs. Tuple<string, DateTime>

Tags:

ASP.Net | C#

Debug Windows Service Running as Interactive Console Application

by 1. February 2018 08:40

Before running in Visual Studio change the project output type from Windows Application to Console Application.  Below is sample Program.cs code to run interactively in Visual Studio.

using System;
using System.Reflection;
using System.ServiceProcess;
using System.Threading;

namespace DemoWindowsService
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main()
        {
            ServiceBase[] servicesToRun;
            servicesToRun = new ServiceBase[]
            {
                new DemoService()
            };
            if (Environment.UserInteractive) RunInteractive(servicesToRun);
            else ServiceBase.Run(servicesToRun);
        }

        static void RunInteractive(ServiceBase[] servicesToRun)
        {
            Console.WriteLine("Services running in interactive mode.");
            Console.WriteLine();

            MethodInfo onStartMethod = typeof(ServiceBase).GetMethod("OnStart",
                BindingFlags.Instance | BindingFlags.NonPublic);
            foreach (ServiceBase service in servicesToRun)
            {
                Console.Write("Starting {0}...", service.ServiceName);
                onStartMethod.Invoke(service, new object[] { new string[] { } });
                Console.Write("Started");
            }

            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine(
                "Press any key to stop the services and end the process...");
            Console.ReadKey();
            Console.WriteLine();

            MethodInfo onStopMethod = typeof(ServiceBase).GetMethod("OnStop",
                BindingFlags.Instance | BindingFlags.NonPublic);
            foreach (ServiceBase service in servicesToRun)
            {
                Console.Write("Stopping {0}...", service.ServiceName);
                onStopMethod.Invoke(service, null);
                Console.WriteLine("Stopped");
            }

            Console.WriteLine("All services stopped.");
            // Keep the console alive for a few seconds to allow the user to see the message.
            Thread.Sleep(5000);
        }
    }
}

Tags:

ASP.Net | C# | Windows Service

Extract PDF File(s) from Adobe PDF Portfolio File Using iTextSharp Open Source PDF Library

by 28. August 2016 07:23

Using iTextSharp open source PDF library, the below console application illustrates opening one or more PDF files (based on file path and file mask inputs) and extracting a desired single PDF file from each.

using iTextSharp.text.pdf;
using System;
using System.Collections.Generic;
using System.IO;

namespace PdfPortfolioSample
{
  class Program
  {
    static void Main(string[] args)
    {
      Console.Write("Enter source path: ");
      string sourcePath = Console.ReadLine();
      Console.Write("Enter file mask (e.g. *.pdf): ");
      string fileMask = Console.ReadLine();
      Console.Write("Recursive (y/n): ");
      bool recursive = Console.ReadLine().ToUpper() == "Y";
      Console.Write("Enter target path: ");
      string targetPath = Console.ReadLine();
      Console.Write("Enter document name to extract (e.g. MLPA.PDF): ");
      string docName = Console.ReadLine();
      List<string> files = GetFiles(sourcePath, fileMask, recursive);
      foreach (string file in files)
      {
        GetPdfFromPortfolio(file, targetPath, docName);
      }
    }
    private static void GetPdfFromPortfolio(string filePath, string targetPath, string docName)
    {
      PdfReader reader = new PdfReader(filePath);
      PdfDictionary root = reader.Catalog;
      PdfDictionary documentnames = root.GetAsDict(PdfName.NAMES);
      PdfDictionary embeddedfiles =
          documentnames.GetAsDict(PdfName.EMBEDDEDFILES);
      PdfArray filespecs = embeddedfiles.GetAsArray(PdfName.NAMES);
      for (int i = 0; i < filespecs.Size;)
      {
        filespecs.GetAsString(i++);
        PdfDictionary filespec = filespecs.GetAsDict(i++);
        PdfDictionary refs = filespec.GetAsDict(PdfName.EF);
        foreach (PdfName key in refs.Keys)
        {
          PRStream stream = (PRStream)PdfReader.GetPdfObject(
            refs.GetAsIndirectObject(key)
          );

          if (filespec.GetAsString(key).ToString().ToUpper() == docName.ToUpper())
            using (FileStream fs = new FileStream(
              targetPath + @"\" + Path.GetFileName(filePath).Substring(0, 10) + filespec.GetAsString(key).ToString(), FileMode.OpenOrCreate
            ))
            {
              byte[] attachment = PdfReader.GetStreamBytes(stream);
              fs.Write(attachment, 0, attachment.Length);
            }
        }
      }

    }
    private static List<string> GetFiles(string path, string fileMask = "", bool recursive = false, List<string> files = null)
    {
      if (files == null) files = new List<string>();
      try
      {
        foreach (var file in Directory.GetFiles(path, fileMask))
        {
          files.Add(file);
        }
        if (recursive)
          foreach (string dir in Directory.GetDirectories(path))
          {
            GetFiles(dir, fileMask, recursive, files);
          }
      }
      catch (System.Exception e)
      {
        Console.WriteLine(e.ToString());
      }
      return files;
    }
  }
}

Tags:

C# | iTextSharp | PDF

Restart IIS Web Site from C# Code

by 24. April 2016 04:58

In some cases I have setup caching on the website for items such as menus, header, footer, etc.  However, when there is a CMS in place on the site and a user changes any of that relevant content there needs to be a way to reset the web cache.  One easy way is to force the IIS web site to restart by making a benign change in the web.config file, which will automatically force the restart.  Below is a sample version of code to do this, where I update an otherwise unused entry in the web.config that just indicates the last date/time of restart request by the user.  In the case of an MVC application I put this into a controller with some specific route provided to the CMS users so they can navigate to that route after making CMS changes that need to be updated in the cache.  As a side note, using this method will require granting write access to the web.config file for the IIS application pool user (by default "IIS AppPool\WebSiteName" user).

    public static void RestartWeb()
    {
      var configuration = WebConfigurationManager.OpenWebConfiguration("~");
      var section = (AppSettingsSection)configuration.GetSection("appSettings");
      section.Settings["LastRestart"].Value = 
        DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToLongTimeString();
      configuration.Save();
    }

Tags:

ASP.Net | C#

C# Generic Class Wrapper

by 23. January 2016 07:57

 

public class Wrapper<T>
{
    public Wrapper(T wrapped)
    {
        Wrapped = wrapped;
    }

    public T Wrapped { get; set; }
}

public class WrapperFactory
{
    public static Wrapper<T> Create<T>(T wrapped)
    {
        return new Wrapper<T>(wrapped);
    }
}

var wrappedInt = WrapperFactory.Create(42);

Tags:

C#

Piranha CMS for MVC Installation

by 22. February 2015 05:44

When I first installed Prianha CMS for MVC I was having issues running it.  I started over and installed via NuGet package manager console in the following order:

PM > Install-Package PiranhaCMS.Core

PM > Install-Package PiranhaCMS.WebPages

PM > Install-Package PiranhaCMS.MVC

PM > Install-Package PiranhaCMSMVC

 

Tags:

C# | MVC

Convert Standard MVC Website to SPA (Single Page Application) Using Sammy.js

by 19. February 2015 07:17

Step One: The Layout Page

For MVC the layout page is a template that ASP.NET uses to render a single HTML document by merging it with the markup in a view page.  In a SPA, the Layout becomes a shell page into which the view's markup is loaded via AJAX calls. The Layout page's lifespan is now the user's session, rather than just the lifespan of the page, so be careful what you scope at this level; the safety net of a page refresh that cleans up after us is gone, and browser memory leaks are distinctly counter-excellent in nature.

To convert a standard MVC website to SPA we'll use NuGet to add Sammy.js to our project. Sammy (among other things) is a jQuery-dependent JavaScript framework which lets us add URL routing to the client side of our app.

Once we've brought in Sammy, we'll add it to a bundle (along with jQuery) in BundleConfig.RegisterBundles:

bundles.Add(new ScriptBundle("~/js/mvc-spa").Include(
    "~/Scripts/jquery-{version}.js",
    "~/Scripts/sammy-{version}.js"));

Then we'll render the bundle at the bottom of our Layout page:

            @Scripts.Render("~/js/mvc-spa")
    </body>
</html>

We'll also need to designate the area of the Layout where the view content will be loaded by finding the element we are currently calling RenderBody and giving it a unique id. For this example, let's go with "page".

<!-- ... -->
</header>
<section id="page">
	@RenderBody()
</section>
<footer>
<!-- ... -->    

Step Two: Go Partial

Next, we need to go through our views, and, with the exception of the Home/Index view, convert each to a Partial View.

Unlike vanilla MVC Views, Partial Views are not merged with the Layout page to render as complete HTML documents. When you make a controller request that returns a Partial View, the response is merely an HTML fragment–precisely what we're looking for in a SPA page.

To convert a View to a Partial, simply change the View call to a call to PartialView in its corresponding Controller Action:

public class SpaFtwController : Controller {
    public ActionResult Index() {
        return PartialView();
    }
}

As I may have mentioned above, do not convert your default view to a partial. This view is the "single page" in "single-page application", and it still needs to render as a complete HTML document, just the once. However, we should move this Index view's content into a separate Partial View, and replace it with some sort of splash content that will only display while our app is still loading. More on that in the next step.

Step Three: One Route to rule them all

The typical usage of Sammy is to describe multiple hash-based routes, along with the js to be executed when the user navigates to them. What we're going to do in this case, though, is create a solitary Sammy route that acts as a pass-through to the existing MVC routing already in place on the server-side.

For example, a request to /#/spaftw would load the content from /SpaFTW into our app. Using fragment identifiers for routing is a classic SPA technique; it changes the browser's URL without causing a whole page request, while also allowing the back button to still work as expected, and enables deep-linking into the app.

Here is a module that contains the code to do just this. We'll add it to our project in a file named Routing.js.

var Routing = function (appRoot, contentSelector, defaultRoute) {
function getUrlFromHash(hash) { var url = hash.replace('#/', ''); if (url === appRoot) url = defaultRoute; return url; }
return { init: function () { Sammy(contentSelector, function () { this.get(/\#\/(.*)/, function (context) { var url = getUrlFromHash(context.path); context.load(url).swap(); }); }).run('#/'); } }; }

Let's unpack that. See the this.get call about two-thirds of the way down? That's Sammy's bread and butter. We're using a regular expression to describe a route URL that captures any href beginning with '/#'. When a request is made for a URL matching this expression, Sammy intercepts it and runs the function that we've passed as get's second parameter. This function grabs this path, strips out the hash, makes an AJAX request for the Partial View for that URL, and swaps it into the element designated by contentSelector. Which, of course, will be our content area in the Layout page.

Finally, we need to wire this into our Layout page. Add Routing.js to our bundle, after Sammy.js:

bundles.Add(new ScriptBundle("~/js/mvc-spa").Include(
        "~/Scripts/jquery-{version}.js",
        "~/Scripts/sammy-{version}.js",
        "~/Scripts/Routing.js"));

Then, add the following script block to the Layout page, after rendering the bundle:

@Scripts.Render("~/js/mvc-spa")
<script>
$(function () {
    var routing = new Routing('@Url.Content("~/")', '#page', 'welcome');
    routing.init();
});
</script>

This instantiates a Routing instance with the root URL for the application (this becomes important if our app is deployed anywhere other than '/'), the selector of our content area ('#page'), and the route to default to when the user navigates to the root of the app. This should be the Partial View that inherited the original content from our Home/Index view, in step two.

Original version of this modified post published here:

http://blog.apterainc.com/bid/313071/Turn-your-ASP-NET-MVC-app-into-a-Single-Page-Application-with-one-classy-Sammy-js-route

 

Tags:

C# | MVC

Issue with ASP.Net Identity from Default Local File System Database to SQL Server Based Database

by 22. December 2014 10:12

I created a new MVC 5 web application with the "Individual User Account" option that configures the ASP.Net Identity model.  By default this uses Entity Framework Code First model with a local file system database created in the local App_Data folder.  I tried moving this to an actual SQL Server database location by creating the five dbo.aspnet_... tables and changing the web.config to point to the new location.  However, in doing so I received the error below.  Turns out to solve this I just needed to change the connection string in the web.config from the Entity Framework style to the basic style (see old vs. new connection strings below).

 <connectionStrings>

    <addname="NewSimpleConnection"connectionString="Data Source=SERVER_NAME_HERE;initial catalog=DB_NAME_HERE;user id=USER_ID_HERE;password=PASSWORD_HERE;Integrated Security=False"providerName="System.Data.SqlClient" />

    <addname="OldEtityFConnection"connectionString="metadata=res://*/MyModel.csdl|res://*/MyModel.ssdl|res://*/MyModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=SERVER_NAME_HERE;initial catalog=DB_NAME_HERE;user id=USER_ID_HERE;password=PASSWORD_HERE;MultipleActiveResultSets=True;App=EntityFramework&quot;"providerName="System.Data.EntityClient" />

  </connectionStrings> 

Server Error in '/' Application.


 

Unable to load the specified metadata resource.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Data.Entity.Core.MetadataException: Unable to load the specified metadata resource.

Source Error:

 

Line 114:      {
Line 115:        var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };
Line 116:        IdentityResult result = await UserManager.CreateAsync(user, model.Password);
Line 117:        if (result.Succeeded)
Line 118:        {

Tags:

ASP.Net | C# | SQL Server

MVC and/or Web API Url Routes Resulting in Page Not Found (http 404 error)

by 16. May 2014 08:39

I was running an MVC/API site on my local development machine using Visual Studio 2013 and when I deployed the site to a development server all the URL routes resulted in page not found (404 error).  To resolve I added the following to the the configuration file.

<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" /> <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" /> <remove name="ExtensionlessUrlHandler-Integrated-4.0" /> <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*."
verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule"
scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll"
preCondition="classicMode,runtimeVersionv4.0,bitness32"
responseBufferLimit="0" /> <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*."
verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule"
scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll"
preCondition="classicMode,runtimeVersionv4.0,bitness64"
responseBufferLimit="0" /> <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*."
verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" /> </handlers>
</system.webServer>


Tags: ,

C#

C# Windows Form TreeView Drag/Drop Move and Copy Nodes, Move Nodes Up/Down and Expand on Hover

by 25. April 2014 08:13

The below code is sample of TreeView drag/drop events that supports the following:

  • Move a TreeNode by dragging and dropping with the left mouse button
  • Copy a TreeNode by dragging and dropping with the right mouse button
  • Move a TreeNode up one node by double-clicking it with the left mouse button
  • Move a TreeNode down one node by double-clicking it with the right mouse button
#region Treeview Drag/Drop Events

private void TestIt()
{
  this.MyTreeView.AllowDrop = true;
  // Add sample nodes
  TreeNode node;
  for (int x = 0; x < 5; ++x)
  {
    // Add the root node
    node = this.MyTreeView.Nodes.Add(String.Format("Node {0}", x * 4));
    for (int y = 1; y < 4; ++y)
    {
      // Add a child node to the previously added node.
      node = node.Nodes.Add(String.Format("Node{0}", x * 4 + y));
    }
  }
}
private void MyTreeView_ItemDrag(object sender, ItemDragEventArgs e)
{
  // Move the dragged node when the left mouse button is used. 
  if (e.Button == MouseButtons.Left)
  {
    DoDragDrop(e.Item, DragDropEffects.Move);
  }
  // Copy the dragged node when the right mouse button is used. 
  else if (e.Button == MouseButtons.Right)
  {
    DoDragDrop(e.Item, DragDropEffects.Copy);
  }
}

// Set the target drop effect to the effect  
// specified in the ItemDrag event handler. 
private void MyTreeView_DragEnter(object sender, DragEventArgs e)
{
  e.Effect = e.AllowedEffect;
}

// Select the node under the mouse pointer to indicate the  
// expected drop location. 

TreeNode lastDragDestination = null;
DateTime lastDragDestinationTime;
private void MyTreeView_DragOver(object sender, DragEventArgs e)
{
  // Retrieve the client coordinates of the mouse position.
  Point targetPoint = MyTreeView.PointToClient(new Point(e.X, e.Y));

  // Select the node at the mouse position.
  MyTreeView.SelectedNode = MyTreeView.GetNodeAt(targetPoint);

  TreeNode destinationNode = null;
  //get current location
  Point pt = new Point(e.X, e.Y);
  pt = MyTreeView.PointToClient(pt);
  destinationNode = MyTreeView.GetNodeAt(pt);
  if (destinationNode == null)
  {
    return;
  }

  //if we are on a new object, reset our timer
  //otherwise check to see if enough time has passed and expand the destination node
  if (destinationNode != lastDragDestination)
  {
    lastDragDestination = destinationNode;
    lastDragDestinationTime = DateTime.Now;
  }
  else
  {
    TimeSpan hoverTime = DateTime.Now.Subtract(lastDragDestinationTime);
    if (hoverTime.TotalMilliseconds > 500)
    {
      destinationNode.Expand();
    }
  }

}

private void MyTreeView_DragDrop(object sender, DragEventArgs e)
{
  // Retrieve the client coordinates of the drop location.
  Point targetPoint = MyTreeView.PointToClient(new Point(e.X, e.Y));

  // Retrieve the node at the drop location.
  TreeNode targetNode = MyTreeView.GetNodeAt(targetPoint);

  // Retrieve the node that was dragged.
  TreeNode draggedNode = (TreeNode)e.Data.GetData(typeof(TreeNode));

  // Confirm that the node at the drop location is not  
  // the dragged node or a descendant of the dragged node. 
  if (!draggedNode.Equals(targetNode) && !ContainsNode(draggedNode, targetNode))
  {
    // If it is a move operation, remove the node from its current  
    // location and add it to the node at the drop location. 
    if (e.Effect == DragDropEffects.Move)
    {
      draggedNode.Remove();
      targetNode.Nodes.Add(draggedNode);
    }

    // If it is a copy operation, clone the dragged node  
    // and add it to the node at the drop location. 
    else if (e.Effect == DragDropEffects.Copy)
    {
      targetNode.Nodes.Add((TreeNode)draggedNode.Clone());
    }

    // Expand the node at the location  
    // to show the dropped node.
    targetNode.Expand();
  }
}

// Determine whether one node is a parent  
// or ancestor of a second node. 
private bool ContainsNode(TreeNode node1, TreeNode node2)
{
  // Check the parent node of the second node. 
  if (node2.Parent == null) return false;
  if (node2.Parent.Equals(node1)) return true;

  // If the parent node is not null or equal to the first node,  
  // call the ContainsNode method recursively using the parent of  
  // the second node. 
  return ContainsNode(node1, node2.Parent);
}

private void MyTreeView_DoubleClick(object sender, EventArgs e)
{
  // Retrieve the client coordinates of the mouse position.
  Point targetPoint = new Point(((MouseEventArgs)e).X, ((MouseEventArgs)e).Y);

  // Select the node at the mouse position.
  this.MyTreeView.SelectedNode = this.MyTreeView.GetNodeAt(targetPoint);
  if (((MouseEventArgs)e).Button.Equals(MouseButtons.Right))
    Extensions.MoveNodeDown(this.MyTreeView.SelectedNode);
  else
    Extensions.MoveNodeUp(this.MyTreeView.SelectedNode);

}

#endregion

Tags:

C#

C# Auto-Rotate Image Based on Camera Rotation Exif Data

by 27. December 2013 08:14

This method uses ExifExtractor code referenced below from CodeProject.com.

public static Bitmap AutoRotateImage(Bitmap bmp)
{
  // Get source from: http://www.codeproject.com/KB/graphics/exifextractor.aspx?fid=207371
  var exif = new EXIFextractor(ref bmp, "n");
  switch (int.Parse(exif["Orientation"].ToString()))
  {
    case 1:
      bmp.RotateFlip(RotateFlipType.RotateNoneFlipNone);
      break;
    case 2:
      bmp.RotateFlip(RotateFlipType.RotateNoneFlipX);
      break;
    case 3:
      bmp.RotateFlip(RotateFlipType.Rotate180FlipNone);
      break;
    case 4:
      bmp.RotateFlip(RotateFlipType.Rotate180FlipX);
      break;
    case 5:
      bmp.RotateFlip(RotateFlipType.Rotate90FlipX);
      break;
    case 6:
      bmp.RotateFlip(RotateFlipType.Rotate90FlipNone);
      break;
    case 7:
      bmp.RotateFlip(RotateFlipType.Rotate270FlipX);
      break;
    case 8:
      bmp.RotateFlip(RotateFlipType.Rotate270FlipNone);
      break;
    default:
      bmp.RotateFlip(RotateFlipType.RotateNoneFlipNone);
      break;
  }
  return bmp;
}

 

Tags:

C#

C# App.Config Custom Dictionary Section to Store Simple Key/Value Pairs

by 4. November 2013 06:12

Below is a sample app.config using a custom dictionary section to store simple key/value pairs:

<configuration>
  <configSections>
    <section name="CustomDictionarySection" type="System.Configuration.DictionarySectionHandler"/>
  </configSections>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <CustomDictionarySection>
    <add key="Key1" value="Value 1" />
    <add key="Key2" value="Value 2" />
    <add key="Key3" value="Value 3" />
  </CustomDictionarySection>
</configuration>
class Program
{
  static void Main(string[] args)
  {
    string key = "Key2";
    var section = (ConfigurationManager.GetSection("CustomDictionarySection") as System.Collections.Hashtable)
                .Cast<System.Collections.DictionaryEntry>()
                .Where(t => t.Key.ToString() == key);
    if (section.Count() > 0)
      Console.WriteLine(string.Format("Found section with key: {0} containing value: {1}", key, section.First().Value));
    else
      Console.WriteLine(string.Format("Could not find section with key: {0}", key));
    Console.Read();
  }
}

Tags:

C#

C# Http Remote Page Post

by 30. August 2013 14:15
NameValueCollection Inputs = new NameValueCollection();
Inputs.Add("param1", "something");
Inputs.Add("param2", "somethingelse");
Http.RemotePost("http://google.com", Inputs);

using System.Collections.Specialized;
using System.Net;

public static class Http
{
  public static void RemotePost(string Url, NameValueCollection Inputs)
  {
    System.Web.HttpContext.Current.Response.Clear();
    System.Web.HttpContext.Current.Response.Write("<html><head>");
    System.Web.HttpContext.Current.Response.Write(string.Format("</head><body onload=\"document.{0}.submit()\">", "form1"));
    System.Web.HttpContext.Current.Response.Write(string.Format("<form name=\"{0}\" method=\"{1}\" action=\"{2}\" >", "form1", "post", Url));
    for (int i = 0; i < Inputs.Keys.Count; i++)
    {
      System.Web.HttpContext.Current.Response.Write(string.Format("<input name=\"{0}\" type=\"hidden\" value=\"{1}\">", Inputs.Keys[i], Inputs[Inputs.Keys[i]]));
    }
    System.Web.HttpContext.Current.Response.Write("</form>");
    System.Web.HttpContext.Current.Response.Write("</body></html>");
    System.Web.HttpContext.Current.Response.End();
  }
}

Tags:

C#

C# Windows Service to Log User Unlocking/Locking Computer

by 20. June 2013 08:09

Windows event logs will typically capture user login/logout activity; however, it does not capture user unlocking/locking their computer (which quite often is the more frequent activity).  This C# code will run as a Windows service and add Information entries into the Windows Application log accessible via the system Event Viewer.  Currently the code currently has an error in implementing "System.Security.Principal.WindowsIdentity.GetCurrent().Name" as an attempt to log the user name performing the activity; however, that is actually simply logging the user name that the Windows service is running as.  In a future update I plan to fix this issue and add the actual user name to the log entry.

 UserLockUnlockProfiler.zipx (41.86 kb)

Links regarding service interacting with user desktop:

https://stackoverflow.com/questions/5200341/capture-screen-on-server-desktop-session/12851218#12851218

https://stackoverflow.com/questions/5200341/capture-screen-on-server-desktop-session/12851218#12851218

Main Service Code:

using System;
using System.Diagnostics;
using System.Management;
using System.ServiceProcess;

namespace ULUPSvc
{
    public partial class ULUPSvc : ServiceBase
    {
        public ULUPSvc()
        {
            InitializeComponent();
            this.CanHandleSessionChangeEvent = true;
        }

        public void LogEvent(string msg)
        {
            msg += " " + DateTime.Now.ToString();
            ManagementScope ms = new ManagementScope("\\\\.\\root\\cimv2");
            ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_ComputerSystem");
            ManagementObjectSearcher searcher = new ManagementObjectSearcher(ms, query);
            foreach (ManagementObject mo in searcher.Get())
            {
                msg += " (" + mo["UserName"].ToString() + ")";
            }
            EventLog eventLog = new EventLog();
            eventLog.Log = "Application";
            eventLog.Source = "ULUPSvc";
            eventLog.WriteEntry(msg, EventLogEntryType.Information);
        }

        protected override void OnSessionChange(SessionChangeDescription changeDescription)
        {
            switch (changeDescription.Reason)
            {
                case SessionChangeReason.SessionLogon:
                    LogEvent("Logon");
                    break;
                case SessionChangeReason.SessionLogoff:
                    LogEvent("Logoff");
                    break;
                case SessionChangeReason.SessionLock:
                    LogEvent("Lock");
                    break;
                case SessionChangeReason.SessionUnlock:
                    LogEvent("Unlock");
                    break;
            }
            base.OnSessionChange(changeDescription);
        }

        protected override void OnStart(string[] args)
        {
            // Make sure we have our application in the event log.
            if (!EventLog.SourceExists("ULUPSvc"))
                EventLog.CreateEventSource("ULUPSvc", "Application");
        }

        protected override void OnStop()
        {
            LogEvent("Stopping");
        }

    }

}

Tags:

C#

C# Get First and Last Day of Previous Month

by 3. December 2012 08:25

To get the first day of previous month:

var firstDayPrevMonth = new DateTime(DateTime.Today.Year
  , DateTime.Today.Month, 1).AddMonths(-1);

To get the last day of previous month:

var lastDayPrevMonth = new DateTime(DateTime.Today.Year
  , DateTime.Today.Month, 1).AddDays(-1);

 

Tags:

C#

ASP.Net C# Export GridView Control Data to Excel File

by 22. October 2012 08:44

This is a simple method to export data directly from an ASP.Net GridView control into an Excel file (CSV formatted).

protected void ExportGridViewDataButton_Click(object sender, EventArgs e)
{
  StringBuilder sb = new StringBuilder();
  foreach (TableCell cel in this.GridViewControl.HeaderRow.Cells)
  {
    sb.Append("\"").Append(cel.Text.Replace(" ", "")).Append("\",");
  }
  sb.Append(((Char)10).ToString());
  foreach (GridViewRow row in this.GridViewControl.Rows)
  {
    foreach (TableCell cel in row.Cells)
    {
      sb.Append("\"").Append(cel.Text.Replace(" ", "")).Append("\",");
    }
    sb.Append(((Char)10).ToString());
  }
  Response.Clear();
  Response.AddHeader("Content-Disposition"
    , "attachment;filename=GridViewExport.csv");
  Response.ContentType = "text/csv";
  Response.Write(sb.ToString());
  Response.Flush();
  Response.End();
}

Tags:

C# | Excel

Combine Binary Files Using C#

by 19. October 2012 09:07
using (var fs = File.OpenWrite("combined.bin"))
{
  var buffer = File.ReadAllBytes("file1.bin");
  fs.Write(buffer, 0, buffer.Length);
  buffer = File.ReadAllBytes("file2.bin");
  fs.Write(buffer, 0, buffer.Length);
  fs.Flush();
}

Tags:

C#

Sys Undefined Exception in ASP.Net Web Form Menu Control Generated JS with URL Routing

by 16. October 2012 08:07

Although the exception only seems to occur when using URL routing it is not consistent (i.e. doesn't always happen).

The page generates this line at the end of the Form tag:

new Sys.WebForms.Menu({ element: 'Navigation Menu', disappearAfter: 500, orientation: 'horizontal', tabIndex: 0, disabled: false });

Throws JS runtime exception:

'Sys' is undefined

Solution:

void Application_Start(object sender, EventArgs e)
{
  RouteTable.Routes.Ignore("{resource}.axd");
}

Or:

  
<system.web>
  <pages controlRenderingCompatibilityVersion="3.5"/>
</system.web>

Tags:

ASP.Net | C# | JavaScript

WCF Web Service XML Sample

by 24. September 2012 11:29
This is some sample code demonstrating a WCF web service with XML based class as an input parameter.
// Shared class...

public class MySampleData
{
  public string UserId { get; set; }
  public Guid RecordId { get; set; }
  public string RecordDesc { get; set; }
  public decimal DataAmount { get; set; }
  public DateTime EffectiveDate { get; set; }
}

// Sample usage...

using System.IO;
using System.Net;
using System.Xml;
using System.Xml.Serialization;

private void SampleUsage()
{
  MySampleData data = new MySampleData()
  {
    UserId = "myuser",
    RecordId = Guid.NewGuid(),
    RecordDesc = "This is a test",
    DataAmount = 100.99,
    EffectiveDate = System.DateTime.Now.AddDays(5)
  };
  string msg = SaveMySampleData(data);
  System.Diagnostics.Debug.WriteLine(msg);
}

// Caller initiating web service transaction...
private void SaveMySampleData(MySampleData data)
{
  XmlSerializer serializer = new XmlSerializer(data.GetType());
  MemoryStream ms = new MemoryStream();
  serializer.Serialize(ms, data);
  StreamReader rdr = new StreamReader(ms);
  ms.Position = 0;
  HttpWebRequest req = (HttpWebRequest)HttpWebRequest
    .Create("http://localhost:43653/MySampleService.svc/SaveMySampleData");
  req.Method = "POST";
  req.ContentType = "application/xml; charset=utf-8";
  byte[] reqBodyBytes = ms.ToArray();
  Stream reqStream = req.GetRequestStream();
  reqStream.Write(reqBodyBytes, 0, reqBodyBytes.Length);
  reqStream.Close();
  HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
  XmlDocument xml = new XmlDocument();
  xml.LoadXml(new StreamReader(resp.GetResponseStream()).ReadToEnd());
  resp.Close();
}

// Web service code (i.e. MySampleService.svc file)

using System;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

[ServiceContract]
public class MySampleService
{
  [OperationContract(Name = "SaveMySampleData")]
  [WebInvoke(Method = "POST", UriTemplate = "SaveMySampleData",
              RequestFormat = WebMessageFormat.Xml,
              ResponseFormat = WebMessageFormat.Xml,
              BodyStyle = WebMessageBodyStyle.Bare)]
  public string SaveMySampleData(XmlElement input)
  {
    XmlSerializer serializer = new XmlSerializer(typeof(MySampleData));
    MySampleData data = (MySampleData)serializer.Deserialize
      (new MemoryStream(System.Text.Encoding.ASCII.GetBytes(input.OuterXml)));
    // Save to db here... just echoing data back for the sample...
    StringBuilder msg = new StringBuilder();
    msg.Append("You sent the following data.").Append(Environment.NewLine);
    msg.Append("UserId: ").Append(data.UserId).Append(Environment.NewLine);
    msg.Append("RecordId: ").Append(data.RecordId).Append(Environment.NewLine);
    msg.Append("RecordDesc: ").Append(data.RecordDesc).Append(Environment.NewLine);
    msg.Append("DataAmount: ").Append(data.DataAmount).Append(Environment.NewLine);
    msg.Append("EffectiveDate: ").Append(data.EffectiveDate.ToString()).Append(Environment.NewLine);
    return msg.ToString();
  }
}

Tags:

C# | Web Service | Windows Communication Foundation

C# LDAP Query - Get User Properties by User Name

by 5. April 2012 08:44

This code allows you to search for an Active Directory user by name and return a dynamic list of properties with optional line feed.  NOTE: There is a hardcoded userid and password that needs to be changed to a valid AD user login.

using System;
using System.DirectoryServices;
using System.Text;
using System.Text.RegularExpressions;

namespace LDAP_Query
{
  class Program
  {
    static void Main(string[] args)
    {
      Console.Write(GetLDAPUserByName("Joseph Pesch"
        , new string[] { "department", "title", "givenName", "displayName" }
        , ((char)10).ToString()));
    }

    private static string GetLDAPUserByName(string userName, string[] properties, string lineFeed)
    {
      StringBuilder sb = new StringBuilder();
      userName = Regex.Replace(userName, @"[\(\)\*\\]", (match) =>
      {
        // escape reserved chars 
        return "\\" + ((int)match.Value[0]).ToString("x");
      }, RegexOptions.Compiled);
      string query = "(&"
        + "(objectCategory=person)" + "(objectClass=user)"
        + "(|" + "(&" + "(sn={0}*)" + "(givenName={1}*)" + ")"
        + "(displayName={2})" + ")" + ")";
      query = String.Format(query, userName.Split(' ')[1]
        , userName.Split(' ')[0], userName);
      using (DirectoryEntry entry =
        new DirectoryEntry("LDAP://" + Environment.UserDomainName
        , "userid", "password", AuthenticationTypes.Secure))
      {
        using (DirectorySearcher ds =
          new DirectorySearcher(entry, query, null, SearchScope.Subtree))
        {
          SearchResultCollection res = ds.FindAll(); // all matches 
          if (res == null) return "CANNOT LOCATE USER";
          foreach (SearchResult r in res)
          {
            foreach (string prop in properties)
            {
              foreach (object property in r.Properties[prop])
              {
                sb.Append(prop).Append("=").Append(property.ToString()).Append(lineFeed);
              }
            }
          }
        }
      }
      return sb.ToString();
    }

  }

}

Tags:

C#