Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

I want to see the "Network Neighborhood"

Posted on 1999-10-19
21
Medium Priority
?
304 Views
Last Modified: 2010-04-04
Hi,
I'm using Delphi 4.0 C/S and Win NT 4.0 Network.

I want to buil a treeview with the network neighborhood in it. My goal is to be able to choose any machine on the network.
I have acheive that with the testbed example I have found on the net (with EE advices). The problems is ...it's much too slow.
The following functions (API) are used in the program :
    - WNetOpenEnum
    - WNetEnumResource
    - WNetCloseEnum

I'm looking for a way to get the N.N. as fast as Explorer.

Do I use the good functions ? (of course not...)
Which function should I use ? Do you know a N.N. Component ?

Any help will be nice,

renam00
0
Comment
Question by:renam00
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
  • 2
  • +7
21 Comments
 
LVL 1

Expert Comment

by:she3i3i
ID: 2139672
I know of a component which does this...

TAHMExplorerTreeView whick comes as part of AHM Triton Tools 2000

Check out http://www.tritontools.com/

There is trialware available for you to play with :)
0
 
LVL 1

Expert Comment

by:she3i3i
ID: 2139676
Hmmm... mind you don't burn your fingers on my previous comment... it's 'which' not 'whick'...
0
 
LVL 20

Expert Comment

by:Madshi
ID: 2139748
I've in mind that the NetServerEnum API was faster, but I'm not sure...

Regards, Madshi.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 12

Expert Comment

by:rwilson032697
ID: 2139933
Listening
0
 
LVL 4

Expert Comment

by:mhervais
ID: 2140333
listening
0
 
LVL 1

Expert Comment

by:yk030299
ID: 2140437
listening
0
 
LVL 6

Expert Comment

by:Jaymol
ID: 2140939
Search on the Delphi Super Page...

    http://ftp.sunet.se/delphi/

for JGNT components.  I use them for all sorts of NT stuff - UserID to FullName, List of domains, list of machines on a domain etc..

John :)
0
 
LVL 10

Expert Comment

by:Lischke
ID: 2141263
Perhaps one could go a totally different way and use the caching mechanism of Explorer by using shell enumeration of the N.N. This would involve COM interfaces though. Interested?

Ciao, Mike
0
 

Author Comment

by:renam00
ID: 2141898
-> Lischke <-
I'm interested by your way...where can I get usefull stuff about the shell enumaration ? Have you any example to suggest ? I'familiar (a little...) with COM interface.
0
 
LVL 10

Expert Comment

by:Lischke
ID: 2142429
Right then... I have never enumerated the N.N. but can give you a complete routine to enumerate IE's history folder which shows all details you need. Don't get confused by the various declartions as I had to make this working for D2 and D3 too.

In order to get the PIDL to N.N. you should use the function GetSpecialFolderLocation instead of the registry access I made here. Once you have the PIDL it is easy to get a shell folder interface for it. This can be asked for an enumeration interface and this one will feed you step by step with all computers.


//------------------------------------------------------------------------------

// The following declarations are taken from D4's ShlObj.pas (IQueryInfo) and VC +  + 6.0 comdef.h (IID_IQueryInfo).
// The IQueryInfo interface is used to get the original tooltip string for the entries in the explorer cache.
// The returned strings are stored as string reference in a node's data member. If this interface is not available
// then the data member remains nil and a default string is used instead.

const IID_IQueryInfo: TGUID = (D1:$00021500; D2:$0000; D3:$0000; D4:($C0, $00, $00, $00, $00, $00, $00, $46));

{$ifndef DFS_COMPILER_4_UP}
const SID_IQueryInfo = '{00021500-0000-0000-C000-000000000046}';

type
  {$ifdef DFS_COMPILER_3_UP}
    IQueryInfo = interface(IUnknown)
      [SID_IQueryInfo]
      function GetInfoTip(dwFlags: DWORD; var ppwszTip: PWideChar): HResult; stdcall;
      function GetInfoFlags(out pdwFlags: DWORD): HResult; stdcall;
    end;
  {$else} // Delphi 2
    IQueryInfo = class(IUnknown)
      function GetInfoTip(dwFlags: DWORD; var ppwszTip: PWideChar): HResult; virtual; stdcall; abstract;
      function GetInfoFlags(var pdwFlags: DWORD): HResult; virtual; stdcall; abstract;
    end;
  {$endif}
 
{$endif}
       
