Who has it?

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Anyone know how I can find out if any process has a handle on a specific file?
 
No, I don't want an already made utility. I would like to know how to do this
in c#.

Thanks
 
Hello Demetri,

See info there
http://www.codeguru.com/Cpp/W-P/system/processesmodules/article.php/c2827
and there http://vbnet.mvps.org/index.html?code/network/netfileenum.htm

The WinAPI code for this is:

void WhoUsesFile( LPCTSTR lpFileName, BOOL bFullPathCheck )
{
BOOL bShow = FALSE;
CString name;
CString processName;
CString deviceFileName;
CString fsFilePath;
SystemProcessInformation::SYSTEM_PROCESS_INFORMATION* p;
SystemProcessInformation pi;
SystemHandleInformation hi;

if ( bFullPathCheck )
{
if ( !SystemInfoUtils::GetDeviceFileName( lpFileName, deviceFileName ) )
{
_tprintf( _T("GetDeviceFileName() failed.\n") );
return;
}
}

hi.SetFilter( _T("File"), TRUE );

if ( hi.m_HandleInfos.GetHeadPosition() == NULL )
{
_tprintf( _T("No handle information\n") );
return;
}

pi.Refresh();

_tprintf( _T("%-6s %-20s %s\n"), _T("PID"), _T("Name"), _T("Path") );
_tprintf( _T("------------------------------------------------------\n") );

for ( POSITION pos = hi.m_HandleInfos.GetHeadPosition(); pos != NULL; )
{
SystemHandleInformation::SYSTEM_HANDLE& h = hi.m_HandleInfos.GetNext(pos);

if ( pi.m_ProcessInfos.Lookup( h.ProcessID, p ) )
{
SystemInfoUtils::Unicode2CString( &p->usName, processName );
}
else
processName = "";

//NT4 Stupid thing if it is the services.exe and I call GetName :((
if ( INtDll::dwNTMajorVersion == 4 && _tcsicmp( processName, _T("services.exe"
) ) == 0 )
continue;

hi.GetName( (HANDLE)h.HandleNumber, name, h.ProcessID );

if ( bFullPathCheck )
bShow = _tcsicmp( name, deviceFileName ) == 0;
else
bShow = _tcsicmp( GetFileNamePosition(name), lpFileName ) == 0;

if ( bShow )
{
if ( !bFullPathCheck )
{
fsFilePath = "";
SystemInfoUtils::GetFsFileName( name, fsFilePath );
}

_tprintf( _T("0x%04X %-20s %s\n"),
h.ProcessID,
processName,
!bFullPathCheck ? fsFilePath : lpFileName );
}
}
}


D> No, I don't want an already made utility. I would like to know how to
D> do this in c#.
D>
D> Thanks
D>
D> "Petar Repac" wrote:
D>---
WBR,
Michael Nemtsev :: blog: http://spaces.live.com/laflour

"At times one remains faithful to a cause only because its opponents do not
cease to be insipid." (c) Friedrich Nietzsch
 
Beware that this code uses undocumented exports from ntdll.dll, and requires
that the caller is a member of the "debug users" group!
Which means that this is not something you would ever use in production
code.

Willy.


