Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi "Nichtverbundenes Netzlaufwerk" aktivieren (https://www.delphipraxis.net/156483-nichtverbundenes-netzlaufwerk-aktivieren.html)

FBrust 3. Dez 2010 13:32

"Nichtverbundenes Netzlaufwerk" aktivieren
 
Hallo,

ich habe hier ein Buffalo-NAS, das beim Hochfahren des PCs automatisch ebenfalls hochfährt.
Leider braucht das NAS länger zum Booten als mein PC, so dass die freigegebenen Netzlaufwerke ständig als "Nichtverbundenes Netzlaufwerk" im Arbeitsplatz angezeigt werden und erst nach einem Doppelklick ihren Inhalt zeigen bzw. verbunden werden.

Meine Frage ist nun, wie ich diese nichtverbundenen Laufwerke aus meinem Delphi-Programm heraus "aktivieren" kann?

Gruß
Frank

himitsu 3. Dez 2010 13:37

AW: "Nichtverbundenes Netzlaufwerk" aktivieren
 
Hast du mal versucht einfach auf das Laufwerk zuzugreifen?

z.B. via TFileStream auf eine Datei zugreifen oder mit FindFirst das Hauptverzeichnis aufzulisten

shmia 3. Dez 2010 15:02

AW: "Nichtverbundenes Netzlaufwerk" aktivieren
 
Das Problem hatte ich auch schon und habe mir dazu folgende Prozedure geschrieben:
Delphi-Quellcode:
type
   TWNetRestoreConnectionW = function (hwndParent:HWND; lpDevice:PWideChar):DWORD; stdcall;

function ReconnectDrive(const path:string):DWORD;
var
   libhandle : HMODULE;
   func : TWNetRestoreConnectionW;
   driveW : WideString;
begin
   Result := 0;
   driveW := ExtractFileDrive(path);
   if driveW='' then
      Exit;

   libhandle := LoadLibrary('mpr.dll');
   if libhandle=0 then
      Exit;
   try
      func := TWNetRestoreConnectionW(GetProcAddress(libhandle, 'WNetRestoreConnectionW'));
      if Assigned(func) then
         Result := func(0, @driveW[1]);
   finally
      FreeLibrary(libhandle);
   end;
end;
Bitte hier rückmelden, ob es funktioniert.
Meine Tests liegen schon lange zurück, so dass es mich interessieren würde,
ob das wirklich klappt.
WNetRestoreConnectionW gibt es anscheinend nicht unter Vista und höher.
Hier wäre Jugend-Forscht gefragt.

DelphiBandit 3. Dez 2010 15:07

AW: "Nichtverbundenes Netzlaufwerk" aktivieren
 
Es gibt eine Möglichkeit über die Registry die Laufwerk-Buchstaben trotzdem als verbunden zu zeigen, das eigentliche Verbinden erfolgt aber erst bei ersten Zugriff auf das Laufwerk. Weiß nicht, ob es Dir nur um die "nicht verbundenen Laufwerke" geht - dann wäre Dir damit sicher geholfen. Oder ob Du tatsächlich schon drauf zugreifen willst, dann nicht.

Gefunden hier oder mit Suchen

FBrust 17. Jan 2011 15:46

AW: "Nichtverbundenes Netzlaufwerk" aktivieren
 
Hallo,

tut mir leid, dass ich mich erst jetzt melde, aber ich wollte auf jeden Fall noch Rückmeldung geben:

Mit dem Code von shmia funktioniert der Zugriff sofort, zumindest unter XP, zu Windows 7 kann ich nix sagen, soweit bin ich noch nicht :).

Vielen Dank für die Hilfe :thumb:


Gruß
Frank

shadowman 11. Dez 2015 11:21

AW: "Nichtverbundenes Netzlaufwerk" aktivieren
 
Hallo,

lange her seit dem letzten Beitrag, aber das Problem ist wohl noch aktuell.

Wie oben schon erwähnt wurde, gibt es ab Vista die Funktion "WNetRestoreConnectionW" nicht mehr, so dass der Code von shmia im Post #3 unter Windows 8.1 nicht funktioniert.

In diesem Artikel zu der entfernten Funktion wird im Abschnitt "Community Additions" unter "The Third Parameter is WRONG" die Funktion "WNetRestoreSingleConnectionW" erwähnt, die es auch in Vista, Windows 8.1 etc. gibt. Klang vielversprechend, also habe ich das Beispiel aus Post #3 wie folgt abgeändert:

Code:
type
   TWNetRestoreSingleConnectionW = function (hwndParent:HWND; lpDevice:PWideChar; fUseUI:boolean):DWORD; stdcall;