procedure TMainForm.FillTree3;

// fills tree3 with explorer history if available, SHGetSpecialFolderLocation might not work and/or CSIDL_HISTORY
// is not defined, thus I use an alternative way (by registry) to get the history folder

  //------------------------------------------------------------

  function DisplayToString(PIDL: PItemIDList; Display: TStrRet): String;

  begin
    case Display.uType of
      STRRET_CSTR   : SetString(Result, Display.cStr, StrLen(Display.cStr));
      STRRET_WSTR : Result := WideCharToString(Display.pOleStr);
      STRRET_OFFSET : SetString(Result, PChar(PIDL) + Display.uOffset, StrLen(PChar(PIDL) + Display.uOffset));
    end;
  end;

  //------------------------------------------------------------

var WeekNode,
    SiteNode,
    URLNode: TTreeNTNode;
    History: PItemIDList;
    Malloc: IMalloc;
    Folder,
    HistoryFolder,
    WeekFolder,
    SiteFolder: IShellFolder;
    Eaten,
    Attrib: {$ifdef DFS_COMPILER_4_UP}
              Cardinal
            {$else}
              {$ifdef DFS_COMPILER_3_UP}
                Integer
              {$else}
                ULONG
              {$endif}
            {$endif};
    {$ifndef DFS_COMPILER_3_UP}
      Flags: UINT;
    {$endif}
    Key: HKEY;
    Buffer: array[0..4096] of Char;
    AType,
    Size: DWORD;
    {$ifdef DFS_COMPILER_3_UP}
      Name        : WideString;
    {$else}
      Name: String;
      PName: PWideChar;
    {$endif}
    HistoryEnumList,
    WeekEnumList,
    SiteEnumList: IEnumIDList;
    Week,
    Site,
    URL: PItemIDList;
    Fetched: {$ifdef DFS_COMPILER_4_UP}
               Cardinal
             {$else}
               {$ifdef DFS_COMPILER_3_UP}
                 Integer
               {$else}
                 ULONG
               {$endif}
             {$endif};
    Display: TStrRet;
    Icon: IExtractIcon;
    IconLarge,
    WeekIcon,
    SiteIcon,
    URLIcon: HICON;
    Index: Integer;
    TempIcon: TIcon;
    Info: IQueryInfo;
    InfoTip: PWideChar;
    FinalString,
    InfoTipStr: String;