| Hello Demetri,
|
| See info there
| http://www.codeguru.com/Cpp/W-P/system/processesmodules/article.php/c2827
| and there http://vbnet.mvps.org/index.html?code/network/netfileenum.htm
|
| The WinAPI code for this is:
|
| void WhoUsesFile( LPCTSTR lpFileName, BOOL bFullPathCheck )
| {
| BOOL bShow = FALSE;
| CString name;
| CString processName;
| CString deviceFileName;
| CString fsFilePath;
| SystemProcessInformation::SYSTEM_PROCESS_INFORMATION* p;
| SystemProcessInformation pi;
| SystemHandleInformation hi;
|
| if ( bFullPathCheck )
| {
| if ( !SystemInfoUtils::GetDeviceFileName( lpFileName, deviceFileName ) )
| {
| _tprintf( _T("GetDeviceFileName() failed.\n") );
| return;
| }
| }
|
| hi.SetFilter( _T("File"), TRUE );
|
| if ( hi.m_HandleInfos.GetHeadPosition() == NULL )
| {
| _tprintf( _T("No handle information\n") );
| return;
| }
|
| pi.Refresh();
|
| _tprintf( _T("%-6s %-20s %s\n"), _T("PID"), _T("Name"), _T("Path") );
| _tprintf(
_T("------------------------------------------------------\n") );
|
| for ( POSITION pos = hi.m_HandleInfos.GetHeadPosition(); pos != NULL; )
| {
| SystemHandleInformation::SYSTEM_HANDLE& h = hi.m_HandleInfos.GetNext(pos);
|
| if ( pi.m_ProcessInfos.Lookup( h.ProcessID, p ) )
| {
| SystemInfoUtils::Unicode2CString( &p->usName, processName );
| }
| else
| processName = "";
|
| //NT4 Stupid thing if it is the services.exe and I call GetName :((
| if ( INtDll::dwNTMajorVersion == 4 && _tcsicmp( processName,
_T("services.exe"
| ) ) == 0 )
| continue;
|
| hi.GetName( (HANDLE)h.HandleNumber, name, h.ProcessID );
|
| if ( bFullPathCheck )
| bShow = _tcsicmp( name, deviceFileName ) == 0;
| else
| bShow = _tcsicmp( GetFileNamePosition(name), lpFileName ) == 0;
|
| if ( bShow )
| {
| if ( !bFullPathCheck )
| {
| fsFilePath = "";
| SystemInfoUtils::GetFsFileName( name, fsFilePath );
| }
|
| _tprintf( _T("0x%04X %-20s %s\n"),
| h.ProcessID,
| processName,
| !bFullPathCheck ? fsFilePath : lpFileName );
| }
| }
| }
|
|
| D> No, I don't want an already made utility. I would like to know how to
| D> do this in c#.
| D>
| D> Thanks
| D>
| D> "Petar Repac" wrote:
| D>
| >> Demetri wrote:
| >>
| >>> Anyone know how I can find out if any process has a handle on a
| >>> specific file?
| >>>
| >> Take a look at http://www.sysinternals.com/FileAndDiskUtilities.html
| >> maybe you will find what you need there.
| >>
| >> Regards,
| >> Petar
| ---
| WBR,
| Michael Nemtsev :: blog: http://spaces.live.com/laflour
|
| "At times one remains faithful to a cause only because its opponents do
not
| cease to be insipid." (c) Friedrich Nietzsche
|
|
 
You know, it amazes me how something that seems like a fundamental thing for
an OS is so hard to come by (code wise). Of course I only want production
worthy code. Why is the code to do such a thing so remote and almost
un-findable (if that is a word).
 
Hello Willy Denoyette [MVP],

i wonder if there are any better solutions?

