Tuesday, December 18, 2012

Help! My Access Database Is Locked!

When a Microsoft Access database is opened, the database engine (known as the JET engine) creates a lock file aka the LDB file.  These LDB files are a known format and contain information about who has opened the database.  This can be useful in certain situations.

Let's say that you use ArcGIS, which can use Access databases for the backend.  You opened the database using ArcGIS and you want to make some changes to the schema.  But ArcGIS won't let you because the schema is locked.  Help!  What can you do?  Enter the LDB File Viewer program.  Simply open the program, drag a LDB file onto the programs window, and it will tell you which computer has the database locked.

Get it!

For completeness sake, the source code is in C# and is as follows:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace AccessLockFileViewer
{
  public partial class AccessLockFileViewer : Form
  {
    public AccessLockFileViewer(string[] files)
    {
      InitializeComponent();
      if (files != null && files.Length > 0)
      {
        this.textBox1.Text = ParseFile(files[0]);
      }
    }

    private void Form1_DragDrop(object sender, DragEventArgs e)
    {
      if (e.Data.GetDataPresent(DataFormats.FileDrop))
      {
        string[] files = (string[])(e.Data.GetData(DataFormats.FileDrop));
        foreach (var file in files)
        {
          string text = ParseFile(file);
          this.textBox1.Text += text;
        }
      }
    }

    string ParseFile(string file)
    {
      /*
       *  For each person who opens a shared database, the Jet database engine writes an
       *  entry in the .ldb file of the database. The size of each .ldb entry is 64 bytes.
       *  The first 32 bytes contain the computer name (such as JohnDoe). The second
       *  32 bytes contain the security name (such as Admin). The maximum number of
       *  concurrent users that the Jet database engine supports is 255. Therefore, the
       *  .ldb file size is never larger than 16 kilobytes.
       */
      using (var stream = new FileStream(file, FileMode.Open))
      {
        BinaryReader reader = new BinaryReader(stream);
        string text = "";
        for (int i = 0; i < reader.BaseStream.Length; i += 64)
        {
          byte[] bin = reader.ReadBytes(32);
          StringBuilder sb = new StringBuilder();
          for (int b = 0; b < 32; b++)
          {
            if (bin[b] == 0)
            {
              break;
            }
            sb.Append((char)bin[b]);
          }
          string user = sb.ToString();


          bin = reader.ReadBytes(32);
          sb = new StringBuilder();
          for (int b = 0; b < 32; b++)
          {
            if (bin[b] == 0)
            {
              break;
            }
            sb.Append((char)bin[b]);
          }
          text += sb.ToString() + "@" + user + "\r\n";
        }
        stream.Close();

        return text;
      }
    }

    private void Form1_DragEnter(object sender, DragEventArgs e)
    {
      if (e.Data.GetDataPresent(DataFormats.FileDrop))
      {
        e.Effect = DragDropEffects.Copy;
      }
      else
      {
        e.Effect = DragDropEffects.None;
      }
    }

    #region Windows Forms Code

    /// 
    /// Required designer variable.
    /// 
    private System.ComponentModel.IContainer components = null;

    /// 
    /// Clean up any resources being used.
    /// 
    /// true if managed resources should be disposed; otherwise, false.
    protected override void Dispose(bool disposing)
    {
      if (disposing && (components != null))
      {
        components.Dispose();
      }
      base.Dispose(disposing);
    }

    #region Windows Form Designer generated code

    /// 
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// 
    private void InitializeComponent()
    {
      this.textBox1 = new System.Windows.Forms.TextBox();
      this.SuspendLayout();
      // 
      // textBox1
      // 
      this.textBox1.Location = new System.Drawing.Point(13, 13);
      this.textBox1.Multiline = true;
      this.textBox1.Name = "textBox1";
      this.textBox1.ReadOnly = true;
      this.textBox1.Size = new System.Drawing.Size(290, 202);
      this.textBox1.TabIndex = 0;
      // 
      // AccessLockFileViewer
      // 
      this.AllowDrop = true;
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
      this.ClientSize = new System.Drawing.Size(317, 230);
      this.Controls.Add(this.textBox1);
      this.Name = "AccessLockFileViewer";
      this.Text = "LDB File Viewer";
      this.DragDrop += new System.Windows.Forms.DragEventHandler(this.Form1_DragDrop);
      this.DragEnter += new System.Windows.Forms.DragEventHandler(this.Form1_DragEnter);
      this.ResumeLayout(false);
      this.PerformLayout();

    }

    #endregion

    private System.Windows.Forms.TextBox textBox1;

    #endregion

  }

  static class Program
  {
    /// 
    /// The main entry point for the application.
    /// 
    [STAThread]
    static void Main(string[] args)
    {
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
      Application.Run(new AccessLockFileViewer(args));
    }
  }
}

No comments:

Post a Comment