begin
  // get task allocator to handle PIDLs
  SHGetMalloc(Malloc);
  History := nil;
  TempIcon := TIcon.Create;
  Tree3.Items.BeginUpdate;
  try
    // get desktop folder interface
    SHGetDesktopFolder(Folder);
    try
      // determine history folder name
      RegOpenKey(HKEY_CURRENT_USER, 'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders', Key);
      Size := SizeOf(Buffer);
      AType := REG_SZ;
      RegQueryValueEx(Key, 'History', nil, @AType, @Buffer, @Size);
      RegCloseKey(Key);
      // Is there a history folder on this machine?
      if StrLen(Buffer) > 0 then
      begin
        // convert folder path to wide string

        {$ifdef DFS_COMPILER_3_UP}
          Name := Buffer;
          // convert path to pidl
          Folder.ParseDisplayName(Handle, nil, PWideChar(Name), Eaten, History, Attrib);
        {$else}
          PName := StringToOLEStr(Buffer);
          try
            // convert path to pidl
            Folder.ParseDisplayName(Handle, nil, PName, Eaten, History, Attrib);        
          finally
            SysFreeString(PName);
          end;
        {$endif}

        // Are we succesfull?
        if assigned(History) then
        begin
          // get a shell folder to this pidl
          OLECheck(Folder.BindToObject(History, nil, IID_IShellFolder, Pointer(HistoryFolder)));
          try
            // now that we are in the history folder enumerate all site folders and their subitems;
            // we don't use findfirst/findnext here since the history folder does not contain real entries
            // but a binary file which must be parsed
            if Succeeded(HistoryFolder.EnumObjects(Handle, SHCONTF_FOLDERS or SHCONTF_INCLUDEHIDDEN, HistoryEnumList)) then
            begin
              // free dummy content of tree3
              Tree3.Items.Clear;
              SystemImages.Clear;
              WeekIcon := 0;
              SiteIcon := 0;
              URLIcon := 0;
              IconLarge := 0;
              while HistoryEnumList.Next(1, Week, Fetched) = S_OK do
              begin
                // for each subfolder do:
                // get display string as in IE
                HistoryFolder.GetDisplayNameOf(Week, STRRET_CSTR, Display);
                Name := DisplayToString(Week, Display);
                // add a corresponding tree node
                WeekNode := Tree3.Items.Add(nil, Name);
                // try getting the tooltip text
                Info := nil;
                HistoryFolder.GetUIObjectOf(Handle, 1, Week, IID_IQUERYINFO, nil, Pointer(Info));
                // interface available?
                if assigned(Info) then
                begin
                  Info.GetInfoTip(0, InfoTip);
                  // convert wide string to ansi string
                  {$ifdef DFS_COMPILER_3_UP}
                    InfoTipStr := InfoTip;
                  {$else}
                    InfoTipStr := WideCharToString(InfoTip);
                  {$endif}
                  // I'm lazy, let Delphi make the copy
                  WeekNode.Data := StrNew(PChar(InfoTipStr));
                  Malloc.Free(InfoTip);
                end;
                // get icon if not already retrieved
                if WeekIcon = 0 then
                begin
                  HistoryFolder.GetUIObjectOf(Handle, 1, Week, IID_IExtractIconA, nil, Pointer(Icon));
                  if assigned(Icon) then
                  begin
                    {$ifdef DFS_COMPILER_3_UP}
                      if Icon.GetIconLocation(GIL_FORSHELL, Buffer, SizeOf(Buffer), Index, Attrib) = NOERROR then
                      begin
                        if (Attrib and GIL_NOTFILENAME) <> 0
                    {$else}
                      if Icon.GetIconLocation(GIL_FORSHELL, Buffer, SizeOf(Buffer), Index, Flags) = NOERROR then
                      begin
                        if (Flags and GIL_NOTFILENAME) <> 0
                    {$endif}
                                                           then Icon.Extract(Buffer, Index, IconLarge, WeekIcon, MakeLParam(16, 16))
                                                           else ExtractIconEx(Buffer, Index, IconLarge, WeekIcon, 1);

                      ImageList_AddIcon(SystemImages.Handle, WeekIcon);
                      DestroyIcon(WeekIcon);
                    end
                    else WeekIcon := HICON(-1);
                  end
                  else WeekIcon := HICON(-1);
                end;
                WeekNode.ImageIndex := 0;
                WeekNode.SelectedIndex := 0;
                WeekNode.Color := clBtnFace;
                WeekNode.Font.Color := clBlack;

                // for each week entry get it's site entries
                OLECheck(HistoryFolder.BindToObject(Week, nil, IID_IShellFolder, Pointer(WeekFolder)));
                try
                  if Succeeded(WeekFolder.EnumObjects(Handle, SHCONTF_FOLDERS or SHCONTF_INCLUDEHIDDEN, WeekEnumList)) then
                  begin
                    while WeekEnumList.Next(1, Site, Fetched) = S_OK do
                    begin
                      // for each subfolder do:
                      // get display string as in IE
                      WeekFolder.GetDisplayNameOf(Site, STRRET_CSTR, Display);
                      // add a corresponding tree node
                      SiteNode := Tree3.Items.AddChild(WeekNode, DisplayToString(Site, Display));
                      // try getting the tooltip text
                      Info := nil;
                      WeekFolder.GetUIObjectOf(Handle, 1, Site, IID_IQUERYINFO, nil, Pointer(Info));
                      // interface available?
                      if assigned(Info) then
                      begin
                        Info.GetInfoTip(0, InfoTip);
                        // convert wide string to ansi string
                        {$ifdef DFS_COMPILER_3_UP}
                          InfoTipStr := InfoTip;
                        {$else}
                          InfoTipStr := WideCharToString(InfoTip);
                        {$endif}
                        // I'm lazy, let Delphi make the copy
                        SiteNode.Data := StrNew(PChar(InfoTipStr));
                        Malloc.Free(InfoTip);
                      end;
                      // get icon if not already retrieved
                      if SiteIcon = 0 then
                      begin
                        WeekFolder.GetUIObjectOf(Handle, 1, Site, IID_IExtractIconA, nil, Pointer(Icon));
                        if assigned(Icon) then
                        begin
                          IconLarge := 0;
                          {$ifdef DFS_COMPILER_3_UP}
                            if Icon.GetIconLocation(GIL_FORSHELL, Buffer, SizeOf(Buffer), Index, Attrib) = NOERROR then
                            begin
                              if (Attrib and GIL_NOTFILENAME) <> 0
                          {$else}
                            if Icon.GetIconLocation(GIL_FORSHELL, Buffer, SizeOf(Buffer), Index, Flags) = NOERROR then
                            begin
                              if (Flags and GIL_NOTFILENAME) <> 0
                          {$endif}
                                                                 then Icon.Extract(Buffer, Index, IconLarge, SiteIcon, MakeLParam(16, 16))
                                                                 else ExtractIconEx(Buffer, Index, IconLarge, SiteIcon, 1);

                            ImageList_AddIcon(SystemImages.Handle, SiteIcon);
                            DestroyIcon(SiteIcon);
                          end
                          else SiteIcon := HICON(-1);
                        end
                        else SiteIcon := HICON(-1);
                      end;
                      SiteNode.ImageIndex := 1;
                      SiteNode.SelectedIndex := 1;
                      SiteNode.Color := clBtnHighlight;
                      SiteNode.Font.Color := clBlack;

                      // for each site entry get it's URL entries
                      OLECheck(WeekFolder.BindToObject(Site, nil, IID_IShellFolder, Pointer(SiteFolder)));
                      try
                        if Succeeded(SiteFolder.EnumObjects(Handle, SHCONTF_NONFOLDERS or SHCONTF_INCLUDEHIDDEN, SiteEnumList)) then
                        begin
                          while SiteEnumList.Next(1, URL, Fetched) = S_OK do
                          begin
                            // for each item do:
                            // get display string as in IE, URLs are differently shown than the other nodes and since
                            // I want to show the tree exactly like IE I have to model the same behaviour

                            // try getting the tooltip text
                            Info := nil;
                            InfoTip := nil;
                            SiteFolder.GetUIObjectOf(Handle, 1, URL, IID_IQUERYINFO, nil, Pointer(Info));
                            // interface available?
                            if assigned(Info) then Info.GetInfoTip(0, InfoTip);

                            if assigned(InfoTip) then
                            begin
                              // convert wide string to ansi string
                              {$ifdef DFS_COMPILER_3_UP}
                                InfoTipStr := InfoTip;
                              {$else}
                                InfoTipStr := WideCharToString(InfoTip);
                              {$endif}
                              Malloc.Free(InfoTip);
                            end
                            else
                            begin
                              SiteFolder.GetDisplayNameOf(URL, STRRET_CSTR, Display);
                              InfoTipStr := DisplayToString(URL, Display);
                            end;

                            // find first line break
                            Size := Pos(#13, InfoTipStr);
                            if Size = 0 then FinalString := InfoTipStr
                                        else
                              if InfoTipStr[Size - 1] = #10 then FinalString := Copy(InfoTipStr, 1, Size - 2)
                                                            else FinalString := Copy(InfoTipStr, 1, Size - 1);

                            // now shorten the string until it fits into the client area, DisplayRect doesn't work
                            // here, since the node hasn't been displayed yet
                            Size := Tree3.Canvas.TextWidth(FinalString);
                            // we are on level 2, hence add the indentation plus some extra space for
                            // level 0 icon and offset
                            if Size + 2 * Tree3.Indent + 40 > Tree3.ClientWidth then
                            begin
                              while Size + 2 * Tree3.Indent + 40 > Tree3.ClientWidth do
                              begin
                                Delete(FinalString, Length(FinalString), 1);
                                Size := Tree3.Canvas.TextWidth(FinalString + '...');
                              end;
                              // add a corresponding tree node
                              URLNode := Tree3.Items.AddChild(SiteNode, FinalString + '...');
                            end
                            else URLNode := Tree3.Items.AddChild(SiteNode, FinalString);
                            // finally make a copy of the entire display string for the tooltip
                            URLNode.Data := StrNew(PChar(InfoTipStr));

                            // get icon if not already retrieved
                            if URLIcon = 0 then
                            begin
                              SiteFolder.GetUIObjectOf(Handle, 1, URL, IID_IExtractIconA, nil, Pointer(Icon));
                              if assigned(Icon) then
                              begin
                                IconLarge := 0;
                                {$ifdef DFS_COMPILER_3_UP}
                                  if Icon.GetIconLocation(GIL_FORSHELL, Buffer, SizeOf(Buffer), Index, Attrib) = NOERROR then
                                  begin
                                    if (Attrib and GIL_NOTFILENAME) <> 0
                                {$else}
                                  if Icon.GetIconLocation(GIL_FORSHELL, Buffer, SizeOf(Buffer), Index, Flags) = NOERROR then
                                  begin
                                    if (Flags and GIL_NOTFILENAME) <> 0
                                {$endif}
                                                                       then Icon.Extract(Buffer, Index, IconLarge, URLIcon, MakeLParam(16, 16))
                                                                       else ExtractIconEx(Buffer, Index, IconLarge, URLIcon, 1);

                                  ImageList_AddIcon(SystemImages.Handle, URLIcon);
                                  DestroyIcon(URLIcon);
                                end
                                else URLIcon := HICON(-1);
                              end
                              else URLIcon := HICON(-1);
                            end;
                            URLNode.ImageIndex := 2;
                            URLNode.SelectedIndex := 2;
                            URLNode.Color := clBtnHighlight;
                            URLNode.Font.Color := clBlack;
                            Malloc.Free(URL);
                          end;
                          SiteNode.AlphaSort;
                          {$ifdef DFS_COMPILER_2} SiteEnumList.Release; {$endif}
                        end;
                      finally
                        // here we need an explicit release, since we are going to use this interface several times
                        SiteFolder := nil;
                      end;

                      // finally free current week entry
                      Malloc.Free(Site);
                    end;
                    WeekNode.AlphaSort;
                    {$ifdef DFS_COMPILER_2} WeekEnumList.Release; {$endif}
                  end;
                finally
                  // here we need an explicit release, since we are going to use this interface several times
                  WeekFolder := nil;
                end;
                // finally free current week entry
                Malloc.Free(Week);
              end;
            end;
          finally
            {$ifdef DFS_COMPILER_2}
              HistoryFolder.Release;
            {$endif}
          end;
        end;
      end;
    finally
      {$ifdef DFS_COMPILER_2}
        Folder.Release;
      {$endif}
    end;
  finally
    Malloc.Free(History);
    {$ifdef DFS_COMPILER_2}
      Malloc.Release;
    {$endif}
    TempIcon.Free;
    Tree3.Items.EndUpdate;
  end;
end;

//------------------------------------------------------------------------------



Ciao, Mike
0
 
LVL 3

Expert Comment

by:bryan7
ID: 2143500
listenning
0
 

Author Comment

by:renam00
ID: 2143518
OK everybody, the stupid question of the day :

    Why people send "listening" messages ?

s'cuser la
0
 
LVL 20

Expert Comment

by:Madshi
ID: 2143541
Because, if you write a comment to a question, you can lateron review the question without any cost. If you don't write a comment, you'll have to buy the question lateron if you want to see the accepted answer...   :-)
0
 

