Auf UNC-Pfad mit Zugangsdaten zugreifen?

Alle Fragen zur Netzwerkkommunikation
Antworten
Lion
Beiträge: 199
Registriert: Mo 24. Mär 2014, 09:58

Auf UNC-Pfad mit Zugangsdaten zugreifen?

Beitrag von Lion »

Hallo Leute,

ich muss auf ein UNC-Verzeichnis zugreifen, das benutzerbeschränkt ist.
Kennt jemand eine Methode, mit der man per Benutzername und Passwort eine Verbindung zu diesem Verzeichnis herstellen kann?

Vielen Dank im Voraus!

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 385
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Auf UNC-Pfad mit Zugangsdaten zugreifen?

Beitrag von Jorg3000 »

Hi!
Falls es Windows betrifft, geht es mit dem Shell-Command "net", wie auf folgender Seite beschrieben:
https://learn.microsoft.com/en-us/previ ... 5(v=ws.11)

Code: Alles auswählen

net use \\Server\FreigabeOrdner /user:Domain\Benutzername Passwort
Wenn keine Domäne verwendet wird, wird als Domain der PC- oder Server-Name angegeben, der das Benutzerkonto bereitstellt.

Verwendung in FreePascal:

Code: Alles auswählen

var
  AProcess: TProcess;
begin
  AProcess := TProcess.Create(nil);
  try
    AProcess.Executable := 'net';
    AProcess.Parameters.Add('use');
    AProcess.Parameters.Add('\\Server\FreigabeOrdner');
    AProcess.Parameters.Add('/user:Domain\Benutzername');
    AProcess.Parameters.Add('Passwort');
    AProcess.Options := AProcess.Options + [poWaitOnExit];  // optional
    AProcess.Execute;
  finally
    AProcess.Free;
  end;
end;
Grüße, Jörg

Lion
Beiträge: 199
Registriert: Mo 24. Mär 2014, 09:58

Re: Auf UNC-Pfad mit Zugangsdaten zugreifen?

Beitrag von Lion »

Danke Dir!

Bin jetzt etwas schlauer geworden und erfahren, dass "net use" mir nicht passt, da mein Programm eine eigene Verbinfung mit User und Passwort zu der Netzfreigabe aufbaut. Net use erlaubt aber nicht, dass sich zwei User von einer Maschine anmelden.

Die KI hat mir folgende Lösung presentiert, aber das Ding schmeißt ständig den Fehler 1219, und es gelingt mir nicht diesen zu umgehen.

Code: Alles auswählen

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Windows, Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    btnVerbinden: TButton;
    edtServer: TEdit;
    edtBenutzer: TEdit;
    edtPasswort: TEdit;
    lblServer: TLabel;
    lblBenutzer: TLabel;
    lblPasswort: TLabel;
    memLog: TMemo;
    procedure btnVerbindenClick(Sender: TObject);
  private
    function VerbindeMitFreigabe(const Server, Benutzer, Passwort: AnsiString): DWORD;
    procedure Log(const Msg: string);
  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

type
  PNetResourceA = ^TNetResourceA;
  TNetResourceA = record
    dwScope: DWORD;
    dwType: DWORD;
    dwDisplayType: DWORD;
    dwUsage: DWORD;
    lpLocalName: PAnsiChar;
    lpRemoteName: PAnsiChar;
    lpComment: PAnsiChar;
    lpProvider: PAnsiChar;
  end;

function WNetAddConnection2A(lpNetResource: PNetResourceA; lpPassword, lpUsername: PAnsiChar;
  dwFlags: DWORD): DWORD; stdcall; external 'mpr.dll' name 'WNetAddConnection2A';

function WNetCancelConnection2A(lpName: PAnsiChar; dwFlags: DWORD; fForce: BOOL): DWORD;
  stdcall; external 'mpr.dll' name 'WNetCancelConnection2A';

procedure TForm1.Log(const Msg: string);
begin
  //memLog.Lines.Add(FormatDateTime('hh:nn:ss', Now) + ' - ' + Msg);
end;

function TForm1.VerbindeMitFreigabe(const Server, Benutzer, Passwort: AnsiString): DWORD;
var
  NetRes: TNetResourceA;
  Res: DWORD;
begin
  // Vorherige Verbindung zum Server trennen (erzwingen)
  Log('Versuche bestehende Verbindung zu trennen...');
  Res := WNetCancelConnection2A(PAnsiChar(Server), 0, True);
  if (Res <> NO_ERROR) and (Res <> ERROR_NOT_CONNECTED) then
  begin
    Log('Fehler beim Trennen: ' + IntToStr(Res));
    Result := Res;
    Exit;
  end
  else
    Log('Verbindung getrennt oder keine Verbindung vorhanden.');

  FillChar(NetRes, SizeOf(NetRes), 0);
  NetRes.dwType := RESOURCETYPE_DISK;
  NetRes.lpLocalName := nil; // Kein Laufwerksbuchstabe
  NetRes.lpRemoteName := PAnsiChar(Server);
  NetRes.lpProvider := nil;

  Log('Versuche neue Verbindung aufzubauen...');
  Result := WNetAddConnection2A(@NetRes, PAnsiChar(Passwort), PAnsiChar(Benutzer), 0);

  if Result = NO_ERROR then
    Log('Verbindung erfolgreich.')
  else
    Log('Verbindung fehlgeschlagen mit Fehlercode: ' + IntToStr(Result));
end;

procedure TForm1.btnVerbindenClick(Sender: TObject);
var
  FehlerCode: DWORD;
  Server, Benutzer, Passwort: AnsiString;
begin
  Server := AnsiString(edtServer.Text);
  Benutzer := AnsiString(edtBenutzer.Text);
  Passwort := AnsiString(edtPasswort.Text);

  Log('Starte Verbindungsaufbau zu ' + string(Server));
  FehlerCode := VerbindeMitFreigabe(Server, Benutzer, Passwort);

  if FehlerCode = NO_ERROR then
    ShowMessage('Verbindung erfolgreich!')
  else
    ShowMessage('Fehler beim Verbinden: ' + IntToStr(FehlerCode));
end;

end.


Benutzeravatar
theo
Beiträge: 10921
Registriert: Mo 11. Sep 2006, 19:01

Re: Auf UNC-Pfad mit Zugangsdaten zugreifen?

Beitrag von theo »

Error 1219 typically occurs in Windows when you are trying to connect to a network share using different credentials while there is already an existing connection to the same share with different credentials. Windows does not allow multiple connections to the same network resource with different credentials.

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 385
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Auf UNC-Pfad mit Zugangsdaten zugreifen?

Beitrag von Jorg3000 »

Was das englische Zitat von Theo sagen will:
Eine Freigabe kann nur für einen Benutzer gleichzeitig verbunden sein (pro Windows-Client). Das gilt generell unter Windows, damit es keine Authentifizierungskonflikte gibt.
Und deshalb spielt es keine Rolle, ob du "net use" an der Konsole oder die importierten Funktionen aus der Windows-eigenen DLL verwendest. Deshalb wird in deinem KI-Beispiel ja auch eine Trennung durchgeführt. Das Gleiche macht der /delete Parameter bei "net use".
Wenn die Trennung und das Verbinden nicht funktioniert, werden vielleicht falsche Parameter übergeben. Erforderlich ist soetwas wie: \\server\freigabe sowie DOMAIN\Benutzername oder SERVERNAME\Benutzername

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6848
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Auf UNC-Pfad mit Zugangsdaten zugreifen?

Beitrag von af0815 »

Lion hat geschrieben: Mo 2. Jun 2025, 15:28 Bin jetzt etwas schlauer geworden und erfahren, dass "net use" mir nicht passt, da mein Programm eine eigene Verbinfung mit User und Passwort zu der Netzfreigabe aufbaut. Net use erlaubt aber nicht, dass sich zwei User von einer Maschine anmelden.
Von einem PC kann man zu einem Server ist es nur möglich mit einem Creditial (=User) sich anzumelden. Zwei unterschiedliche Verbindungen gehen nicht. Man kann nur eine Verbindung aufbauen, arbeiten, Verbindung sauber ! abbauen und mit neuen User sich anmelden. Baut man die Verbindung nicht sauber ab, kommt der andere Benutzer nicht hinein und bekommt die entsprechenden Fehlermeldungen so wie du. Mit net use sieht man meistens die noch bestehende Verbindung, obwohl der Datei Explorer sie nicht mehr anzeigt.

Und vergiss was die KI zusammenträumt und dir sagt was geht. Die meisten sogenannten Lösungen haben im Hintergrund hinkende Pferdefüße. Und hier ist die Beschränkung des fernen Betriebssystems.

Ich verwende zum Beispiel (aus den Zeiten vor der KI, also ganz einfach MI - menschliche Intelligenz). Allerdings schon lange nicht mehr verwendet, weil kein Windows im Einsatz :-)
unit WNNetShare;

{$mode objfpc}{$H+}

interface

uses
Classes, SysUtils;

function ConnectNetworkDrive(const ADrive: String;
const ADirectory, AUsername, APassword: String;
const ARestoreAtLogon: Boolean ): Boolean;

procedure DisconnetNetworkDrive(const ADrive: String);


implementation

uses
windows;

function ConnectNetworkDrive(const ADrive: String;
const ADirectory, AUsername, APassword: String;
const ARestoreAtLogon: Boolean ): Boolean;
var
NetResource: TNetResource;
dwFlags: DWORD;
lPwd, lUser: PChar;
begin
NetResource.dwType:=RESOURCETYPE_DISK;
NetResource.lpLocalName:=PChar(ADrive);
NetResource.lpRemoteName:=PChar(ADirectory);
NetResource.lpProvider:=nil;

if ARestoreAtLogon then
dwFlags:=CONNECT_UPDATE_PROFILE
else
dwFlags:=0;
if AUsername = '' then
lUser:=PChar(AUsername)
else
lUser:=nil;
if APassword = '' then
lPwd:=PChar(APassword)
else
lPwd:=nil;
Result:=WNetAddConnection2(NetResource,
lPwd,
lUser,
dwFlags)=NO_ERROR;
end;

procedure DisconnetNetworkDrive(const ADrive: String);
begin
if not WNetCancelConnection2(PChar(ADrive),0, True)=NO_ERROR then
RaiseLastOSError;
end;


end.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

PascalDragon
Beiträge: 962
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Auf UNC-Pfad mit Zugangsdaten zugreifen?

Beitrag von PascalDragon »

Du könntest dir für die Bibliothek libsmb2 eine Unit schreiben (oder eventuell durch h2pas generieren lassen) und diese nutzen. Das ist dann nämlich eine separate Verbindung.
FPC Compiler Entwickler

Antworten