W> Beware that this code uses undocumented exports from ntdll.dll, and
W> requires
W> that the caller is a member of the "debug users" group!
W> Which means that this is not something you would ever use in
W> production
W> code.
W> Willy.
W>
W> W> | Hello Demetri,
W> |
W> | See info there
W> |
W> http://www.codeguru.com/Cpp/W-P/system/processesmodules/article.php/c
W> 2827
W> | and there
W> http://vbnet.mvps.org/index.html?code/network/netfileenum.htm
W> |
W> | The WinAPI code for this is:
W> |
W> | void WhoUsesFile( LPCTSTR lpFileName, BOOL bFullPathCheck )
W> | {
W> | BOOL bShow = FALSE;
W> | CString name;
W> | CString processName;
W> | CString deviceFileName;
W> | CString fsFilePath;
W> | SystemProcessInformation::SYSTEM_PROCESS_INFORMATION* p;
W> | SystemProcessInformation pi;
W> | SystemHandleInformation hi;
W> |
W> | if ( bFullPathCheck )
W> | {
W> | if ( !SystemInfoUtils::GetDeviceFileName( lpFileName,
W> deviceFileName ) )
W> | {
W> | _tprintf( _T("GetDeviceFileName() failed.\n") );
W> | return;
W> | }
W> | }
W> |
W> | hi.SetFilter( _T("File"), TRUE );
W> |
W> | if ( hi.m_HandleInfos.GetHeadPosition() == NULL )
W> | {
W> | _tprintf( _T("No handle information\n") );
W> | return;
W> | }
W> |
W> | pi.Refresh();
W> |
W> | _tprintf( _T("%-6s %-20s %s\n"), _T("PID"), _T("Name"),
W> _T("Path") );
W> | _tprintf(
W> _T("------------------------------------------------------\n") );
W> |
W> | for ( POSITION pos = hi.m_HandleInfos.GetHeadPosition(); pos !=
W> NULL; )
W> | {
W> | SystemHandleInformation::SYSTEM_HANDLE& h =
W> hi.m_HandleInfos.GetNext(pos);
W> |
W> | if ( pi.m_ProcessInfos.Lookup( h.ProcessID, p ) )
W> | {
W> | SystemInfoUtils::Unicode2CString( &p->usName, processName );
W> | }
W> | else
W> | processName = "";
W> |
W> | //NT4 Stupid thing if it is the services.exe and I call GetName :((
W> | if ( INtDll::dwNTMajorVersion == 4 && _tcsicmp( processName,
W> _T("services.exe"
W> | ) ) == 0 )
W> | continue;
W> |
W> | hi.GetName( (HANDLE)h.HandleNumber, name, h.ProcessID );
W> |
W> | if ( bFullPathCheck )
W> | bShow = _tcsicmp( name, deviceFileName ) == 0;
W> | else
W> | bShow = _tcsicmp( GetFileNamePosition(name), lpFileName ) == 0;
W> |
W> | if ( bShow )
W> | {
W> | if ( !bFullPathCheck )
W> | {
W> | fsFilePath = "";
W> | SystemInfoUtils::GetFsFileName( name, fsFilePath );
W> | }
W> |
W> | _tprintf( _T("0x%04X %-20s %s\n"),
W> | h.ProcessID,
W> | processName,
W> | !bFullPathCheck ? fsFilePath : lpFileName );
W> | }
W> | }
W> | }
W> |
W> |
W> | D> No, I don't want an already made utility. I would like to know
W> how to
W> | D> do this in c#.
W> | D>
W> | D> Thanks
W> | D>
W> | D> "Petar Repac" wrote:
W> | D>
W> | >> Demetri wrote:
W> | >>
W> | >>> Anyone know how I can find out if any process has a handle on a
W> | >>> specific file?
W> | >>>
W> | >> Take a look at
W> http://www.sysinternals.com/FileAndDiskUtilities.html
W> | >> maybe you will find what you need there.
W> | >>
W> | >> Regards,
W> | >> Petar
W> | ---
W> | WBR,
W> | Michael Nemtsev :: blog: http://spaces.live.com/laflour
W> |
W> | "At times one remains faithful to a cause only because its
W> opponents do
W> not
W> | cease to be insipid." (c) Friedrich Nietzsche
W> |
W> |
---
WBR,
Michael Nemtsev :: blog: http://spaces.live.com/laflour

"At times one remains faithful to a cause only because its opponents do not
cease to be insipid." (c) Friedrich Nietzsch
 
No, while there are other way's to handle this, none can make use of
documented features.
But, when talking about "solutions", you first need to define the problem.
What exactly are you trying to solve here?.
Why do people want know about "who" has an open handle to a file, for other
reasons than debugging?
Say a program owns the handle to a file called a.txt, while a 2nd program
tries to open the same a.txt file. When the open fails due to a sharing
violation, you know that the file has been opened by another process, right?
Now there are three reasons for the sharing violation:
1. App1 isn't designed for sharing, whatever the sharing mode.
2. App1 is designed to share the file, but app2 isn't designed to share.
3. None of the applications are designed to share the file.

Which one of the above can be solved by knowing who has the file open, and
how are you going to solve it?
The only solution is to "correctly handle" the sharing, if this is not
possible for whatever reason, then you can't run the applications
simultaneously.


Willy.

