Ciao
Mi sono recentemente imbarcato nel "mondo delle API non documentate" scoprendo che, anche se mamma microsoft sembra non volerlo far sapere in giro, è possibile fare quello che chiedevi anche senza un kernel driver.
Ti rimando qui per una descrizione completa:
http://procoder.forumfree.net/?t=38978927
In fondo all'articolo trovi un link da cui scaricare una dll che dovrai copiare nella cartella di esecuzione della tua applicazione (oppure nella cartella di windows); quindi il codice per usarla da VB.Net o C# è questo:
'VB.Net
Imports System.Runtime.InteropServices
Public Class TuaForm
<StructLayout(LayoutKind.Sequential)> _
Structure FileInformation
'ID del processo che tiene aperto il file
Public ProcessID As Integer
'Handle del file aperto dal processo
'(è riferito al contesto del processo, non puoi fare praticamente niente con questo)
Public FileHandle As IntPtr
End Structure
'Importa la funzione dalla dll. Inserisci il percorso completo corretto della dll,
'oppure assicurati che la dll si trovi nella cartella dell'eseguibile
<DllImport("WhoLocked.dll")> _
Shared Function GetPidLockingFile( _
<MarshalAs(UnmanagedType.LPWStr)> ByVal filePath As String, _
<[In](), Out()> ByVal outInfo As FileInformation(), _
ByVal maxCount As Integer) As Integer
End Function
Private Sub TuoButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles TuoButton.Click
'Richiede il file da monitorare
Dim OFD As New OpenFileDialog()
If (OFD.ShowDialog() <> Windows.Forms.DialogResult.OK) Then Return
TuaRichTextBox.Clear()
'Alloca l'array che conterrà gli ID dei processi che tengono aperto il file
Dim fileInfo(50) As FileInformation
'Ottiene le informazioni dalla funzione nella Dll, e il numero di processi trovati
Dim count As Integer = GetPidLockingFile(OFD.FileName, fileInfo, 50)
'Cicla su tutti i processi mostrando l'output in una RichTextBox
For i As Integer = 0 To count - 1
'Scrive le informazioni sulla richtextbox
TuaRichTextBox.AppendText(String.Format("Process ID: {0}" & vbCrLf & _
"Handle: 0x{1:X}" & vbCrLf & vbCrLf, _
fileInfo(i).ProcessID, CInt(fileInfo(i).FileHandle)))
Next
End Sub
End Class
//C#
public partial class TuaForm : Form
{
public TuaForm()
{
InitializeComponent();
}
[StructLayout(LayoutKind.Sequential)]
struct FileInformation
{
//PID del processo che tiene aperto il file
public int pid;
//Handle del file aperto dal processo (nell'ambito del processo)
public IntPtr procHandle;
}
[DllImport(@"WhoLocked.dll")]
static extern int GetPidLockingFile(
[MarshalAs(UnmanagedType.LPWStr)]String filePath,
[In, Out]FileInformation[] outInfo,
int maxCount);
private void tuoButton_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() != DialogResult.OK)
return;
tuaTextBox.Clear();
//Crea una lista per contenere i valori di ritorno
FileInformation[] res = new FileInformation[20];
int count = GetPidLockingFile(ofd.FileName, res, 20);
//Cicla fra tutti i risultati
for (int i = 0; i < count; i++)
{
tuaTextBox.AppendText(String.Format("Process ID: {0}\r\nHandle: 0x{1:X}\r\n\r\n",
res[i].pid, (int)res[i].procHandle));
}
}
}
Mi rendo conto che il thread è abbastanza datato, ma potrà essere d'aiuto in futuro anche ad altra gente 
Luca