Link to home
Start Free TrialLog in
Avatar of qdyoung
qdyoung

asked on

Browse Windows95 special directory

Followwing code can open Printer directory:
  WinExec('control Printers', sw_ShowNormal);
but How to open Dialup Networking?
Avatar of qdyoung
qdyoung

ASKER

Edited text of question
Hmm. Which dialog do you mean? I'm not sure about that...

Is it one of the folders that are described under winAPI SHGetSpecialFolderLocation?

Regards, Madshi.
Hi qdyoung,

the dialup networking, normally automatically pops up, if you try to make a connection.

You can use the RasDailA function for that...

also look at  http://sme.belgium.eu.net/~vip107/rasdial.zip

Regards, Zif.

please, inform me if this is what you want or not
Avatar of qdyoung

ASKER

Thanks. Sorry for nor clear. Dial-up networking folder is not
one of the folders that are described under winAPI
SHGetSpecialFolderLocation. And I do not need to make a connection.Just need to explore this folder in code, just like this:
ShellExecute(Handle, 'explore', 'C:\', nil, nil, SW_Show);
Of cause, I don't know whether this methord can apply to Dial-up networking folder.



what about looking them up in the registry?
Avatar of qdyoung

ASKER

It do has a GUID {992CFFA0-F557-101A-88EC-00DD010CCC48}.
Also this GUID is a subkey under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\explorer\mycomputer\NameSpace\
I can't tell you in detail how to do it. Here is how you can browse an "PItemIDList" object (here I used SHGetSpecialFolderLocation, because it's the easiest way to get a PItemIDList object):

function ExecutePidl(pidl: PItemIDList) : boolean;
var ei : TShellExecuteInfo;
begin
  zeroMemory(@ei,sizeOf(ei));
  with ei do begin
    cbSize:=SizeOf(ei);
    fMask:=SEE_MASK_FLAG_NO_UI or SEE_MASK_IDLIST;
    WND:=Application.handle;
    lpVerb:='Open';
    lpIDList:=pidl;
    nShow:=SW_SHOWNORMAL;
  end;
  result:=ShellExecuteEx(@ei);
end;

procedure FreePidl(var pidl: PItemIDList);
var malloc : IMalloc;
begin
  if (pidl<>nil) and (SHGetMalloc(malloc)=NOERROR) then begin
    malloc.Free(pidl);
    pidl:=nil;
  end;
end;

function ExecuteSpecialFolderLocation(sfl: cardinal) : boolean;
var pidl : PItemIDList;
begin
  result:=SHGetSpecialFolderLocation(INVALID_HANDLE_VALUE,sfl,pidl)=NOERROR;
  if result then
    try
      ExecutePidl(pidl);
    finally FreePidl(pidl) end;
end;

if ExecuteSpecialFolderLocation(CSIDL_CONTROLS) then messageBox(0,'yes','did it work?',0)
else                                                 messageBox(0,'no', 'did it work?',0);

Of course this doesn't solve your problem, because the Dialup Networking object you want to browse is unfortunately not in the SHGetSpecialFolderLocation objects. Don't know why...  :-(

However, there is definitely a PItemIDList object for the Dialup Networking object. The problem is: How can you get this pidl?

You could enumerate the content of the "MyComputer" object (CSIDL_DRIVES is the SHGetSpecialFolderLocation const for MyComputer). If you want to know how to do this you should look either in the demo sources directory that is being shipped with Delphi4 - if you have Delphi4. Otherwise you could look at this page:
http://members.aye.net/~bstowers/delphi/
There's a component in the beta section called "TSystemTreeView" that does this enumeration stuff and much more.

It's quite complicated, isn't it!?    :-(((

Regards, Madshi.
I've found another interesting possibility. Unfortunately I can't get it to work. Look at the following. If I understand the documentation right, it should work this way, but it doesn't...  :-(
If you find an error, please tell it to me.

var DialupGuid : string = '{992CFFA0-F557-101A-88EC-00DD010CCC48}';

function ExecuteGuid : boolean;
var ei : TShellExecuteInfo;
    s1 : string;
begin
  zeroMemory(@ei,sizeOf(ei));
  with ei do begin
    cbSize:=SizeOf(ei);
    fMask:=SEE_MASK_FLAG_NO_UI or SEE_MASK_CLASSNAME;
    WND:=Application.handle;
    lpClass:=pchar(DialupGuid);
    nShow:=SW_SHOWNORMAL;
  end;
  result:=ShellExecuteEx(@ei);
end;

Regards, Madshi.
I intent to put my cards on qdyoung's comment. Though I think this thread might become very interesting.

Regards,
Williams
Hi Williams, my english is not so well. What does that mean: "I intend to put my cards on qdyoung's comment"?
Thank you...

Regards, Madshi.
ASKER CERTIFIED SOLUTION
Avatar of heathprovost
heathprovost
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
BTW, the "correct" way to do this would be by using the ITEMIDLIST as Madshi pointed out.  However my method will work and is much less complicated.
I found another solution:

procedure TForm1.Button1Click(Sender: TObject);
var
  MyHomeDir, DialUpFolder: String;
begin
  MyHomeDir:=ExtractFilePath(ParamStr(0));
  DialUpFolder:=PChar(MyHomeDir+'Dial-Up Networking.{992CFFA0-F557-101A-88EC-00DD010CCC48}');
  if not DirectoryExists(DialUpFolder) then
    CreateDirectory(PChar(DialUpFolder), nil);  // Unit FileCtrl
  ShellExecute(Handle, 'explore', PChar(DialUpFolder), nil, nil, SW_Show); // Unit ShellApi
//  ShellExecute(Handle, 'open', PChar(DialUpFolder), nil, nil, SW_Show); // Unit ShellApi
end;

I hope that'll help you.
regards, ptm
ptmcomp:  Your code creates a NEW directory in the directory the application started in.  It doesnt open the shell folder for DUN.  It also does not determine if DUN is installed.
Hmm, heathprovost, it works. But please tell me: Where did you learn this strange syntax???

BTW, you could shorten the sources to this:

function ExecuteDialup : boolean;
begin
  result:=WinExec(pchar('C:\WINDOWS\EXPLORER.EXE ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{992CFFA0-F557-101A-88EC-00DD010CCC48}'), SW_SHOWNORMAL)>31;
end;

Since the Guids are the same on every computer on every windows system, you can hardcode them...

ptm, nice hack, but IMHO heathprovost's code (respectively my version of it) it even a little bit nicer...  :-)

Regards, Madshi.
Madshi, I know that the GUIDs are always the same.  The reason I didnt hardcode it is since not everyone has Dialup networking installed, Your code would have failed.  After thinking about it though, I feel stupid.  I should have just hardcoded it and then if the winexec call fails, I could have caught it there.  My mind must be wandering......

As for my strange syntax, at the moment I suffer for a deplorable condition called code confusion.  It occurs whenever you are writing 3 different programs in 3 different languages at the same time. :) lol
qdyoung, you should DEFINITELY do it Madshi's way.  It is much less confusing.

Heath
qdyoung, I would suggest the following change however:

function ExecuteDialup: boolean;
var
  WindowsDir: array [0..255] of char;
  ExplorerCmd: String;
begin
  GetWindowsDirectory(@WIndowsDir, 256);
  ExplorerCmd := String(WindowsDir) + '\' + 'EXPLORER.EXE';
  result:=WinExec(pchar(ExplorerCmd + ' ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{992CFFA0-F557-101A-88EC-00DD010CCC48}'), SW_SHOWNORMAL)>31;  
end;

This way you can be sure that it will work regardless of what directory windows (or windows NT) is installed in.

Heath
Madshi: I ment, that I believe qdyoungs comment was the closest answer to this, I didn't make your code above to work either :-(

Cheers,
Williams
heathprovost,

what about this:

function ExecuteDialup : boolean;
begin
  result:=WinExec(pchar('Explorer ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{992CFFA0-F557-101A-88EC-00DD010CCC48}'), SW_SHOWNORMAL)>31;
end;

Windows finds the explorer for us...  :-)))

With "strange syntax" I didn't mean your style of programming...  :-)
I meant this "::{}\::{}" syntax. I didn't find something like this in my win32.hlp file...

Hmmm. One problem with the shortened code. If the WinExec fails there comes a quite nasty windows error message. So perhaps we should add a second function called "function IsDialupInstalled : boolean" that just checks if the registry key "HKEY_CLASSES_ROOT\CLSID\{992CFFA0-F557-101A-88EC-00DD010CCC48}" exists. What do you think?

Another thing, ptm's code DOES work (I didn't test it, but I'm quite sure). He creates a Dialup directory in his application's root path AND THEN EXECUTES it. That will really open up the Dialup Folder. But nevertheless your code is nicer...

Regards, Madshi.
Williams, aha...   :-)
Madshi, hehe... :-)
Williams, hihi...  :-)
Hmm... madshi your good'n'old hack coder :-), I get an error:

Windows Explorer:
The path ''Explorer ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{992CFFA0-F557-101A-88EC-00DD010CCC48}' does not exist or is not a directory.

Which OS does you run ?

Cheers,
Williams
>>"what about this:

function ExecuteDialup : boolean;
begin
  result:=WinExec(pchar('Explorer ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{992CFFA0-F557-101A-88EC-00DD010CCC48}'), SW_SHOWNORMAL)>31;
end;
What about this"

Much better! :)

>>"With "strange syntax" I didn't mean your style of programming...  :-)
I meant this "::{}\::{}" syntax. I didn't find something like this in my win32.hlp file..."

This stuff is just from observation.  It isnt in the API reference.  If you create a shortcut to DUN and then look at the target in properties, you will see something like this:

C:\WINDOWS\EXPLORER.EXE ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{992CFFA0-F557-101A-88EC-00DD010CCC48}

I just copied the syntax.

>>"Hmmm. One problem with the shortened code. If the WinExec fails there comes a quite nasty windows error message. So perhaps we should add a second function called "function IsDialupInstalled : boolean" that just checks if the registry key "HKEY_CLASSES_ROOT\CLSID\{992CFFA0-F557-101A-88EC-00DD010CCC48}" exists. What do you think?"

I cant test because I have DUN installed and am not going to remove it (it is working and that is enough !)  But if Winexec cause error that is the way to go.

>>"Another thing, ptm's code DOES work (I didn't test it, but I'm quite sure). He creates a Dialup directory in his application's root path AND THEN EXECUTES it. That will really open up the Dialup Folder. But nevertheless your code is nicer..."

On my machine his code makes a folder called 'Dial-Up Networking', but there is nothing in it.  I dont understand how that would be of any help.  

Heath
This is a clearer and better answer and includes Madshi's suggestions:

>>CODE STARTS
unit DUNStuff;

interface

uses
  Windows, Registry;

  function DunIsInstalled: boolean;
  function ExecuteDun : boolean;

const
  DunClassKey = 'CLSID\{992CFFA0-F557-101A-88EC-00DD010CCC48}';
  ExploreDunCmd = 'Explorer ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{992CFFA0-F557-101A-88EC-00DD010CCC48}';

implementation

function DunIsInstalled: boolean;
var
  Reg: TRegistry;
begin
  Reg := TRegistry.Create;
  Reg.RootKey := HKEY_CLASSES_ROOT;
  Result := Reg.KeyExists(DunClassKey);
  Reg.Free;
end;

function ExecuteDun : boolean;
begin
  Result := False;
  if DunIsInstalled then
    Result := WinExec(ExploreDunCmd, SW_SHOWNORMAL) > 31;
end;

end.
>>CODE ENDS

Just include this unit and call ExecuteDun.

Heath


hey great, you guys cleared it. Pitty I wasn't around :-(
Hey Heath, I still can't get your code to work, it just fail on the command DunIsInstalled, but ok, maybe it's because I run Windows NT :-)

But just for the generel interest, I got this hack to work with NT4.0 ..

function TForm1.ExecuteDialup : Boolean;
var
  Reg: TRegistry;
  List: TStringList;
  Res,i: Integer;
  found: Boolean;
  S: String;
  pS: Array[0..MAX_PATH] of Char;
begin
  Result:= False;
  Reg:= TRegistry.Create;
  Reg.Rootkey:= HKEY_LOCAL_MACHINE;
  If Reg.OpenKey('SOFTWARE\Microsoft\Windows\CurrentVersion\explorer\mycomputer\NameSpace',false) then
  begin
    List:= TStringList.Create;
    Reg.GetKeyNames(List);
    i:= 0; found:= False;
    While (i<List.count) and not(found) do
    begin
      If List.Strings[i][1] = '{' then
      If Reg.OpenKey(List.Strings[i],false) then
      Begin
        Try
          found:= Reg.ReadString('') = 'Dial-Up Networking';
        Except
        End;
        Reg.CloseKey;
      End;
      if not(found) then inc(i);
    End;
    Reg.CloseKey;
    If found then
    If Reg.OpenKey('Software\Classes\CLSID\'+List.Strings[i]+'\shell\open\command',false) then
    begin
      S:= Reg.ReadString('');
      i:= pos('%SystemRoot%',S);
      If i>0 then
      Begin
        Delete(S,i,Length('%SystemRoot%'));
        GetWindowsDirectory(pS,MAX_PATH);
        Insert(StrPas(pS),S,i);
      End else
      Begin
        i:= pos('%SystemRoot%',S);
        If i>0 then
        Begin
          Delete(S,i,Length('%SystemRoot%'));
          GetWindowsDirectory(pS,MAX_PATH);
          Insert(StrPas(pS),S,i);
        End else
      End;
      res:=  ShellExecute(Handle,'open',pChar(S),nil,nil,SW_SHOWNORMAL);
      S:= '';
      Case Res of
        0: S:='The operating system is out of memory or resources.';
        ERROR_FILE_NOT_FOUND: S:='The specified file was not found.';
        ERROR_PATH_NOT_FOUND: S:='The specified path was not found.';
        ERROR_BAD_FORMAT: S:='The .EXE file is invalid (non-Win32 .EXE or error in .EXE image).';
        SE_ERR_ACCESSDENIED: S:='Windows 95 only: The operating system denied access to the specified file.';
        SE_ERR_ASSOCINCOMPLETE: S:='The filename association is incomplete or invalid.';
        SE_ERR_DDEBUSY: S:='The DDE transaction could not be completed because other DDE transactions were being processed.';
        SE_ERR_DDEFAIL: S:='The DDE transaction failed.';
        SE_ERR_DDETIMEOUT: S:='The DDE transaction could not be completed because the request timed out.';
        SE_ERR_DLLNOTFOUND: S:='Windows 95 only: The specified dynamic-link library was not found.';
        SE_ERR_NOASSOC: S:='There is no application associated with the given filename extension.';
        SE_ERR_SHARE: S:='A sharing violation occurred.';
      End;
      If S<>'' then
        ShowMessage(S)
      else
        Result:= True;
      Reg.CloseKey;
    End;
    List.free;
  End;
  reg.free;
end;

Regards,
Williams
Ok Williams2, how about this:

unit DUNStuff;

interface

uses
  Windows, Registry;

  function DunIsInstalled: boolean;
  function ExecuteDun : boolean;

const
  DunClassKey = 'SOFTWARE\Microsoft\Windows\CurrentVersion\explorer\mycomputer\NameSpace\{992CFFA0-F557-101A-88EC-00DD010CCC48}';
  ExploreDunCmd = 'Explorer ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{992CFFA0-F557-101A-88EC-00DD010CCC48}';

implementation

function DunIsInstalled: boolean;
var
  Reg: TRegistry;
begin
  Reg := TRegistry.Create;
  Reg.RootKey := HKEY_LOCAL_MACHINE;
  Result := Reg.KeyExists(DunClassKey);
  Reg.Free;
end;

function ExecuteDun : boolean;
begin
  Result := False;
  if DunIsInstalled then
    Result := WinExec(ExploreDunCmd, SW_SHOWNORMAL) > 31;
end;

end.

This will work under NT and 95.  Also a bit simpler than yours. Although your errorcode is more robust, I would personally rather go the simple route.

BTW - This is fun!
By the time we all finish with this one it will consist of 2 lines of assembler...........  :)
hehehehehehehehe :-)
Ahem heathprovost.. It still doesn't work. The keys doesn't exist in my registry. :-( (I though checked it with win98 and it worked fine) But on the other hand my example does not work in my version of windows 98 because the CLSID described as the 'dial-up networking' does not appear to exist anywhere else in the registry (why ?).

But you are right, this IS fun hehe

Cheers,
Williams
OK, this WILL work on both Windows 95 and NT. I PROMISE.

unit DUNStuff;

interface

uses
  Windows, Registry;

  function DunIsInstalled: integer;
  function ExecuteDun : boolean;

const
  Win95DunClassKey = 'CLSID\{992CFFA0-F557-101A-88EC-00DD010CCC48}';
  WinNTDunClassKey = 'CLSID\{a4d92740-67cd-11cf-96f2-00aa00a11dd9}';
  Win95ExploreDunCmd = 'Explorer ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{992CFFA0-F557-101A-88EC-00DD010CCC48}';
  WinNTExploreDunCmd = 'RasPhone.exe';
implementation

function DunIsInstalled: integer;
var
  Reg: TRegistry;
begin
  Result := 0;
  Reg := TRegistry.Create;
  Reg.RootKey := HKEY_CLASSES_ROOT;
  If Reg.KeyExists(Win95DunClassKey) then
    Result := 1;
  If Reg.KeyExists(WinNTDunClassKey) then
    Result := 2;
  Reg.Free;
end;

function ExecuteDun: boolean;
var
  I: integer;
begin
  Result := False;
  I := DunIsInstalled;
  Case I of
    0: exit;
    1: Result := WinExec(Win95ExploreDunCmd, SW_SHOWNORMAL) > 31;
    2: Result := WinExec(WinNTExploreDunCmd, SW_SHOWNORMAL) > 31;
  end;
end;

end.

The reason the other stuff didnt work is because the shell interface of WIndows NT is different.  There is no folder object for DUN under NT.  The object refers back to an executable so the explorer command wont work with its GUID. The above code takes this into account and will work with both (at least currently).  I wont promise forward compatibility since NT's shell interface WILL change in the future (MS already has stated that it will be changed to be more like 98's).

Heath
DAMN!!!!!! I broke it under 95/98. This fixes it FOR BOTH. I really promise this time.

unit DUNStuff;

interface

uses
  Windows, Registry;

  function DunIsInstalled: integer;
  function ExecuteDun : boolean;

const
  Win95DunClassKey = 'CLSID\{992CFFA0-F557-101A-88EC-00DD010CCC48}';
  WinNTDunClassKey = 'CLSID\{a4d92740-67cd-11cf-96f2-00aa00a11dd9}';
  Win95ExploreDunCmd = 'Explorer ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{992CFFA0-F557-101A-88EC-00DD010CCC48}';
  WinNTExploreDunCmd = 'RasPhone.exe';
implementation

function DunIsInstalled: integer;
var
  Reg: TRegistry;
  Version: TOSVersionInfo;
begin
  Result := VER_PLATFORM_WIN32s;
  Reg := TRegistry.Create;
  Reg.RootKey := HKEY_CLASSES_ROOT;
  Version.dwOSVersionInfoSize := SizeOf(Version);
  GetVersionEx(Version);
  if Version.dwPlatformId = VER_PLATFORM_WIN32_NT then
  begin
        If Reg.KeyExists(WinNTDunClassKey) then
          Result := VER_PLATFORM_WIN32_NT;
  end
  else
  begin
        if Version.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS then
              If Reg.KeyExists(Win95DunClassKey) then
                Result := VER_PLATFORM_WIN32_WINDOWS;
  end;
  Reg.Free;
end;

function ExecuteDun: boolean;
var
  I: integer;
begin
  Result := False;
  I := DunIsInstalled;
  Case I of
    VER_PLATFORM_WIN32s: exit;
            VER_PLATFORM_WIN32_NT: Result := WinExec(WinNTExploreDunCmd, SW_SHOWNORMAL) > 31;
    VER_PLATFORM_WIN32_WINDOWS: Result := WinExec(Win95ExploreDunCmd, SW_SHOWNORMAL) > 31;
  end;
end;

end.


It is getting tedious to boot back and forth.......
hahahahaha, I guess you are a bit tired now

Now we are talking, it works allright :-) ..I promise you though I will report back when I install Windows 2000 in a few days hehe :-)

Regards,
Williams
Avatar of qdyoung

ASKER

Oh, so many experts. Maybe this site should add a function so that
I can share points to other participators.

Thanks.

Young