| Hello Willy Denoyette [MVP],
|
| i wonder if there are any better solutions?
|
| W> Beware that this code uses undocumented exports from ntdll.dll, and
| W> requires
| W> that the caller is a member of the "debug users" group!
| W> Which means that this is not something you would ever use in
| W> production
| W> code.
| W> Willy.
| W>
| W> | W> | Hello Demetri,
| W> |
| W> | See info there
| W> |
| W> http://www.codeguru.com/Cpp/W-P/system/processesmodules/article.php/c
| W> 2827
| W> | and there
| W> http://vbnet.mvps.org/index.html?code/network/netfileenum.htm
| W> |
| W> | The WinAPI code for this is:
| W> |
| W> | void WhoUsesFile( LPCTSTR lpFileName, BOOL bFullPathCheck )
| W> | {
| W> | BOOL bShow = FALSE;
| W> | CString name;
| W> | CString processName;
| W> | CString deviceFileName;
| W> | CString fsFilePath;
| W> | SystemProcessInformation::SYSTEM_PROCESS_INFORMATION* p;
| W> | SystemProcessInformation pi;
| W> | SystemHandleInformation hi;
| W> |
| W> | if ( bFullPathCheck )
| W> | {
| W> | if ( !SystemInfoUtils::GetDeviceFileName( lpFileName,
| W> deviceFileName ) )
| W> | {
| W> | _tprintf( _T("GetDeviceFileName() failed.\n") );
| W> | return;
| W> | }
| W> | }
| W> |
| W> | hi.SetFilter( _T("File"), TRUE );
| W> |
| W> | if ( hi.m_HandleInfos.GetHeadPosition() == NULL )
| W> | {
| W> | _tprintf( _T("No handle information\n") );
| W> | return;
| W> | }
| W> |
| W> | pi.Refresh();
| W> |
| W> | _tprintf( _T("%-6s %-20s %s\n"), _T("PID"), _T("Name"),
| W> _T("Path") );
| W> | _tprintf(
| W> _T("------------------------------------------------------\n") );
| W> |
| W> | for ( POSITION pos = hi.m_HandleInfos.GetHeadPosition(); pos !=
| W> NULL; )
| W> | {
| W> | SystemHandleInformation::SYSTEM_HANDLE& h =
| W> hi.m_HandleInfos.GetNext(pos);
| W> |
| W> | if ( pi.m_ProcessInfos.Lookup( h.ProcessID, p ) )
| W> | {
| W> | SystemInfoUtils::Unicode2CString( &p->usName, processName );
| W> | }
| W> | else
| W> | processName = "";
| W> |
| W> | //NT4 Stupid thing if it is the services.exe and I call GetName :((
| W> | if ( INtDll::dwNTMajorVersion == 4 && _tcsicmp( processName,
| W> _T("services.exe"
| W> | ) ) == 0 )
| W> | continue;
| W> |
| W> | hi.GetName( (HANDLE)h.HandleNumber, name, h.ProcessID );
| W> |
| W> | if ( bFullPathCheck )
| W> | bShow = _tcsicmp( name, deviceFileName ) == 0;
| W> | else
| W> | bShow = _tcsicmp( GetFileNamePosition(name), lpFileName ) == 0;
| W> |
| W> | if ( bShow )
| W> | {
| W> | if ( !bFullPathCheck )
| W> | {
| W> | fsFilePath = "";
| W> | SystemInfoUtils::GetFsFileName( name, fsFilePath );
| W> | }
| W> |
| W> | _tprintf( _T("0x%04X %-20s %s\n"),
| W> | h.ProcessID,
| W> | processName,
| W> | !bFullPathCheck ? fsFilePath : lpFileName );
| W> | }
| W> | }
| W> | }
| W> |
| W> |
| W> | D> No, I don't want an already made utility. I would like to know
| W> how to
| W> | D> do this in c#.
| W> | D>
| W> | D> Thanks
| W> | D>
| W> | D> "Petar Repac" wrote:
| W> | D>
| W> | >> Demetri wrote:
| W> | >>
| W> | >>> Anyone know how I can find out if any process has a handle on a
| W> | >>> specific file?
| W> | >>>
| W> | >> Take a look at
| W> http://www.sysinternals.com/FileAndDiskUtilities.html
| W> | >> maybe you will find what you need there.
| W> | >>
| W> | >> Regards,
| W> | >> Petar
| W> | ---
| W> | WBR,
| W> | Michael Nemtsev :: blog: http://spaces.live.com/laflour
| W> |
| W> | "At times one remains faithful to a cause only because its
| W> opponents do
| W> not
| W> | cease to be insipid." (c) Friedrich Nietzsche
| W> |
| W> |
| ---
| WBR,
| Michael Nemtsev :: blog: http://spaces.live.com/laflour
|
| "At times one remains faithful to a cause only because its opponents do
not
| cease to be insipid." (c) Friedrich Nietzsche
|
|
 
See my reply to Michael.

Willy.



