Gelöst! Wie "echte Verzeichnisse" von "Links" unterscheiden?

Anfängerfragen zum Programmieren mit PureBasic.
EmmJott
Beiträge: 39
Registriert: 25.10.2024 12:23

Gelöst! Wie "echte Verzeichnisse" von "Links" unterscheiden?

Beitrag von EmmJott »

Guude Morsche aus Hessen!

Folgendes Problem:ExplorerTreeGadget zeigt u. a. im User-Verzeichnis das Verzeichnis "Startmenü" an. Mit ExamineDirectory finde ich darin keine Einträge. Meine laienhafte Vermutung: Richtig so, denn das ist gar kein Verzeichnis, sondern ein Link zu einem Verzeichnis, nämlich User\Appdata\Microsoft\usw. Leider zeigt aber auch Filesize mit "-2", dass das ein Verzeichnis ist.

Kann man mit Purebasic "echte Verzeichnisse" von "Link auf Verzeichnis" unterscheiden und wenn ja, wie findet man das Zielverzeichnis?

Nachtrag: Auf DOS-Ebene geht das mit "dir /al" - irgendwie muss es also gehen.
Zuletzt geändert von EmmJott am 15.05.2025 16:55, insgesamt 1-mal geändert.
Bin aktiv in der rentenvorbereitenden Arbeitslosigkeit - zwangsweise. Auch nach >30 Jahren im Betrieb springst Du über die Klinge, wenn der (Miss-)Manager seinen Hintern retten will. Lasst Euch von euren Arbeitgebern bloß nix von wegen Loyalität erzählen - wenn's drauf ankommt, ist die nix Wert!
Benutzeravatar
Bisonte
Beiträge: 2465
Registriert: 01.04.2007 20:18

Re: Wie "echte Verzeichnisse" von "Links" unterscheiden?

Beitrag von Bisonte »

das sind dann die sogenannten "Systemverzeichnisse"... es gibt hier im Forum diverse Möglichkeiten die richtigen Pfade zu ermitteln... wie z.B. im englischen Forum https://www.purebasic.fr/english/viewtopic.php?t=82092 weiter unten von Jan2004 oder das was ich grad nicht wiederfinde was TassyJim dort meint.
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
EmmJott
Beiträge: 39
Registriert: 25.10.2024 12:23

Re: Wie "echte Verzeichnisse" von "Links" unterscheiden?

Beitrag von EmmJott »

Hi,

vielen Dank für den Hinweis! Ja, das geht wohl in diese Richtung. Schaue mir gerade das hier an:
https://www.purebasic.fr/english/viewto ... 70#p604570

Das würde schon mal meine 2. Frage beantworten, nämlich die nach dem Zielverzeichnis. Habe aber noch das Problem: Wie unterscheide ich ein "echtes Verzeichnis" (mir fehlt der Fachbegriff) von einem Link, für den das Zielverzeichnis erst noch ermittelt werden muss (mittels Code von Jan2004).
Bin aktiv in der rentenvorbereitenden Arbeitslosigkeit - zwangsweise. Auch nach >30 Jahren im Betrieb springst Du über die Klinge, wenn der (Miss-)Manager seinen Hintern retten will. Lasst Euch von euren Arbeitgebern bloß nix von wegen Loyalität erzählen - wenn's drauf ankommt, ist die nix Wert!
Benutzeravatar
Bisonte
Beiträge: 2465
Registriert: 01.04.2007 20:18

Re: Wie "echte Verzeichnisse" von "Links" unterscheiden?

Beitrag von Bisonte »

EmmJott hat geschrieben: 14.05.2025 22:09 ... Habe aber noch das Problem: Wie unterscheide ich ein "echtes Verzeichnis" (mir fehlt der Fachbegriff) von einem Link, für den das Zielverzeichnis erst noch ermittelt werden muss (mittels Code von Jan2004).
Ich wüsste nicht, dass es dafür eine Möglichkeit gibt, es per Programm zu "erkennen".
Die Frage hat sich mir nie gestellt, eher die Frage, wie krieg ich den Pfad raus...

