Frage

Dies ist eine Client-Server-Anwendung. Ich erstelle ein Update-Programm, das eine Liste von EXE-Dateien, Skripts ausführen ersetzen wird, und alles anderes, dass der Bedarf aktualisiert werden. Dies wird auf dem Server installiert werden.

Zuerst habe ich Notwendigkeit zu überprüfen, ob die ausführbare Datei über eine Netzwerkfreigabe geöffnet wird. Ich kann, indem Sie in der Computerverwaltung dies manuell tun dann Gemeinsame Dateien und Dateien öffnen. Dies scheint der einzige Weg, um zu überprüfen, ob die Datei geöffnet ist. Ich habe versucht, R / W mit überprüfen, ob die Datei geöffnet wird, aber das hat nicht funktioniert. Betrachtete Win32_ServerConnection aber nur aufgeführte Anzahl von Dateien, die nicht die Namen waren offen.

Das mag ich 7 oder C # in Delphi codieren, wenn es nicht in Delphi getan werden kann. Ich habe ein paar Programme gefunden, die die geöffneten Dateien auf einem Server anzeigen können, aber nichts darüber, wie dies geschehen kann.

War es hilfreich?

Lösung

ich eine Funktion wie diese, um zu überprüfen, ob ich eine Datei auf dem Dateisystem verändern kann. Grundsätzlich versuche ich zu „erstellen“ eine neue Datei namens fName, noch die bestehende (es sollte vorhanden sein) öffnen und eine gültige Datei-Handle, um es zu bekommen. Wenn das fehlschlägt, dann ist die Datei verwendet. Die Funktion erstellt keine tatsächlich eine Datei, noch ändert es die bestehende filessytem (ich nie mit dem Griff alles tun). Es ist einfach überprüfen, ob ich eine Datei Handle auf die Datei bekommen kann, sollte ich etwas damit tun möchten.

Das funktioniert auch für Dateien von einer Freigabe auf einem entfernten Computer geöffnet werden kann.

 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;

Andere Tipps

Warum Sie nicht nur versuchen, es zu löschen? Sie erhalten eine Fehlermeldung erhalten, wenn die Datei geöffnet ist. Und wenn das Löschen funktioniert, können Sie einfach kopieren Sie die aktualisierte ausführbare Datei.

Unter Windows 2000 und höher, könnten Sie 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.

Es scheint, dass der Pfad im LocalPath Parameter übergeben hat mit einem doppelten Schrägstrich beginnen, z.

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

Die Ausgabe (wenn die Datei durch eine Aktie geöffnet ist):

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

Beachten Sie auch, dass MSDN sagt:

  

"Nur Mitglieder der Administratoren oder   Server-Operatoren lokale Gruppe kann   erfolgreich führen die NetFileEnum   Funktion. "

Sie können eine statische Liste von „Server“ halten, dass dies läuft auf, der Name Prozessmaschine Nachschlag kann, den Hostnamen oder den Computernamen für ein Spiel. Wenn es in der Liste können Sie seine offene lokale nehmen.

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");
}

Haben Sie das Filesystemwatcher in System.IO gesehen?

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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top