| You know, it amazes me how something that seems like a fundamental thing
for
| an OS is so hard to come by (code wise). Of course I only want production
| worthy code. Why is the code to do such a thing so remote and almost
| un-findable (if that is a word).
|
| --
| -Demetri
|
|
| "Willy Denoyette [MVP]" wrote:
|
| > Beware that this code uses undocumented exports from ntdll.dll, and
requires
| > that the caller is a member of the "debug users" group!
| > Which means that this is not something you would ever use in production
| > code.
| >
| > Willy.
| >
| >
| > | > | Hello Demetri,
| > |
| > | See info there
| > |
http://www.codeguru.com/Cpp/W-P/system/processesmodules/article.php/c2827
| > | and there
http://vbnet.mvps.org/index.html?code/network/netfileenum.htm
| > |
| > | The WinAPI code for this is:
| > |
| > | void WhoUsesFile( LPCTSTR lpFileName, BOOL bFullPathCheck )
| > | {
| > | BOOL bShow = FALSE;
| > | CString name;
| > | CString processName;
| > | CString deviceFileName;
| > | CString fsFilePath;
| > | SystemProcessInformation::SYSTEM_PROCESS_INFORMATION* p;
| > | SystemProcessInformation pi;
| > | SystemHandleInformation hi;
| > |
| > | if ( bFullPathCheck )
| > | {
| > | if ( !SystemInfoUtils::GetDeviceFileName( lpFileName,
deviceFileName ) )
| > | {
| > | _tprintf( _T("GetDeviceFileName() failed.\n") );
| > | return;
| > | }
| > | }
| > |
| > | hi.SetFilter( _T("File"), TRUE );
| > |
| > | if ( hi.m_HandleInfos.GetHeadPosition() == NULL )
| > | {
| > | _tprintf( _T("No handle information\n") );
| > | return;
| > | }
| > |
| > | pi.Refresh();
| > |
| > | _tprintf( _T("%-6s %-20s %s\n"), _T("PID"), _T("Name"),
_T("Path") );
| > | _tprintf(
| > _T("------------------------------------------------------\n") );
| > |
| > | for ( POSITION pos = hi.m_HandleInfos.GetHeadPosition(); pos !=
NULL; )
| > | {
| > | SystemHandleInformation::SYSTEM_HANDLE& h =
hi.m_HandleInfos.GetNext(pos);
| > |
| > | if ( pi.m_ProcessInfos.Lookup( h.ProcessID, p ) )
| > | {
| > | SystemInfoUtils::Unicode2CString( &p->usName, processName );
| > | }
| > | else
| > | processName = "";
| > |
| > | //NT4 Stupid thing if it is the services.exe and I call GetName :((
| > | if ( INtDll::dwNTMajorVersion == 4 && _tcsicmp( processName,
| > _T("services.exe"
| > | ) ) == 0 )
| > | continue;
| > |
| > | hi.GetName( (HANDLE)h.HandleNumber, name, h.ProcessID );
| > |
| > | if ( bFullPathCheck )
| > | bShow = _tcsicmp( name, deviceFileName ) == 0;
| > | else
| > | bShow = _tcsicmp( GetFileNamePosition(name), lpFileName ) == 0;
| > |
| > | if ( bShow )
| > | {
| > | if ( !bFullPathCheck )
| > | {
| > | fsFilePath = "";
| > | SystemInfoUtils::GetFsFileName( name, fsFilePath );
| > | }
| > |
| > | _tprintf( _T("0x%04X %-20s %s\n"),
| > | h.ProcessID,
| > | processName,
| > | !bFullPathCheck ? fsFilePath : lpFileName );
| > | }
| > | }
| > | }
| > |
| > |
| > | D> No, I don't want an already made utility. I would like to know how
to
| > | D> do this in c#.
| > | D>
| > | D> Thanks
| > | D>
| > | D> "Petar Repac" wrote:
| > | D>
| > | >> Demetri wrote:
| > | >>
| > | >>> Anyone know how I can find out if any process has a handle on a
| > | >>> specific file?
| > | >>>
| > | >> Take a look at
http://www.sysinternals.com/FileAndDiskUtilities.html
| > | >> maybe you will find what you need there.
| > | >>
| > | >> Regards,
| > | >> Petar
| > | ---
| > | WBR,
| > | Michael Nemtsev :: blog: http://spaces.live.com/laflour
| > |
| > | "At times one remains faithful to a cause only because its opponents
do
| > not
| > | cease to be insipid." (c) Friedrich Nietzsche
| > |
| > |
| >
| >
| >
 
Suppose a file is being written to by some other application (not yours) and
it is a large file (up to 6 or 8 gigs). Your code is watching what is being
written to but would not know that the writting is completed. The only way I
can figure out if the file is done being written is to check if something has
an open handle on it.

Got other bright ideas?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top