Im Grunde kannst du davon ausgehen, das ALLES, was von Windows kommt, mit solchen "relativen" Pfaden arbeitet,
Window kann ja schliesslich auf jedem Laufwerk installiert werden... nicht nur C:
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
EmmJott
Beiträge: 39
Registriert: 25.10.2024 12:23

Re: Wie "echte Verzeichnisse" von "Links" unterscheiden?

Beitrag von EmmJott »

Bin da ja vielleicht auf dem Holzweg, habe aber mal mit den Konstanten aus
https://learn.microsoft.com/de-de/windo ... -constants
rumgespielt.

Bei den Verzeichnissen, die offenbar nur Symlinks sind und auf ein Zielverzeichnis verweisen, tauchen die Attribute
#FILE_ATTRIBUTE_REPARSE_POINT und #FILE_ATTRIBUTE_NOT_CONTENT_INDEXED auf. Hiermit ermittelt:

Code: Alles auswählen


Enumeration  
  #parent
  #parentstatusbar
  #parentmenu
  #parentfont_1
  #escape 
  #etg
EndEnumeration

;- Konstanten

#FILE_ATTRIBUTE_READONLY = $00000001                    ;#PB_FileSystem_ReadOnly
#FILE_ATTRIBUTE_HIDDEN = $00000002                      ;#PB_FileSystem_Hidden
#FILE_ATTRIBUTE_SYSTEM = $00000004                      ;#PB_FileSystem_System

#FILE_ATTRIBUTE_DIRECTORY = $00000010
#FILE_ATTRIBUTE_ARCHIVE = $00000020                     ;#PB_FileSystem_Archive
#FILE_ATTRIBUTE_DEVICE = $00000040
#FILE_ATTRIBUTE_NORMAL = $00000080                      ;#PB_FileSystem_Normal
#FILE_ATTRIBUTE_TEMPORARY = $00000100
#FILE_ATTRIBUTE_SPARSE_FILE = $00000200
#FILE_ATTRIBUTE_REPARSE_POINT = $00000400
#FILE_ATTRIBUTE_COMPRESSED = $00000800                  ;#PB_FileSystem_Compressed
#FILE_ATTRIBUTE_OFFLINE = $00001000
#FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = $00002000
#FILE_ATTRIBUTE_ENCRYPTED = $00004000
#FILE_ATTRIBUTE_INTEGRITY_STREAM = $00008000
#FILE_ATTRIBUTE_VIRTUAL = $00010000
#FILE_ATTRIBUTE_NO_SCRUB_DATA = $00020000
#FILE_ATTRIBUTE_EA = $00040000
#FILE_ATTRIBUTE_RECALL_ON_OPEN = $00040000             ;gleicher Wert wie #FILE_ATTRIBUTE_EA ?
#FILE_ATTRIBUTE_PINNED = $00080000
#FILE_ATTRIBUTE_UNPINNED = $00100000

#FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS = $00400000

Procedure checkDirAttr(dir$)
  Value = GetFileAttributes(dir$) 
  Debug dir$
  If Value = -1 
    Debug "Fehler beim Lesen der Attribute!"
  Else     
    If Value & #FILE_ATTRIBUTE_READONLY : Debug "#FILE_ATTRIBUTE_READONLY" : EndIf
    If Value & #FILE_ATTRIBUTE_HIDDEN : Debug "#FILE_ATTRIBUTE_HIDDEN" : EndIf
    If Value & #FILE_ATTRIBUTE_SYSTEM : Debug "#FILE_ATTRIBUTE_SYSTEM" : EndIf
    
    If Value & #FILE_ATTRIBUTE_DIRECTORY : Debug "#FILE_ATTRIBUTE_DIRECTORY" : EndIf
    If Value & #FILE_ATTRIBUTE_ARCHIVE : Debug "#FILE_ATTRIBUTE_ARCHIVE" : EndIf
    If Value & #FILE_ATTRIBUTE_DEVICE : Debug "#FILE_ATTRIBUTE_DEVICE" : EndIf
    If Value & #FILE_ATTRIBUTE_NORMAL : Debug "#FILE_ATTRIBUTE_NORMAL" : EndIf
    If Value & #FILE_ATTRIBUTE_TEMPORARY : Debug "#FILE_ATTRIBUTE_TEMPORARY" : EndIf
    If Value & #FILE_ATTRIBUTE_SPARSE_FILE : Debug "#FILE_ATTRIBUTE_SPARSE_FILE" : EndIf
    If Value & #FILE_ATTRIBUTE_REPARSE_POINT : Debug "#FILE_ATTRIBUTE_REPARSE_POINT" : EndIf
    If Value & #FILE_ATTRIBUTE_COMPRESSED : Debug "#FILE_ATTRIBUTE_COMPRESSED" : EndIf
    If Value & #FILE_ATTRIBUTE_OFFLINE : Debug "#FILE_ATTRIBUTE_OFFLINE" : EndIf
    If Value & #FILE_ATTRIBUTE_NOT_CONTENT_INDEXED : Debug "#FILE_ATTRIBUTE_NOT_CONTENT_INDEXED" : EndIf
    If Value & #FILE_ATTRIBUTE_ENCRYPTED : Debug "#FILE_ATTRIBUTE_ENCRYPTED" : EndIf
    If Value & #FILE_ATTRIBUTE_INTEGRITY_STREAM : Debug "#FILE_ATTRIBUTE_INTEGRITY_STREAM" : EndIf
    If Value & #FILE_ATTRIBUTE_VIRTUAL : Debug "#FILE_ATTRIBUTE_VIRTUAL" : EndIf
    If Value & #FILE_ATTRIBUTE_NO_SCRUB_DATA : Debug "#FILE_ATTRIBUTE_NO_SCRUB_DATA" : EndIf
    If Value & #FILE_ATTRIBUTE_EA : Debug "#FILE_ATTRIBUTE_EA" : EndIf
    If Value & #FILE_ATTRIBUTE_RECALL_ON_OPEN : Debug "#FILE_ATTRIBUTE_RECALL_ON_OPEN" : EndIf
    If Value & #FILE_ATTRIBUTE_PINNED : Debug "#FILE_ATTRIBUTE_PINNED" : EndIf
    If Value & #FILE_ATTRIBUTE_UNPINNED : Debug "#FILE_ATTRIBUTE_UNPINNED" : EndIf
    
    If Value & #FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS : Debug "#FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS" : EndIf     
  EndIf
  Debug "----------------------"
  Debug " "   
  ; Werte aus: https://learn.microsoft.com/de-de/windows/win32/fileio/file-attribute-constants
EndProcedure

;GetParentWinMetrics
Global winwidth, winheight
Procedure GetParentWinMetrics()
  winwidth = WindowWidth(#parent)
  winheight = WindowHeight(#parent)
  If IsMenu(#parentmenu) : winheight - MenuHeight() : EndIf
  If IsStatusBar(#parentstatusbar) : winheight - StatusBarHeight(#parentstatusbar) : EndIf  
EndProcedure

Procedure UpdateGadgets()
  GetParentWinMetrics()
  ResizeGadget(#etg,0,0,winwidth,winheight)
EndProcedure

Procedure UpdateWindow()
  dx = WindowWidth(#parent)
  dy = WindowHeight(#parent)
  If dx % 2 : dx + 1 : EndIf
  If dy % 2 : dy + 1 : EndIf
  ResizeWindow(#parent,#PB_Ignore,#PB_Ignore,dx,dy)  
  UpdateGadgets()
EndProcedure

;- openwindow
#parentflags = #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered
OpenWindow(#parent, 0, 0, 1000, 700, "", #parentflags)
LoadFont(#parentfont_1, "Calibri", 11) : SetGadgetFont(#PB_Default, FontID(#parentfont_1))

;- Shortcuts
AddKeyboardShortcut(0, #PB_Shortcut_Escape, #escape)

;- Statusbar
If CreateStatusBar(#parentstatusbar, WindowID(#parent))
  AddStatusBarField(#PB_Ignore)  
EndIf

If IsMenu(#parentmenu)
  WindowBounds(#parent, 220, MenuHeight(), #PB_Ignore, #PB_Ignore)
Else
  WindowBounds(#parent, 220, 0, #PB_Ignore, #PB_Ignore)
EndIf

;- Programmcode -----------------------------------
;winwidth, winheight
GetParentWinMetrics()

ExplorerTreeGadget(#etg,0,0,winwidth,winheight,GetUserDirectory(#PB_Directory_Documents))



; BindEvents
BindEvent(#PB_Event_SizeWindow, @UpdateWindow(), #parent)

;- Eventschleife

Repeat
  Event = WindowEvent()
  Gadget = EventGadget()
  
  Select Event
    Case #PB_Event_CloseWindow
      Select EventWindow()
        Case #parent
          Break
      EndSelect
  EndSelect
  
  Select Gadget
    Case #etg
      Select EventType()
        Case #PB_EventType_Change
          checkDirAttr(GetGadgetText(Gadget))
        Case #PB_EventType_LeftClick
        Case #PB_EventType_LeftDoubleClick
        Case #PB_EventType_RightClick              
        Case #PB_EventType_RightDoubleClick
      EndSelect
      
  EndSelect
  
ForEver

End
Meine Frage: Bin ich da komplett auf der falschen Fährte oder kann jemand bestätigen, dass mit #FILE_ATTRIBUTE_REPARSE_POINT und / oder #FILE_ATTRIBUTE_NOT_CONTENT_INDEXED ein Symlink sicher erkannt und eine Unterscheidung zu einem "echten " Verzeichnis sicher funktioniert? Reicht eines der beiden Attribute (welches?) oder müssen beide vorhanden sein?
Bin aktiv in der rentenvorbereitenden Arbeitslosigkeit - zwangsweise. Auch nach >30 Jahren im Betrieb springst Du über die Klinge, wenn der (Miss-)Manager seinen Hintern retten will. Lasst Euch von euren Arbeitgebern bloß nix von wegen Loyalität erzählen - wenn's drauf ankommt, ist die nix Wert!
Benutzeravatar
HeX0R
Beiträge: 3040
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Re: Wie "echte Verzeichnisse" von "Links" unterscheiden?

Beitrag von HeX0R »

Laut MSDN ist #FILE_ATTRIBUTE_REPARSE_POINT zumindest ein Teil der Lösung.
EmmJott
Beiträge: 39
Registriert: 25.10.2024 12:23

Re: Wie "echte Verzeichnisse" von "Links" unterscheiden?

Beitrag von EmmJott »

Noch kurz, bevor ich mich auf's Fahrrad schwinge, um das schöne Wetter auszunutzen:

Ja, sieht so aus, dass mit dem Attribut #FILE_ATTRIBUTE_REPARSE_POINT ein "echtes Verzeichnis" von einem Link zu unterscheiden ist. Um das eigentliche Zielverzeichnis zu finden, gibt es zwei Wege:
a) eine Procedure zu entwickeln, die mittels API-Funktionen und Strukturen und sonstigen Betriebssysteminterna den Pfad ausspuckt - bei Weitem zu hoch für mich
b) FSUTIL verwenden, z. B. so:

Code: Alles auswählen

fsutil reparsepoint query "C:\Users\{username}\Startmenü"
ohne abschließenden "\".

Wenn mir jemand so eine elegante procedure schreiben könnte, wäre traumhaft, ansonsten würde ich mit runprogram eine Temp-Datei erzeugen, die entsprechende Zeile auslesen und die Temp-Datei wieder löschen.
Bin aktiv in der rentenvorbereitenden Arbeitslosigkeit - zwangsweise. Auch nach >30 Jahren im Betrieb springst Du über die Klinge, wenn der (Miss-)Manager seinen Hintern retten will. Lasst Euch von euren Arbeitgebern bloß nix von wegen Loyalität erzählen - wenn's drauf ankommt, ist die nix Wert!
DePe
Beiträge: 194
Registriert: 26.11.2017 16:17

Re: Wie "echte Verzeichnisse" von "Links" unterscheiden?

Beitrag von DePe »

Es gibt hier einen alten Code von freak der passen könnte:
https://www.purebasic.fr/english/viewto ... 2&t=370284

Edit: Der Code funktioniert ohne Änderung unter Windows 7 mit PB v6.21b9 32/64.

Peter
Axolotl
Beiträge: 265
Registriert: 31.12.2008 16:34

Re: Wie "echte Verzeichnisse" von "Links" unterscheiden?

Beitrag von Axolotl »

@DePe, der Link scheint nicht zu funktionieren.....
@EmmJott, du kannst mit RunProgram() das Ergebnis von "dir /a [C:\...]" auswerten. Bevor man sich mit API quält. Anbei noch ein Blog-Beitrag für eine Lösung in C. (Sorry, aber ich habe keine Zeit (Lust) das umzuschreiben.)

Weitere Suche ergab das hier. Nicht getestet.
Using PureBasic latest stable version and current alpha/beta (x64) on Windows 11 Home
DePe
Beiträge: 194
Registriert: 26.11.2017 16:17

Re: Wie "echte Verzeichnisse" von "Links" unterscheiden?

Beitrag von DePe »

Hallo Axolotl,

vielleicht funktioniert der Link so:
https://www.purebasic.fr/english/viewtopic.php?p=282633

Peter

Anbei der unveränderte Code von freak:

Code: Alles auswählen

; WinIoCtl.h
;
#FILE_DEVICE_FILE_SYSTEM         = $00000009
#METHOD_BUFFERED                 = 0
#FILE_ANY_ACCESS                 = 0
#FILE_SPECIAL_ACCESS             = (#FILE_ANY_ACCESS)

Macro CTL_CODE( DeviceType, Function, Method, Access )
  (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
EndMacro

#FSCTL_SET_REPARSE_POINT         = CTL_CODE(#FILE_DEVICE_FILE_SYSTEM, 41, #METHOD_BUFFERED, #FILE_SPECIAL_ACCESS)
#FSCTL_GET_REPARSE_POINT         = CTL_CODE(#FILE_DEVICE_FILE_SYSTEM, 42, #METHOD_BUFFERED, #FILE_ANY_ACCESS)
#FSCTL_DELETE_REPARSE_POINT      = CTL_CODE(#FILE_DEVICE_FILE_SYSTEM, 43, #METHOD_BUFFERED, #FILE_SPECIAL_ACCESS)

; Winbase.h
;
#FILE_FLAG_OPEN_REPARSE_POINT    = $00200000

; WinNT.h
;
#IO_REPARSE_TAG_MOUNT_POINT  = $A0000003       
#IO_REPARSE_TAG_HSM          = $C0000004       
#IO_REPARSE_TAG_HSM2         = $80000006       
#IO_REPARSE_TAG_SIS          = $80000007       
#IO_REPARSE_TAG_DFS          = $8000000A       
#IO_REPARSE_TAG_SYMLINK      = $A000000C       
#IO_REPARSE_TAG_DFSR         = $80000012


; From Windows Driver Kit.
; http://msdn.microsoft.com/en-us/library/ms791514.aspx
;
Structure SymbolicLinkReparseBuffer
  SubstituteNameOffset.w
  SubstituteNameLength.w
  PrintNameOffset.w
  PrintNameLength.w
  Flags.l
  PathBuffer.w[1]
EndStructure

Structure MountPointReparseBuffer
  SubstituteNameOffset.w
  SubstituteNameLength.w
  PrintNameOffset.w
  PrintNameLength.w
  PathBuffer.w[1]
EndStructure

Structure GenericReparseBuffer
  DataBuffer.b[1]
EndStructure

Structure REPARSE_DATA_BUFFER
  ReparseTag.l
  ReparseDataLength.w
  Reserved.w
  StructureUnion
    SymbolicLinkReparseBuffer.SymbolicLinkReparseBuffer
    MountPointReparseBuffer.MountPointReparseBuffer
    GenericReparseBuffer.GenericReparseBuffer
  EndStructureUnion
EndStructure




; Tries to follow a directory link on Windows Vista (should also work for files)
;
; - If the directory is no link, the result is the original directory
; - If the target cannot be read, the result is ""
;
Procedure.s GetDirectoryTarget(Directory$)
  Protected TokenHandle, BufferSize, hDirectory, BytesReturned.l
  Protected Privileges.TOKEN_PRIVILEGES
  Protected *Buffer.REPARSE_DATA_BUFFER
  Protected Result$ = ""

  ; Check if the directory is a reparse point (link or mount point)
  ;
  If GetFileAttributes_(@Directory$) & #FILE_ATTRIBUTE_REPARSE_POINT

    ; The backup privilege is required to open a directory for io queries
    ; So try to set it on our process token. (usually it should be set already)
    ;
    If OpenProcessToken_(GetCurrentProcess_(), #TOKEN_ADJUST_PRIVILEGES, @TokenHandle)
      Privileges\PrivilegeCount = 1
      Privileges\Privileges[0]\Attributes = #SE_PRIVILEGE_ENABLED
    
      If LookupPrivilegeValue_(#Null, @"SeBackupPrivilege", @Privileges\Privileges[0]\Luid)       
        AdjustTokenPrivileges_(TokenHandle, #False, @Privileges, SizeOf(TOKEN_PRIVILEGES), #Null, #Null)
      EndIf    
      CloseHandle_(TokenHandle)
    EndIf
    
    ; Open the directory
    ;   Have to pass 0 as access right (not #GENERIC_READ), as it fails otherwise
    ;   http://www.codeproject.com/KB/vista/Windows_Vista.aspx
    ;
    hDirectory = CreateFile_(@Directory$, 0, #FILE_SHARE_READ|#FILE_SHARE_WRITE, #Null, #OPEN_EXISTING, #FILE_FLAG_OPEN_REPARSE_POINT | #FILE_FLAG_BACKUP_SEMANTICS, #Null)
    If hDirectory <> #INVALID_HANDLE_VALUE
    
      ; Allocate a buffer for the io query. 1000 bytes should be enough for the real path (in unicode)
      ;
      BufferSize = SizeOf(REPARSE_DATA_BUFFER) + 1000
      *Buffer = AllocateMemory(BufferSize)
      
      If *Buffer
        
        ; Query the directory for reparse point information
        ;
        If DeviceIoControl_(hDirectory, #FSCTL_GET_REPARSE_POINT, #Null, 0, *Buffer, BufferSize, @BytesReturned, #Null) <> 0
        
          ; Check the kind of reparse point (device drivers can create their own tags, so this is important)
          ; The "& $FFFFFFFF" is for 64bit, as the tags are negative when interpreted as quads
          ;
          If *Buffer\ReparseTag & $FFFFFFFF = #IO_REPARSE_TAG_MOUNT_POINT

            ; Read the result. The offset and length are in bytes. PeekS needs length in characters
            ;
            Result$ = PeekS(@*Buffer\MountPointReparseBuffer\PathBuffer[0] + *Buffer\MountPointReparseBuffer\SubstituteNameOffset, *Buffer\MountPointReparseBuffer\SubstituteNameLength / 2, #PB_Unicode)

          ElseIf *Buffer\ReparseTag & $FFFFFFFF = #IO_REPARSE_TAG_SYMLINK
          
            Result$ = PeekS(@*Buffer\SymbolicLinkReparseBuffer\PathBuffer[0] + *Buffer\SymbolicLinkReparseBuffer\SubstituteNameOffset, *Buffer\SymbolicLinkReparseBuffer\SubstituteNameLength / 2, #PB_Unicode)
            
          EndIf
        
        EndIf     
      
        FreeMemory(*Buffer)
      EndIf
    
      CloseHandle_(hDirectory)
    EndIf
  
  Else
  
    ; It is not a reparse point, so return the original path
    ;
    Result$ = Directory$
    
  EndIf
  
  ; Since the result is a unicode directory name, it can have the "\??\" prefix which allows a length of 32767 characters.
  ;
  If Left(Result$, 4) = "\??\"
    Result$ = Right(Result$, Len(Result$)-4)
  EndIf

  ProcedureReturn Result$
EndProcedure



; ----------------------------------------------------------------------------


Directory$ = "C:\Documents and Settings\"

Debug "Testing: " + Directory$
Debug "Target: " + GetDirectoryTarget(Directory$)
Antworten