function ReconnectDrive(const path:string):DWORD;
var
   libhandle : HMODULE;
   func : TWNetRestoreSingleConnectionW;
   driveW : WideString;
begin
   Result := 0;
   driveW := ExtractFileDrive(path);
   if driveW='' then
      Exit;

   libhandle := LoadLibrary('mpr.dll');
   if libhandle=0 then
      Exit;
   try
      func := TWNetRestoreSingleConnectionW(GetProcAddress(libhandle, 'WNetRestoreSingleConnectionW'));
      if Assigned(func) then
         Result := func(0, @driveW[1], true);
   finally
      FreeLibrary(libhandle);
   end;
end;
Leider zu früh gefreut. Übergibt man für "fUseUI" false, gibt es keine Rückmeldung und das Laufwerk bleibt "inaktiv". Übergibt man true, bleibt das Laufwerk zwar auch "inaktiv", aber es wird zumindest das angezeigt:
Zitat:

Fehler bei der erneuten Verbindungsherstellung von K: mit
\\SV-MAIN\K (Entwicklung)
Microsoft Windows Network: Der lokale Gerätename wird bereits verwendet.

Die Verbindung wurde nicht wiederhergestellt.
Ansonsten habe ich nach längeren Recherchen noch diese zwei Möglichkeiten gefunden:

#1 http://www.devsuperpage.com/search/A...p?ArtID=149021
Code:
function ConnectDrive(_drvLetter: string; _netPath: string; _showError:
Boolean;
  _reconnect: Boolean): DWORD;
var
  nRes: TNetResource;
  errCode: DWORD;
  dwFlags: DWORD;
