如何检查是否从服务器访问exe

这是客户端服务器应用程序。 我正在创建一个更新程序,它将替换exe文件列表,运行脚本以及需要更新的任何其他内容。 这将安装在服务器上。

首先,我需要检查是否通过网络共享打开了可执行文件。 我可以通过进入计算机管理然后共享文件和打开文件手动完成此操作。 这似乎是检查文件是否打开的唯一方法。 我尝试使用R / W来检查文件是否已打开,但这不起作用。 看看Win32_ServerConnection,但这只列出了打开的文件数而不是名称。

如果在Delphi中无法完成,我想用Delphi 7或C#编写代码。 我找到了一些程序可以查看服务器上的打开文件,但没有关于如何做到这一点。

我使用这样的函数来检查我是否可以改变文件系统上的文件。 基本上我尝试“创建”一个名为fName的新文件,仍然打开现有的(如果存在)并获得有效的文件句柄。 如果失败,则该文件正在使用中。 该函数实际上并不创建文件,也不会改变现有的filessytem(我从不对句柄做任何事情)。 它只是检查我是否可以获取文件句柄文件,我是否应该用它做一些事情。

这也适用于从远程计算机上的共享打开的文件。

function IsFileInUse(fName: string): boolean; var HFileRes: HFILE; begin Result := false; if not FileExists(fName) then exit; HFileRes := CreateFile(pchar(fName), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); Result := (HFileRes = INVALID_HANDLE_VALUE); if not Result then CloseHandle(HFileRes); end; 

你为什么不试着删除它? 如果文件当前处于打开状态,您将收到错误消息。 如果删除它有效,您只需复制更新的可执行文件。

在Windows 2000及更高版本中,您可以使用NetFileEnum API:

 program test; {$APPTYPE CONSOLE} uses Windows, Classes, SysUtils; type PFileInfo3 = ^TFileInfo3; TFileInfo3 = record fi3_id: DWORD; fi3_permissions: DWORD; fi3_num_locks: DWORD; fi3_pathname: PWideChar; fi3_username: PWideChar; end; TNetFileEnumCallback = function(const FileInfo: TFileInfo3; Data: Pointer): Boolean; const netapi = 'netapi32.dll'; function NetApiBufferFree(Buffer: Pointer): DWORD; stdcall; external netapi; function NetFileEnum(servername: PWideChar; basepath: PWideChar; username: PWideChar; level: DWORD; var bufptr: Pointer; prefmaxlen: DWORD; var entriesread: DWORD; var totalentries: DWORD; resume_handle: PDWORD): DWORD; stdcall; external netapi; procedure EnumNetFileUsers(const LocalPath: WideString; Callback: TNetFileEnumCallback; Data: Pointer = nil); const EntryCount = 32; var NetResult, EntriesRead, TotalEntries, ResumeHandle: Cardinal; Buf: Pointer; P: PFileInfo3; I: Integer; begin EntriesRead := 0; TotalEntries := 0; ResumeHandle := 0; repeat NetResult := NetFileEnum(nil, PWideChar(LocalPath), nil, 3, Buf, EntryCount * SizeOf(TFileInfo3), EntriesRead, TotalEntries, @ResumeHandle); if not (NetResult in [ERROR_SUCCESS, ERROR_MORE_DATA]) then RaiseLastOSError(NetResult); try P := Buf; for I := 0 to EntriesRead - 1 do begin if Callback(P^, Data) then Break; Inc(P); end; finally NetApiBufferFree(Buf); end; until NetResult = ERROR_SUCCESS; end; function ShowFileInfo(const FileInfo: TFileInfo3; Data: Pointer): Boolean; begin Result := False; Writeln(Format('id: %d, permissions: $%.8x, num_locks: %d, pathname: ''%s'', username: ''%s''', [FileInfo.fi3_id, FileInfo.fi3_permissions, FileInfo.fi3_num_locks, FileInfo.fi3_pathname, FileInfo.fi3_username])); end; begin try if ParamCount = 1 then EnumNetFileUsers(ParamStr(1), ShowFileInfo); except on E: Exception do begin Writeln(Format('[%s] %s', [E.ClassName, E.Message])); ExitCode := 1; end; end; end. 

似乎在LocalPath参数中传递的路径必须以双反斜杠开头,例如:

 test.exe C:\\Dev\Test\test.exe 

产生以下输出(如果文件通过共享打开):

 id: -469761405, permissions: $00000001, num_locks: 0, pathname: 'C:\\Dev\Test\test.exe', username: 'Ondrej' 

另请注意,MSDN说:

“只有Administrators或Server Operators本地组的成员才能成功执行NetFileEnum函数。”

您可以保留一个静态的“服务器”列表来运行,您可以查找匹配的进程计算机名称,主机名或计算机名称。 如果它在列表中你可以假设它是开放的本地。

 string name = Environment.MachineName; string name = System.Net.Dns.GetHostName(); string name = System.Windows.Forms.SystemInformation.ComputerName; Process[] myProcesses = Process.GetProcessesByName("myExeProcName",MachineName); foreach(Process myProcess in myProcesses) { Console.Write("MachineName : " + myProcess.MachineName + "\n"); } 

你见过System.IO中的FileSystemWatcher吗?

http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx