probleme beim einbinden von netapi32.lib
-
@JeGr : danke das du dich damit beschäftigst hast... das gute ist jetzt bei dem quelltext, dass das programm läuft. das schlechte, er findet keinen computer...
hast du das mal unter win9x probiert??? und müsste das programm auch den eigenen computer finden???
ach und kennst du irgendeine gute hilfe zu den ganzen sachen??? also winapi programmierung mit dem BCB zum beispiel??? ich weiß jetzt nämlich z.b. nicht, was eine netresource ist...
-
Also zur WinAPI kann ich auch nur sagen, dass ich die Sachen in der Windows SDK Hilfe bzw auf MSDN-Website nachgeschlagen habe.
Unter Win2k funktioniert der Code auf jeden Fall einandfrei.
Ich habe alle Rechner der Domäne (ca. 400 St.) in meinem RichEdit aufgelistet.Ich habe momentan hier nur Win2k, aber ich kann's heute Abend mal auf meinem Win98 Rechner ausprobieren.
Falls du die WinAPI Sachen nicht ganz verstehst, dann kann ich dir nur noch einmal die entsprechenden Hilfeseiten ans Herz legen.
Ich habe mich damit am Anfang auch sehr schwer getan, aber wenn man einmal den Trick raus hat, dann findet man sich ganz gut zurecht.
Ansonsten kannst du auch ein bisschen googeln, da findet man auch immer wieder ein paar interessante Schnippsel und Anregungen[ Dieser Beitrag wurde am 04.02.2003 um 12:47 Uhr von JeGr editiert. ]
-
Hi,
ja teste den Code ma auf Win9x! Und noch ne Frage, wie bekomme ich aus dem Rechnernamen die IP heraus!Danke
Alexander Sulrian
[edit] Hi,
hab gerade eine Delphi-Komponente gefunden, die genau das macht: http://overbyte.delphicenter.com/frame_index.html und dann runter scrollen zuName:
ICS_NetFind.zip
Size:
7 KB
Author:
Sven Schmidts
Use this component to make a broadcast and find all PC's, on wich this component is running. You can send your own data to the PC's and receive the data, that is send back within addional strings.Ich hab's noch nicht getestet und weiß nicht obs auf Win9x läuft! Drauf gekommen bin ich durch: http://www.delphipraxis.net/viewtopic.php?t=1872 !
Werde noch weiter suchen!Danke
Alexander Sulfrian
[/edit][ Dieser Beitrag wurde am 04.02.2003 um 17:52 Uhr von Alexander Sulfrian editiert. ]
-
So, ich habe die ganze Sache noch einmal überarbeitet.
Hab das Beispiel aus der Windows SDK Hilfe so modifiziert, dass nun die Rechnernamen des lokalen Netzerks in ein RichEdit geschrieben werden.Habe es unter Win98 und Win2k getestet und bei beiden habe ich das gleiche Resultat erhalten.
Hier der neue Code:
//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //=========================================================================== // Funktion ListNetworkComputer //--------------------------------------------------------------------------- // // Ermittelt die Rechnernamen im lokalen Netzwerk. // Ist Win9x kompatibel. //--------------------------------------------------------------------------- // // Erstellt 04/02/2003 by Jens Gross mit Borland C++ Builder 6 //=========================================================================== BOOL WINAPI ListNetworkComputer(HWND hwnd, HDC hdc, LPNETRESOURCE lpnr) { // Variablendeklaration HANDLE hEnum; // Handle von WNetOpenEnum DWORD Result; // Rückgabewert für WNetXXX DWORD Buffer = 16384; // 16K als Startgrösse DWORD Entries = 0xFFFFFFFF; // liste alle möglichen Einträge LPNETRESOURCE NetResource; // Pointer auf NETRESOURCE // (enthält die gelisteten Einträge) // führe WNetOpenEnum aus, um Auflistung der Netzwerkressourcen // zu beginnen und ermittle den Rückgabewert Result = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_ANY, 0, lpnr, &hEnum); // wenn Rückgabewert Fehler if(Result != NO_ERROR) { // gib Flag zurück, dass Funktion fehlerhaft return FALSE; } // solange noch Daten vorhanden sind do { // allokiere Speicher für NETRESOURCE-Struktur NetResource = (LPNETRESOURCE)GlobalAlloc(GPTR, Buffer); // führe WNetEnumResource aus, um Auflistung fortzusetzen, // die mit WNetOpenEnum begonnen wurde und ermittle Rückgabewert Result = WNetEnumResource(hEnum, &Entries, NetResource, &Buffer); // wenn Rückgabewert in Ordnung if(Result == NO_ERROR) { // ermittle für alle ermittelten Einträge die Namen for(DWORD i=0; i<Entries; i++) { // wenn ermittelter Eintrag ein Container ist // (z.B. Domäne, Arbeitsgruppe etc) if(RESOURCEUSAGE_CONTAINER == (NetResource[i].dwUsage & RESOURCEUSAGE_CONTAINER)) { // wenn List-Funktion FALSE liefert if(!ListNetworkComputer(hwnd, hdc, &NetResource[i])) { // gib Fehlermeldung aus ShowMessage("Fehler bei der weiteren Auflistung!"); } // List-Funktion hat TRUE geliefert else { // ermittle den Remotenamen AnsiString RemoteName = AnsiString(NetResource[i].lpRemoteName); // wenn Remotename vorhanden und der Name mit \\ beginnt // (\\ deshalb, damit nur Rechner aufgelistet werden und nicht // auch noch die Domänen, Arbeitsgruppen etc) if(RemoteName != "" && RemoteName.SubString(1,2) == "\\\\") { // schreibe Namen in RichEdit von Formular Form1->RichEdit1->Lines->Add(RemoteName); } } } } } // wenn keine weiteren Daten mehr vorliegen else if(Result != ERROR_NO_MORE_ITEMS) { // beende die Schleife break; } } while(Result != ERROR_NO_MORE_ITEMS); // gib den allokierten Speicher wieder frei GlobalFree((HGLOBAL)NetResource); // führe WNetCloseEnum aus, um die Auflistung zu beenden // und ermittle den Rückgabewert Result = WNetCloseEnum(hEnum); // wenn Rückgabewert Fehler if(Result != NO_ERROR) { // gib Flag zurück, dass Funktion fehlerhaft return FALSE; } // gib Flag zurück, dass Funktion erfolgreich return TRUE; } //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { // leere Inhalt von RichEdit RichEdit1->Clear(); // führe List-Funktion aus ListNetworkComputer(Application->Handle, NULL, NULL); } //---------------------------------------------------------------------------
Zum Theme IP-Adressen:
Du kannst dir zu einem Rechnernamen über Winsock mit gethostby...() und einer hostent-Struktur die IP-Adressen ermitteln.
Wie das genau geht, kann man in der FAQ bzw. bei Bytes&More nachlesen.
-
juhu es funktioniert!!!!!! danke JeGr!!!!!
es taucht dann, nachdem er die rechner aufgelistet hat, zwar die meldung "Fehler bei der weiteren Auflistung!" auf, aber das ist mir egal. wenns nichts schimmes ist, kann ich die zeile aus dem code ja auch einfach entfernen oder??? ist ja eigentlich bloß eine info für den benutzer...
ach JeGr, wo findet man die windows sdk hilfe eigentlich??? die ist kommt nicht gleich bei der windows installation auf den computer rauf, oder? danke...
-
Bei mir ist die SDK Hilfe jedenfalls installiert.
Wenn du im BCB unter dem Menü Hilfe nachschaust, dann befindet sich dort ein entsprechender Eintrag.
Auf der Festplatte müsste es die folgende Datei sein:
C:\Programme\Gemeinsame Dateien\Borland Shared\MSHelp\guide.hlpWenn die nicht da ist, dann musst du halt nochmal bei der BCB-Installation nachschauen.
Ansonsten findest du das ganze auch Online unter: http://msdn.microsoft.com/library/default.asp
Die Meldung kannst du natürlich unterdrücken. Kannst statt dessen auch eine andere Fehlerbehandlung machen bzw. es auch einfach ignorieren.
Die Hauptsache ist doch, dass die Rechner erscheinen[ Dieser Beitrag wurde am 05.02.2003 um 08:15 Uhr von JeGr editiert. ]
-
@JeGr: schon ganz gut, nur noch ein paar anmerkungen
1. wozu brauchst Du das Handle der Anwendung und ein Handle auf nen Device Context?
[cpp]
BOOL WINAPI ListNetworkComputer(HWND hwnd, HDC hdc, LPNETRESOURCE lpnr)[/cpp]2. warum erst umständlich mit GlobalAlloc Speicher reservieren?
eine einfache Variablen deklaration reicht da vollkommen aus
if (RESOURCEUSAGE_CONTAINER == (NetResource[i].dwUsage & RESOURCEUSAGE_CONTAINER))
ist identisch mit:
if (NetResource[i].dwUsage & RESOURCEUSAGE_CONTAINER)
beispiel: dezimal: 2 == 3 & 2 binär: 010 == 011 & 010 -> 010 == 010 => true doppelt gemoppelt :) dezimal: 3 & 2 binär: 011 & 010 -> 010 => true
-
Danke für die Hinweise!
Das meiste ist hier aber nicht auf meinem Mist gewachsen.
Ich habe den Grossteil (vor allem das mit dem Speicher allokieren) aus der Windows SDK-Hilfe übernommen. Dort wurde das eben so gemacht.Ansonsten war ich froh, dass die Funktion soweit funktioniert hat und da hab ich mich nicht mehr darum gekümmert, das Ganze noch zu optimieren.
Aber falls hier jemand Zeit und sonst nichts bessers vor hat, dann darf er gerne die ganze Sache überarbeiten.
Vielleicht könnte man dies dann auch in die FAQ stellen
-
Ausserdem hat bei einer universellen Lösung eine Zeile wie Form1->RichEdit1->Lines->Add(RemoteName); auch nichts zu suchen. Statt dessen sollte zB. einfach ein Zeiger auf eine StringList als Funktionsparameter übergeben werden:
ListNetworkComputer(TStrings *ResList) { ... ResList->Add(NetResource->lpRemoteName); ... } ... ListNetworkComputer(Memo1->Lines);
Ihr merkt schon, ich suche wieder Freiwillige für einen hübschen FAQ-Beitrag.
-
N'abend.
hab den Code nochmal etwas abgeändert:
Wäre dieser nun FAQ-tauglich?!
//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //=========================================================================== // Funktion ListNetworkComputer //--------------------------------------------------------------------------- // // Ermittelt die Rechnernamen im lokalen Netzwerk. // Ist Win9x kompatibel. //--------------------------------------------------------------------------- // // Parameter: // IN: - TStrings* ComputerList - Liste zum Speichern der Namen // - LPNETRESOURCE Root - Zeige auf NETRESOURCE-Strukur // (wenn NULL, dann werden alle verfügbaren // Ressourcen aufgelistet) // RETURN: BOOL - Flag, ob Funktion erfolgreich //--------------------------------------------------------------------------- // // Aufrufbeispiel: ListNetworkComputer(Memo1->Lines, NULL) // (Listet alle Rechnernamen im lokalen Netzerk in // einem Memo auf) //--------------------------------------------------------------------------- // // Erstellt 05/02/2003 by Jens Gross mit Borland C++ Builder 6 //=========================================================================== BOOL WINAPI ListNetworkComputer(TStrings* ComputerList, LPNETRESOURCE Root) { // Variablendeklaration HANDLE hEnum; // Handle von WNetOpenEnum DWORD Result; // Rückgabewert für WNetXXX DWORD Buffer = 16384; // 16K als Startgrösse DWORD Entries = 0xFFFFFFFF; // liste alle möglichen Einträge LPNETRESOURCE NetResource; // Pointer auf NETRESOURCE // (enthält die gelisteten Einträge) // führe WNetOpenEnum aus, um Auflistung der Netzwerkressourcen // zu beginnen und ermittle den Rückgabewert Result = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_ANY, 0, Root, &hEnum); // wenn Rückgabewert Fehler if(Result != NO_ERROR) { // gib Flag zurück, dass Funktion fehlerhaft return FALSE; } // solange noch Daten vorhanden sind do { // allokiere Speicher für NETRESOURCE-Struktur NetResource = (LPNETRESOURCE)GlobalAlloc(GPTR, Buffer); // führe WNetEnumResource aus, um Auflistung fortzusetzen, // die mit WNetOpenEnum begonnen wurde und ermittle Rückgabewert Result = WNetEnumResource(hEnum, &Entries, NetResource, &Buffer); // wenn Rückgabewert in Ordnung if(Result == NO_ERROR) { // ermittle für alle ermittelten Einträge die Namen for(DWORD i=0; i<Entries; i++) { // wenn ermittelter Eintrag ein Container ist // (z.B. Domäne, Arbeitsgruppe etc) if(RESOURCEUSAGE_CONTAINER == (NetResource[i].dwUsage & RESOURCEUSAGE_CONTAINER)) { // wenn List-Funktion TRUE liefert if(ListNetworkComputer(ComputerList, &NetResource[i])) { // ermittle den Remotenamen AnsiString RemoteName = AnsiString(NetResource[i].lpRemoteName); // wenn Remotename vorhanden und der Name mit \\ beginnt // (\\ deshalb, damit nur Rechner aufgelistet werden und nicht // auch noch die Domänen, Arbeitsgruppen etc) if(RemoteName != "" && RemoteName.SubString(1,2) == "\\\\") { // schreibe Namen in Liste ComputerList->Add(RemoteName); } } } } } // wenn keine weiteren Daten mehr vorliegen else if(Result != ERROR_NO_MORE_ITEMS) { // beende die Schleife break; } } while(Result != ERROR_NO_MORE_ITEMS); // gib den allokierten Speicher wieder frei GlobalFree((HGLOBAL)NetResource); // führe WNetCloseEnum aus, um die Auflistung zu beenden // und ermittle den Rückgabewert Result = WNetCloseEnum(hEnum); // wenn Rückgabewert Fehler if(Result != NO_ERROR) { // gib Flag zurück, dass Funktion fehlerhaft return FALSE; } // gib Flag zurück, dass Funktion erfolgreich return TRUE; } //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { // leere Inhalt von RichEdit RichEdit1->Clear(); // führe List-Funktion aus ListNetworkComputer(RichEdit1->Lines, NULL); } //---------------------------------------------------------------------------
-
kann man hier nicht die else if weglassen. das Result wird doch von der while-schleife abgeprüft!
// wenn keine weiteren Daten mehr vorliegen else if(Result != ERROR_NO_MORE_ITEMS) { // beende die Schleife break; } } while(Result != ERROR_NO_MORE_ITEMS);
naja und wie gesagt:
if (RESOURCEUSAGE_CONTAINER == (NetResource[i].dwUsage & RESOURCEUSAGE_CONTAINER)) // ist identisch mit if(NetResource[i].dwUsage & RESOURCEUSAGE_CONTAINER)
und statt SubString hätte ich vlei mit Pos geprüft (Integervergleich). obwohl... hm.. Pos() muss ja auch erst nach dem String suchen, ist also vielleicht rum wie numm.. ansonsten ab in die FAQ.
-
@Sunday: Meine Frage an dich steht immernoch!
-
Tag WebFritzi, danke hat mir super weitergeholfen.
-
Kein Problem, mach ich doch gerne für dich.