UNC Pfad

  • Hallo zusammen!

    Ich möchte ein kleines Progrämmchen schreiben, welches die folgenden zwei Dinge per HotKey tun kann:
    - Automatisch neuen Ordner erstellen. (Im aktuell geöffneten Windows Explorer) Dies ist für mich nützlich, da ich sonst immer rechte Maustaste > Neu > Ordner wählen muss! Jetzt geht's per HotKey!
    - Automatisch den UNC Pfad zu derjenigen Datei in die Zwischenablage kopieren, welche gerade markiert ist.

    Wie kann ich das machen? Den Ordner erstellen habe ich geschafft. Wenn auch nur über eine Tastensimulation. Geht es anderst? Eleganter?

    Danke!

    Spoiler anzeigen
    [autoit]

    Opt("TrayIconHide", 1)
    Opt("TrayAutoPause", 0)

    [/autoit] [autoit][/autoit] [autoit]

    HotKeySet("{F7}", "NewFolder") ;F7 Hotkey for creating new folder in Windows Explorer
    HotKeySet("{F10}", "UNCPath") ;F10 Hotkey for storing UNC path of the selected file in the clipboard.

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    Sleep(10000)
    WEnd
    Exit

    [/autoit] [autoit][/autoit] [autoit]

    Func NewFolder()
    Send("+{F10}")
    Send("n")
    Send("o")
    EndFunc ;==>NewFolder

    [/autoit] [autoit][/autoit] [autoit]

    Func UNCPath()

    [/autoit] [autoit][/autoit] [autoit]

    EndFunc ;==>UNCPath

    [/autoit]
  • So, nun bin ich ein bisschen weiter.
    Ich habe nun herausgefunden, wie man den aktuellen Pfad findet, in welchem man im Explorer ist.
    Dementsprechend habe ich auch die Funktion NewFolder angepasst.

    Doch wie finde ich den UNC Pfad der markierten Datei heraus?

    Spoiler anzeigen
    [autoit]

    Opt("TrayIconHide", 1)
    Opt("TrayAutoPause", 0)

    [/autoit] [autoit][/autoit] [autoit]

    HotKeySet("{F7}", "NewFolder") ;F7 Hotkey for creating new folder in Windows Explorer
    HotKeySet("{F10}", "UNCPath") ;F10 Hotkey for storing UNC path of the selected file in the clipboard.

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    Sleep(10000)
    WEnd
    Exit

    [/autoit] [autoit][/autoit] [autoit]

    Func NewFolder()
    Local $sPath = "", $aInfo, $sDirName = "Neuer Ordner", $iDirExtension = 2, $sDirFullName = ""

    [/autoit] [autoit][/autoit] [autoit]

    $sPath = WinGetText("[CLASS:CabinetWClass]")
    $aInfo = StringSplit($sPath, @LF)
    If Not IsArray($aInfo) Then Return -1
    $sPath = $aInfo[2]

    [/autoit] [autoit][/autoit] [autoit]

    DirGetSize($sPath & "\" & $sDirName)
    If @error <> 1 Then ;Directory already exist!
    While 1 ;While Directory exist which I want to create....
    DirGetSize($sPath & "\" & $sDirName & " (" & $iDirExtension & ")")
    If @error <> 1 Then ;Directory already exist!
    $iDirExtension += 1 ;Increment Index
    Else ;Directory not exist!
    $sDirFullName = $sDirName & " (" & $iDirExtension & ")"
    DirCreate($sPath & "\" & $sDirFullName) ;Create Directory with index-number
    ExitLoop ;Exit While
    EndIf
    WEnd
    Else
    $sDirFullName = $sDirName
    DirCreate($sPath & "\" & $sDirFullName) ;Create Directory without index-number
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    Send("{F5}") ;Refresh explorer view
    Sleep(200)
    Send($sDirFullName, 1) ;Select created folder
    Send("{F2}") ;Edit name

    [/autoit] [autoit][/autoit] [autoit]

    ;~ Send("+{F10}")
    ;~ Send("n")
    ;~ Send("o")
    EndFunc ;==>NewFolder

    [/autoit] [autoit][/autoit] [autoit]

    Func UNCPath()
    Local $sPath, $aInfo
    $sPath = WinGetText("[CLASS:CabinetWClass]")
    $aInfo = StringSplit($sPath, @LF)
    If Not IsArray($aInfo) Then Return -1
    $sPath = $aInfo[2]

    [/autoit] [autoit][/autoit] [autoit]

    EndFunc ;==>UNCPath

    [/autoit]
  • Hat jemand eine Idee, wie ich den UNC Pfad einer gerade im Windows Explorer herausfinden kann?
    Oder zumindestens irgendwelche Informationen über die markierte Datei?

  • Den Dateinamen zu markieren wirst du mit ctrl+c hinbekommen. Dann per

    [autoit]

    $dateiname=Stringreplace(stringtrimleft(binarytostring(_ClipBoard_GetData(15)),20),chr(0),"")

    [/autoit]

    auslesen. Klappt unter XP32, bitte mal unter anderen BS testen...

  • Den Dateinamen zu markieren wirst du mit ctrl+c hinbekommen. Dann per

    [autoit]

    $dateiname=Stringreplace(stringtrimleft(binarytostring(_ClipBoard_GetData(15)),20),chr(0),"")

    [/autoit]

    auslesen. Klappt unter XP32, bitte mal unter anderen BS testen...


    So ist es besser:

    [autoit]

    #include<ClipBoard.au3>

    [/autoit][autoit][/autoit][autoit]

    $dateiname=StringTrimLeft(binarytostring(_ClipBoard_GetData(15), 2), 10)
    $last = StringInStr($dateiname, Chr(0), 1, 1)
    If $last Then $dateiname = StringLeft($dateiname, $last-1)
    MsgBox(0, '', $dateiname)

    [/autoit]

    Edit: Den aktuellen explorerpfad bekommst du auch so: http://www.autoitscript.com/forum/index.php?showtopic=89833
    Die ausgewählten Dateien dann über ListView-Funktionen denke ich.

    Einmal editiert, zuletzt von progandy (16. Juni 2010 um 20:32)

  • Hallo!
    Vielen Dank!!
    Es funktioniert fast :)

    Ich bekomme nun den ganzen Pfad mit Dateiname. Aber eigentlich wollte ich den UNC Pfad.
    Also \\Servername\Freigabe\Pfad1\Pfad2\Dateiname.ext
    Wie komme ich nun an den ran? Aber das ist schon mal genial!

    Nur habe ich leider überhaupt nicht verstanden, wie das funktioniert!
    Könnte mir das jemand erklären?

    Hier der Code:

    Spoiler anzeigen
    [autoit]

    Func UNCPath()
    Local $Filename, $tmp, $last

    [/autoit] [autoit][/autoit] [autoit]

    If WinActive("[CLASS:CabinetWClass]") = 0 Then Return -1 ;Return if not the Windows Explorer Windows is active!
    _ClipBoard_Empty() ;Clears Clipboard
    Send("^c") ;Ctrl + C
    While 1 ;Wait till Clipboard is captured (with Ctrl+C)
    $tmp = _ClipBoard_GetData(15)
    If $tmp <> "" Then ExitLoop
    WEnd
    $tmp = BinaryToString($tmp, 2) ;Converts binary to String
    $tmp = StringTrimLeft($tmp, 10) ;Why this?
    $last = StringInStr($tmp, Chr(0), 1) ;Why this?
    If $last Then $Filename = StringLeft($tmp, $last -1) ;Why this?
    _ClipBoard_SetData($Filename)
    ;~ MsgBox(0,"",$Filename)
    EndFunc ;==>UNCPath

    [/autoit]
  • @progandy
    /EDIT/ Erledigt, hatte UTF versaubeutelt....manchmal sollte man nachts schlafen...dann kommt auch im Gehirn an, was das Auge sieht!....

    veronesi
    auf allen Freigaben im Netz bekomme ich den UNC-Pfad zurück. Wenn du auf der lokalen Maschine arbeitest, dann werden allerdings auch die lokalen Dateinamen zurückgegeben. Aber wo ist das Problem, die Rückgabe am Anfang auf \\ zu testen und dann den Servernamen davorzuhängen? Zu deinen Fragen:

    - Ich habe mir jetzt nicht das Format angeschaut, aber der Dateipfad fängt erst ab dem 20. Zeichen (des Ursprungsstrings) an. Daher mit stringtrim() abschneiden.
    - Strings werden allgemein üblich nullterminiert, d.h. das Nullbyte zeigt der anzeigenden Funktion (z.B. der Messagebox oder Consolewrite), daß der String hier zu Ende ist. Tatsächlich kann der string aber viel länger sein, er wird aber nur bis zum ersten Nullbyte dargestellt. Auch die AutoIt-Stringfunktionen juckt das Nullbyte irgendwo in der Mitte des Strings nicht, Ausnahme ist stringregexp(), aber wofür gibts stringtobinary()?^^

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    Einmal editiert, zuletzt von Andy (17. Juni 2010 um 08:48)

  • veronesi
    auf allen Freigaben im Netz bekomme ich den UNC-Pfad zurück. Wenn du auf der lokalen Maschine arbeitest, dann werden allerdings auch die lokalen Dateinamen zurückgegeben. Aber wo ist das Problem, die Rückgabe am Anfang auf \\ zu testen und dann den Servernamen davorzuhängen?

    Ich arbeite auch im Netzwerk. Und ich bekomme immer den Pfad zurück (U:\2_Projekte\AutoIt\Testscript.au3) Aber leider ist das nicht der UNC Pfad.
    Das Problem liegt darin, dass bei verschiedenen Leuten die Serverpfade nicht zwingend auf die gleichen Laufwerksbuchstaben gemappt sind. Deshalb benötige ich die UNC Pfade.
    Und "einfach" den Servernamen davorzusetzen geht auch nicht, weil ich den dann ja nicht kenne.
    Wir haben hier 72 verschiedene Server in einem Cluster. Da kann jedes Verzeichnis (auch wenn es für den Benutzer auf der gleichen Freigabe ist) von einem anderen Server stammen!

  • hm, seltsam, ich bekomme überall
    \\rechnername\laufwerk\pfad\dateiname

  • Das Format 15 in der Zwischenbablage ist das HDROP-Format. Erst kommt ein Header, der den Inhalt der Struktur defniniert. Um es korrekt auszulesen, kann folgende Funktion verwendet werden. Damit werden außerdem alle Dateinamen in der Zwischenablage als Array ausgegeben.

    Spoiler anzeigen
    [autoit]

    #include<ClipBoard.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Func _GetFilesFromClip()
    ; Author: ProgAndy
    Local Static $DROPFILES = "DWORD pFiles; int pt[2]; int fNC; int fWide;"
    If Not _ClipBoard_IsFormatAvailable($CF_HDROP) Then Return SetError(1,0,0)
    Local $bBinary = _ClipBoard_GetData($CF_HDROP)
    If Not @extended Then Return SetError(2,0,0)

    [/autoit] [autoit][/autoit] [autoit]

    Local $iFormat = 2
    $1 = BinaryMid($bBinary, 1, 4)
    If BinaryMid($bBinary, 16, 4) = Binary("0x00000000") Then $iFormat = 1
    Local $t = DllStructCreate("dword")
    DllStructSetData(DllStructCreate("byte[4]", DllStructGetPtr($t)), 1, BinaryMid($bBinary, 1, 4))
    $iOffset = DllStructGetData($t, 1)
    $sFiles = StringTrimRight(BinaryToString(BinaryMid($bBinary, $iOffset+1), $iFormat), 2)
    If $sFiles='' Then Return SetError(3,0,0)
    Return StringSplit($sFiles, Chr(0))
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    #include<Array.au3>
    $a = _GetFilesFromClip()
    _ArrayDisplay($a)

    [/autoit]

    Den UNC-Pfad zu einem Luafwerksbuchstaben solltest du so bekommen. Nicht getestet, da ich gerade keinen Pfad zur Verfügung habe,

    Spoiler anzeigen
    [autoit]

    #include<WinNet.au3>
    Func _WinNet_LetterToUNC($sDriveLetter)
    ; Author: ProgAndy
    Local Static $sizeNETRESOURCE = DllStructGetSize(DllStructCreate($tagNETRESOURCE, 1))
    $sDriveLetter = StringLeft($sDriveLetter, 1)&':'
    Local $hEnum, $nStatus, $iCount, $iBuffer, $tBuffer, $pBuffer, $iLen, $sLocalName, $tString, $pString, $tNETRESOURCE, $sRemoteName

    [/autoit] [autoit][/autoit] [autoit]

    If DriveStatus($sDriveLetter) = 'INVALID' Then Return SetError(1,0,'')
    If Not _WinNet_OpenEnum(0, 0, 0, 0, $hEnum) or $hEnum=0 Then Return SetError(2,0,'')

    [/autoit] [autoit][/autoit] [autoit]

    $iCount = -1
    _WinNet_EnumResource($hEnum, $iCount, 0, $iBuffer)
    If $iBuffer = 0 Then Return SetError(3,0,0)
    $tBuffer = DllStructCreate("byte[" & $iBuffer+1 & ']')
    $pBuffer = DllStructGetPtr($tBuffer)

    [/autoit] [autoit][/autoit] [autoit]

    $iCount = -1
    If _WinNet_EnumResource($hEnum, $iCount, $pBuffer, $iBuffer) Then
    For $i = 0 To $iCount-1
    $tNETRESOURCE = DllStructCreate($tagNETRESOURCE, $pBuffer+$i*$sizeNETRESOURCE)

    [/autoit] [autoit][/autoit] [autoit]

    $pString = DllStructGetData($tNETRESOURCE, 'LocalName')
    $iLen = DllCall("kernel32.dll", "int", "lstrlenW", "ptr", $pString)
    If Not @error Then $iLen = $iLen[0]
    $sLocalName = DllStructGetData(DllStructCreate("wchar[" & $iLen & "]", $pString), 1)

    [/autoit] [autoit][/autoit] [autoit]

    If StringLeft($sLocalName, 2) = $sDriveLetter Then
    $pString = DllStructGetData($tNETRESOURCE, 'RemoteName')
    $iLen = DllCall("kernel32.dll", "int", "lstrlenW", "ptr", $pString)
    If Not @error Then $iLen = $iLen[0]
    $sRemoteName = DllStructGetData(DllStructCreate("wchar[" & $iLen & "]", $pString), 1)
    _WinNet_CloseEnum($hEnum)
    Return $sRemoteName
    EndIf
    Next
    EndIf
    _WinNet_CloseEnum($hEnum)
    EndFunc

    [/autoit]

    2 Mal editiert, zuletzt von progandy (17. Juni 2010 um 09:32)

  • OK.
    Ich bekomme den Pfad der markierten Datei im Array. Das ist ja korrekt. Einfach von diesem muss ich noch irgendwie auf den UNC Pfad kommen. (Siehe Bild)

    Aber leider schnalle ich nicht, warum man diesen Header dann noch beschneiden muss, um an den Pfad zu kommen. Stehen dann in diesem Header diese Informationen? Und woher weiss ich das? Wieviele Zeichen? Wo findet man das?

    Danke für weitere Infos!

  • Die Infos bekommt man da, wo man eigentlich alle Infos herbekommt^^ MSDN
    z.B. http://msdn.microsoft.com/en-us/library/…ipboard_Formats

    Aber diese Arbeit habe ich mir ehrlich gesagt nicht gemacht. Datei im Explorer markieren, ctrl+c.
    Eine for/to Schleife und alle Rückgaben von _ClipBoard_GetData() ausgeben lassen und diese nach dem Dateinamen durchsuchen, voila, der Rest ist Stringmanipulation.

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    Einmal editiert, zuletzt von Andy (17. Juni 2010 um 10:13)

  • Ich habe noch eine zweite Funktion reineditiert. Kannst du mal testen, ob du den UNC-pfad für einen Laufwerksbuchstaben bekommst?

    PS: Wenn man die Daten aus der Zwischenablage ausließt, bekommt man den header und die Pfade aller kopierten Dateien als Binärdaten. Nun muss man davon den Header abschneiden, um nur noch die Pfade zu haben. Dann in einen String umwandeln und die durch Chr(0) getrennten Pfade in ein Array auftrennen. Das ist alles, was meine Funktion macht.

  • @progandy
    Vielen Dank für die Funktion. Leider bekomme ich immer 0 zurück!
    Hier meine Versuche:

    Spoiler anzeigen
    [autoit]

    Func UNCPath()
    Local $Filename, $tmp, $last

    [/autoit] [autoit][/autoit] [autoit]

    If WinActive("[CLASS:CabinetWClass]") = 0 Then Return -1 ;Return if not the Windows Explorer Windows is active!
    _ClipBoard_Empty() ;Clears Clipboard
    Send("^c") ;Ctrl + C
    While 1 ;Wait till Clipboard is captured (with Ctrl+C)
    $tmp = _ClipBoard_GetData(15) ;Get Clipboard Header Data
    If $tmp <> "" Then ExitLoop
    WEnd
    $tmp = BinaryToString($tmp, 2) ;Converts binary to String
    $tmp = StringTrimLeft($tmp, 10)
    $last = StringInStr($tmp, Chr(0), 1)
    If $last Then $Filename = StringLeft($tmp, $last -1) ;Filename contains now Path and filename, but not in UNC
    $Filename = _WinNet_LetterToUNC(StringLeft($Filename, 3))
    _ClipBoard_SetData($Filename)
    MsgBox(0,"",$Filename)
    EndFunc ;==>UNCPath

    [/autoit] [autoit][/autoit] [autoit]

    Func _WinNet_LetterToUNC($sDriveLetter)
    ; Author: ProgAndy
    Local Static $sizeNETRESOURCE = DllStructGetSize(DllStructCreate($tagNETRESOURCE, 1))
    $sDriveLetter = StringLeft($sDriveLetter, 1)&':'
    Local $hEnum, $nStatus, $iCount, $iBuffer, $tBuffer, $pBuffer, $iLen, $sLocalName, $tString, $pString, $tNETRESOURCE, $sRemoteName

    [/autoit] [autoit][/autoit] [autoit]

    If DriveStatus($sDriveLetter) = 'INVALID' Then Return SetError(1,0,'')
    If Not _WinNet_OpenEnum(0, 0, 0, 0, $hEnum) or $hEnum=0 Then Return SetError(2,0,'')

    [/autoit] [autoit][/autoit] [autoit]

    $iCount = -1
    _WinNet_EnumResource($hEnum, $iCount, 0, $iBuffer)
    If $iBuffer = 0 Then Return SetError(3,0,0)
    $tBuffer = DllStructCreate("byte[" & $iBuffer+1 & ']')
    $pBuffer = DllStructGetPtr($tBuffer)

    [/autoit] [autoit][/autoit] [autoit]

    $iCount = -1
    If _WinNet_EnumResource($hEnum, $iCount, $pBuffer, $iBuffer) Then
    For $i = 0 To $iCount-1
    $tNETRESOURCE = DllStructCreate($tagNETRESOURCE, $pBuffer+$i*$sizeNETRESOURCE)

    [/autoit] [autoit][/autoit] [autoit]

    $pString = DllStructGetData($tNETRESOURCE, 'LocalName')
    $iLen = DllCall("kernel32.dll", "int", "lstrlenW", "ptr", $pString)
    If Not @error Then $iLen = $iLen[0]
    $sLocalName = DllStructGetData(DllStructCreate("wchar[" & $iLen & "]", $pString), 1)

    [/autoit] [autoit][/autoit] [autoit]

    If StringLeft($sLocalName, 2) = $sDriveLetter Then
    $pString = DllStructGetData($tNETRESOURCE, 'RemoteName')
    $iLen = DllCall("kernel32.dll", "int", "lstrlenW", "ptr", $pString)
    If Not @error Then $iLen = $iLen[0]
    $sRemoteName = DllStructGetData(DllStructCreate("wchar[" & $iLen & "]", $pString), 1)
    _WinNet_CloseEnum($hEnum)
    Return $sRemoteName
    EndIf
    Next
    EndIf
    _WinNet_CloseEnum($hEnum)
    EndFunc

    [/autoit]