begin
  { Fill NetRessource with #0 to provide uninitialized values }
  { NetRessource mit #0 füllen => Keine unitialisierte Werte }
  FillChar(NRes, SizeOf(NRes), #0);
  nRes.dwType := RESOURCETYPE_DISK;
  { Set Driveletter and Networkpath }
  { Laufwerkbuchstabe und Netzwerkpfad setzen }
  nRes.lpLocalName := PChar(_drvLetter);
  nRes.lpRemoteName := PChar(_netPath); { Example: \\Test\C }
  { Check if it should be saved for use after restart and set flags }
  { Überprüfung, ob gespeichert werden soll }
  if _reconnect then
    dwFlags := CONNECT_UPDATE_PROFILE and CONNECT_INTERACTIVE
  else
    dwFlags := CONNECT_INTERACTIVE;

  errCode := WNetAddConnection3(Form1.Handle, nRes, nil, nil, dwFlags);
  { Show Errormessage, if flag is set }
  { Fehlernachricht aneigen }
  if (errCode <> NO_ERROR) and (_showError) then
  begin
    Application.MessageBox(PChar('An error occured while connecting:' +
#13#10 +
      SysErrorMessage(GetLastError)),
      'Error while connecting!',
      MB_OK);
  end;
  Result := errCode; { NO_ERROR }
end;
#2 http://www.experts-exchange.com/ques...ped-Drive.html
Code:
function RefreshMappedDrive(cDrvLetter: Char): Boolean;
const
  WbemUser           ='';
  WbemPassword       ='';
  WbemComputer       ='localhost';
  wbemFlagForwardOnly = $00000020;
var
  FSWbemLocator : OLEVariant;
  FWMIService  : OLEVariant;
  FWbemObjectSet: OLEVariant;
  FWbemObject  : OLEVariant;
  oEnum        : IEnumvariant;
  iValue       : LongWord;
  WshNetwork   : OLEVariant;
begin;
  Result := False;

  FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  FWMIService  := FSWbemLocator.ConnectServer(WbemComputer, 'root\CIMV2', WbemUser, WbemPassword);
  FWbemObjectSet:= FWMIService.ExecQuery('SELECT LocalName,ConnectionState,RemotePath FROM Win32_NetworkConnection','WQL',wbemFlagForwardOnly);
  oEnum        := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
  while oEnum.Next(1, FWbemObject, iValue) = 0 do
  begin
    if String(FWbemObject.LocalName) = (cDrvLetter+':') then //if this drive
    begin
      if String(FWbemObject.ConnectionState) <> 'Connected' then //if disconnected
      begin
        //try to reconnect ....
        try
          WshNetwork := CreateOleObject('WScript.Network');
          WshNetwork.MapNetworkDrive(cDrvLetter+':', String(FWbemObject.RemotePath));
        except
        end;
        Result := True;
      end
      else
      begin
        Result := True;
      end;
      Break;
    end;
    FWbemObject:=Unassigned;
  end;
end;

procedure TForm1.Button6Click(Sender: TObject);
begin
  if FileExists('z:\test.txt') then
    Memo2.Lines.Add('exists')
  else
  begin
    Memo2.Lines.Add('connecting');

    CoInitialize(nil);
    try
      RefreshMappedDrive('Z');
    finally
      CoUninitialize;
    end;
  end;
end;

Beide funktionieren aber ebenfalls nicht so richtig.

Beim ersten Beispiel gibt es das:
Zitat:

An error occured while connecting:
Der angegebene Gerätename ist unzulässig
Beim zweiten Beispiel gibt es das:
Zitat:

Der lokale Gerätename wird bereits verwendet
Sonst gab es noch Beiträge zum tatsächlichen Einrichten / Entfernen von Netzlaufwerken per Code, was aber aufgrund der höchstwahrscheinlichen notwendigen Eingabe des Benutzernamens / des Passwords etc. nicht infrage kommt.


Habt Ihr vielleicht neuere Erkentnisse / Lösungsvorschläge?

mensch72 11. Dez 2015 11:59

AW: "Nichtverbundenes Netzlaufwerk" aktivieren
 
Ich würde zunächst mal schaun, ob wenn das Problem besteht, es per Kommandozeile mit "net ..." einen Weg gäbe es zu lösen. Ob man dann die passenden API Aufrufe sucht, oder es per ShellExecute dann auch weiter mit "net ..." macht, ist dann eine Geschmackssache.

Ansonsten wenn die Laufwerksverbindungen nicht automatisch beim Windowsstart "sofort" hergestellt werden, sondern per (verzögerter) "nasconnect.cmd" Batchdatei durch Aufruf von "net use ..." sollte das einfach lösbar sein, wenn die NAS hochgefahren und bereit ist.

jobo 11. Dez 2015 13:37

AW: "Nichtverbundenes Netzlaufwerk" aktivieren
 
Zitat:

Zitat von shadowman (Beitrag 1324091)
Sonst gab es noch Beiträge zum tatsächlichen Einrichten / Entfernen von Netzlaufwerken per Code, was aber aufgrund der höchstwahrscheinlichen notwendigen Eingabe des Benutzernamens / des Passwords etc. nicht infrage kommt.

Kommt man denn um User / Password Angabe drum rum?
Ich hab keine Ahnung von den API Calls, aber es kann nur 2 Varianten geben:
a) Der Nutzer ist in der Domäne authentifiziert, dann ist eine Angabe von User/Pw nicht notwendig
b) Er ist nicht in der Domäne angemeldet, dann muss er sich mit irgendeinem account + PW anmelden

Sollte mit "net use.." alles nachvollziehbar sein. Das ist wahrscheinlich auch die langlebigere Schnittstelle.

shadowman 12. Dez 2015 10:03

AW: "Nichtverbundenes Netzlaufwerk" aktivieren
 
Hallo, danke für Eure Rückmeldungen.

Grundsätzlich geht es um den Fall, dass der angemeldete Benutzer die nötigen Rechte hat und die Laufwerke in der Regel auch da sind, also verbunden. Manchmal kommt es vor, dass die zwar im Explorer zu sehen, aber mit rotem X gekennzeichnet sind, also nicht verbunden. Klickt man im Explorer doppelt auf das Laufwerk, ist man ohne Passwort-Abfrage direkt drin. Genau um diese Wiederherstellung geht es mir, was bis Vista ja auch ging. Bei anderen Konstellation soll von mir aus gerne die PW-Abfrage etc. kommen, denn dann käme sie ja auch aus dem Explorer heraus.

Eine evtl. "optimierfähige" automatisierte Einrichtung / Wiederherstellung beim Start ist in dem Fall keine Option, weil das bei den Kunden passiert und da kann man nicht jedem Tipps oder Skripte in die Hand drücken, wie man es besser macht, oder sich selbst um deren Netzwerke kümmern. Deswegen hoffe ich, dass es aus unserer Anwendung irgendwie geht.

Das mit "net..." / "net use..." muss ich mir anschauen - kenne mich da nicht so aus. Verstehe aber nicht, warum die Möglichkeit ab Vista entfernt wurde. Wäre sehr praktisch gewesen. Neue Erkentnisse zu den verbleibenden Möglichkeiten (s.o.) scheint es nicht zu geben, obwohl es das Problem häufig gibt: gestern z.B. meine Entwicklungs-VM gestartet und Lauferke zu einem der Server waren nicht verbunden. Heute gestartet und alle Laufwerke sind wieder ganz normal da (wie meistens). Hier ist es ja kein Problem, aber die Kunden rufen dann an und meinen das Programm läuft nicht mehr. Ist dann zwar schnell erklärt was Sache ist, aber nervig ist es trotzdem.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:45 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz