0

Hi,

I'm devloping a c# application that shows all the usb storage devices' names and dates of past 30 days. I'm done searching the google and hadn't found a clue. Please help me out.

Edited by aung.kyaw.1428

2
Contributors
1
Reply
25
Views
4 Years
Discussion Span
Last Post by deceptikon
2

My first approach would be to monitor the last write time for the USBSTOR registry key in a windows service and persist those results in a separate database or file. Really the most difficult part of that would be working around the complete lack of support for time stamps in registry keys. So you'd have to drop down to the Win32 API for that information.

For example:

using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;

class Program
{
    static void Main(string[] args)
    {
        string usbStor = @"SYSTEM\ControlSet001\Enum\USBSTOR";

        using (var keyUsbStor = Registry.LocalMachine.OpenSubKey(usbStor))
        {
            var usbDevices = from className in keyUsbStor.GetSubKeyNames()
                             let keyUsbClass = keyUsbStor.OpenSubKey(className)
                             from instanceName in keyUsbClass.GetSubKeyNames()
                             let keyUsbInstance = new RegistryKeyEx(keyUsbClass.OpenSubKey(instanceName))
                             select new
                             {
                                 UsbName = keyUsbInstance.Key.GetValue("FriendlyName"),
                                 ConnectTime = keyUsbInstance.LastWriteTime
                             };

            foreach (var usbDevice in usbDevices.OrderBy(x => x.ConnectTime))
            {
                Console.WriteLine("({0}) -- '{1}'", usbDevice.ConnectTime, usbDevice.UsbName);
            }
        }
    }
}

/// <summary>
/// Wraps a RegistryKey object and corresponding last write time.
/// </summary>
/// <remarks>
/// .NET doesn't expose the last write time for a registry key 
/// in the RegistryKey class, so P/Invoke is required.
/// </remarks>
public class RegistryKeyEx
{
    #region P/Invoke Declarations
    // This declaration is intended to be used for the last write time only. int is used
    // instead of more convenient types so that dummy values of 0 reduce verbosity.
    [DllImport("advapi32.dll", EntryPoint = "RegQueryInfoKey", CallingConvention = CallingConvention.Winapi, SetLastError = true)]
    extern private static int RegQueryInfoKey(
        SafeRegistryHandle hkey,
        int lpClass,
        int lpcbClass,
        int lpReserved,
        int lpcSubKeys,
        int lpcbMaxSubKeyLen,
        int lpcbMaxClassLen,
        int lpcValues,
        int lpcbMaxValueNameLen,
        int lpcbMaxValueLen,
        int lpcbSecurityDescriptor,
        IntPtr lpftLastWriteTime);
    #endregion

    #region Public Poperties
    /// <summary>
    /// Gets the registry key owned by the info object.
    /// </summary>
    public RegistryKey Key { get; private set; }

    /// <summary>
    /// Gets the last write time for the corresponding registry key.
    /// </summary>
    public DateTime LastWriteTime { get; private set; }
    #endregion

    /// <summary>
    /// Creates and initializes a new RegistryKeyInfo object from the provided RegistryKey object.
    /// </summary>
    /// <param name="key">RegistryKey component providing a handle to the key.</param>
    public RegistryKeyEx(RegistryKey key)
    {
        Key = key;
        SetLastWriteTime();
    }

    /// <summary>
    /// Creates and initializes a new RegistryKeyInfo object from a registry key path string.
    /// </summary>
    /// <param name="parent">Parent key for the key being loaded.</param>
    /// <param name="keyName">Path to the registry key.</param>
    public RegistryKeyEx(RegistryKey parent, string keyName)
        : this(parent.OpenSubKey(keyName))
    { }

    /// <summary>
    /// Queries the currently set registry key through P/Invoke for the last write time.
    /// </summary>
    private void SetLastWriteTime()
    {
        Debug.Assert(Key != null, "RegistryKey component must be initialized");

        GCHandle pin = new GCHandle();
        long lastWriteTime = 0;

        try
        {
            pin = GCHandle.Alloc(lastWriteTime, GCHandleType.Pinned);

            if (RegQueryInfoKey(Key.Handle, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pin.AddrOfPinnedObject()) == 0)
            {
                LastWriteTime = DateTime.FromFileTime((long)pin.Target);
            }
            else
            {
                LastWriteTime = DateTime.MinValue;
            }
        }
        finally
        {
            if (pin.IsAllocated)
            {
                pin.Free();
            }
        }
    }
}
Votes + Comments
Phew man, you know some things!
This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.