Author Comment

by:renam00
ID: 2143562
Thanks !!
0
 
LVL 10

Expert Comment

by:Lischke
ID: 2156376
renam00,

how is it going? May I propose an answer?

Ciao, Mike
0
 

Author Comment

by:renam00
ID: 2156416
->Lischke<-
Go for it ...
I solve my problem. I found an (almost) component that query the [explorer]Shell.
I think that's what the code you post is doing too...anyway I took code from a sample I found on the net (I'm lazy...) but your advices where right.

So feel free to submit an answer and thanks again.

renam00
0
 
LVL 10

Accepted Solution

by:
Lischke earned 600 total points
ID: 2158088
I'm pleased to hear that. I'm sure my code and explanation will be of use for you sometimes later... :-)

Ciao, Mike
0
 
LVL 4

Expert Comment

by:mhervais
ID: 2158453
what component renam00 ?
0
 

Author Comment

by:renam00
ID: 2159790
the "component" (it's a unit in fact...) is call TFolderDialog. The sad new is I can't remember where I found it (I've downloaded  a lot of stuff lately) sorry...
0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 2160654
I'm pretty sure I have seen TFolderDialog on DSP... (http://sunsite.ecm.edu.pl/delphi

Cheers,

Raymond.
0
 
LVL 1

Expert Comment

by:Fraction
ID: 2719575
listening
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
In this video you will find out how to export Office 365 mailboxes using the built in eDiscovery tool. Bear in mind that although this method might be useful in some cases, using PST files as Office 365 backup is troublesome in a long run (more on t…
Have you created a query with information for a calendar? ... and then, abra-cadabra, the calendar is done?! I am going to show you how to make that happen. Visualize your data!  ... really see it To use the code to create a calendar from a q…
Suggested Courses

715 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question