Jump to content

Get path from file in clipboard


Recommended Posts

When I copy a track in my music application, both text and the file are copied. For example: if i paste in a text file this text is pasted "Slowdive - Alison", and if I paste in a folder the mp3 is pasted. I know that in C# you can use Clipboard.GetFileDropList() to get the path of the file. But how do I do this in Autoit? Get the path.


I have tried these two, both result in text like "Slowdive - Alison"

#include <Clipboard.au3>
MsgBox(0, "", ClipGet())
MsgBox(0, "", _ClipBoard_GetData())
Link to comment
Share on other sites

  • Moderators

I haven't played with the clipboard in years... 

I copied a media file from a folder and was able to get the name with this, not sure why a lot of the memory constants are not listed (or I couldn't find them @M$ site) but I had to play around with the clipboard enum to find the right file.  I don't believe I have your exact scenario because you say you get the name, but this is more for S&G to see if it works for you.

#include <Clipboard.au3>


ConsoleWrite(_ClipBoard_GetFilePath_Tmp() & @CRLF)


Func _ClipBoard_GetFilePath_Tmp()

    Local Const $iFileName = 0xC006

    If Not _ClipBoard_IsFormatAvailable($iFileName) Then Return SetError(-1, 0, 0)
    If Not _ClipBoard_Open(0) Then Return SetError(2, 0, 0)

    ; get mem location aka handle
    Local $hMem = _ClipBoard_GetDataEx($iFileName)
    If $hMem = 0 Then
        _ClipBoard_Close()
        Return SetError(-3, 0, 0)
    EndIf

    Local $pMem = _MemGlobalLock($hMem)
    If $pMem = 0 Then
        _ClipBoard_Close()
        Return SetError(-4, 0, 0)
    EndIf

    Local $iMemSize = _MemGlobalSize($hMem)
    If $iMemSize = 0 Then
        _MemGlobalUnlock($hMem)
        _ClipBoard_Close()
        Return SetError(-5, 0, 0)
    EndIf

    Local $tData = DllStructCreate("char[" & $iMemSize & "]", $pMem)

    _MemGlobalUnlock($hMem)
    _ClipBoard_Close()

    Return SetExtended($iMemSize, DllStructGetData($tData, 1))
EndFunc

 

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

I tried your script. If i have a file copied it outputs the path. But when I have the track copied from my music application (foobar2000) it outputs "0".

Is it possible that foobar2000 copies an array of things? If that is possible...

Quote

item 1: "Slowdive - Alison"
item 2: "D:\Music\Slowdive\1993 Souvlaki\01. Alison.mp3"

Link to comment
Share on other sites

  • Moderators
1 hour ago, spuuunit said:

Is it possible that foobar2000 copies an array of things? If that is possible...

I've given you this answer not only with my script but with my statement about enum, try using the copy udf enum, getdata and memory funcs.  There are some example scripts on the enum that show you a lot of the data available in the help file, try experimenting with them to get an idea on how to accomplish what you need.  Try tearing apart the functions in the udf itself so you can understand how to use some of the dllcalls and memory funcs.

I see you say you've tried to snippets of function calls, what else have you tried?  Searched the forum/google? What were the success and failures of what you found and tried?  No screen shots, no real code?  You've been a member 11 years, you know how this goes lol.

 

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

  • Moderators

Here, I wrote something to get you a majority of the way, now you can use the format ids and mem locations to get the data you want (or you can use the array to see if the data you want is even there).

#include <Clipboard.au3>
#include <Array.au3>

Global $gaArgs = _ClipBoard_GetCurrentFormatArray()
If @error Then
    MsgBox(16, "Error", "Error: " & @error)
Else
    _ArrayDisplay($gaArgs, Default, Default, Default, Default, "ID Formatted|ID Raw|ID Type|Memory Location")
EndIf

Func _ClipBoard_GetCurrentFormatArray($hOwner = 0)

    _ClipBoard_Open($hOwner)

    Local $iCount = _ClipBoard_CountFormats()
    If @error Then
        _ClipBoard_Close()
        Return SetError(-1, 0, 0)
    EndIf

    ; Array[number of formats][0:format id formatted
    ;                          1:format id raw
    ;                          2:format type
    ;                          3:memory location]
    ; If memory location = 0, then we'll exclude it from the array
    Local $i2ndArgs = 4 ; using redim later, save time making sure count is right
    Local $aRet[$iCount][$i2ndArgs]
    Local $iFormat, $iEnum = 0, $hMem = 0
    Do
        $iFormat = _ClipBoard_EnumFormats($iFormat)
        If $iFormat <> 0 Then
            $hMem = _ClipBoard_GetDataEx($iFormat)
            If $hMem <> 0 Then
                $aRet[$iEnum][0] = "0x" & Hex($iFormat, 4) ; format id formatted
                $aRet[$iEnum][1] = $iFormat ; format id raw
                $aRet[$iEnum][2] = _ClipBoard_FormatStr($iFormat) ; format type
                $aRet[$iEnum][3] = $hMem ; memory location
                $iEnum += 1
            EndIf
        EndIf
    Until $iFormat = 0

    _ClipBoard_Close()

    If $iEnum = 0 Then Return SetError(-2, 0, 0)

    ; resize array
    ReDim $aRet[$iEnum][$i2ndArgs]

    Return SetExtended($iEnum, $aRet)
EndFunc

I only wrote this because I believe it should exist for everyone, this is definitely something I can see being handy for a majority of people that use the ClipBoard.au3 extensively.

Edited by SmOke_N
Added header for _ArrayDisplay in case someone was to lazy to read the notes left in the function

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

6 hours ago, spuuunit said:

Thanks for the code, ...

When you code your solution(s), post them here.

Spoiler
#include <Clipboard.au3>
#include <Array.au3>

Global $gaArgs = _ClipBoard_GetCurrentFormatArray() ; https://www.autoitscript.com/forum/index.php?showtopic=211494&view=findpost&p=1530297
If @error Then
    MsgBox(16, "Error", "Error: " & @error)
Else
    _ArrayDisplay($gaArgs, Default, Default, Default, Default, "ID Formatted|ID Raw|ID Type|Memory Location|Data from  hMem ( if you added the code )")
EndIf

Func _ClipBoard_GetCurrentFormatArray($hOwner = 0)

    _ClipBoard_Open($hOwner)

    Local $iCount = _ClipBoard_CountFormats()
    If @error Then
        _ClipBoard_Close()
        Return SetError(-1, 0, 0)
    EndIf

    ; Array[number of formats][0:format id formatted
    ;                          1:format id raw
    ;                          2:format type
    ;                          3:memory location]
    ; If memory location = 0, then we'll exclude it from the array
    Local $i2ndArgs = 4 + 1 ; using redim later, save time making sure count is right ; + 1 to set the data
    Local $aRet[$iCount][$i2ndArgs]
    Local $iFormat, $iEnum = 0, $hMem = 0
    Do
        $iFormat = _ClipBoard_EnumFormats($iFormat)
        If $iFormat <> 0 Then
            $hMem = _ClipBoard_GetDataEx($iFormat)
            If $hMem <> 0 Then
                $aRet[$iEnum][0] = "0x" & Hex($iFormat, 4) ; format id formatted
                $aRet[$iEnum][1] = $iFormat ; format id raw
                $aRet[$iEnum][2] = _ClipBoard_FormatStr($iFormat) ; format type
                $aRet[$iEnum][3] = $hMem ; memory location
                $aRet[$iEnum][4] = _ClipBoard_ClipBoard_GetDataFromMem($hMem, $iFormat)
                $iEnum += 1
            EndIf
        EndIf
    Until $iFormat = 0

    _ClipBoard_Close()

    If $iEnum = 0 Then Return SetError(-2, 0, 0)

    ; resize array
    ReDim $aRet[$iEnum][$i2ndArgs]

    Return SetExtended($iEnum, $aRet)
EndFunc   ;==>_ClipBoard_GetCurrentFormatArray

Func _ClipBoard_ClipBoard_GetDataFromMem($hMem, $iFormat) ; added by argumentum
    ; based on prior post ; https://www.autoitscript.com/forum/topic/211494-get-path-from-file-in-clipboard/?do=findComment&comment=1530284
    Local $pMemoryBlock = _MemGlobalLock($hMem)
    If $pMemoryBlock = 0 Then Return SetError(-4, 0, "")
    Local $vRet, $iDataSize = _MemGlobalSize($hMem)
    If $iDataSize = 0 Then
        _MemGlobalUnlock($hMem)
        Return SetError(-5, 0, "")
    EndIf

    ; hint: https://github.com/tpn/winsdk-10/blob/master/Include/10.0.10240.0/um/ShlObj.h
    ; I guess someone/you has to declare/enum these:
    Local Enum $CF_FileName = 49158, $CF_FileNameW

    Switch $iFormat ; chunk from: #include <Clipboard.au3> ; _ClipBoard_GetData()
        Case $CF_TEXT, $CF_OEMTEXT, $CF_FileName
            $vRet = DllStructGetData(DllStructCreate("char[" & $iDataSize & "]", $pMemoryBlock), 1)

        Case $CF_UNICODETEXT, $CF_FileNameW
            $iDataSize = Round($iDataSize / 2) ; Round() shouldn't be necessary, as CF_UNICODETEXT should be 2-bytes wide & thus evenly-divisible
            $vRet = DllStructGetData(DllStructCreate("wchar[" & $iDataSize & "]", $pMemoryBlock), 1)

        Case $CF_HDROP ; based on ; by jchd ; https://www.autoitscript.com/forum/topic/210647-drag-and-drop-many-files-to-a-compiled-script/?do=findComment&comment=1522418
            $vRet = DllStructGetData(DllStructCreate("byte[" & $iDataSize & "]", $pMemoryBlock), 1)
            $vRet = StringReplace(BinaryToString(BinaryMid($vRet, 21, BinaryLen($vRet) - 24), 2), Chr(0), "|") ; $SB_UTF16LE(2) = UTF16 Little Endian
            $iDataSize = StringLen($vRet) ; edit after KaFu post ; https://www.autoitscript.com/forum/topic/211494-get-path-from-file-in-clipboard/?do=findComment&comment=1530305

        Case Else ; Binary data return for all other formats
            $vRet = DllStructGetData(DllStructCreate("byte[" & $iDataSize & "]", $pMemoryBlock), 1)

    EndSwitch

    _MemGlobalUnlock($hMem)
    Return SetExtended($iDataSize, $vRet)
EndFunc   ;==>_ClipBoard_ClipBoard_GetDataFromMem

 

I'd love to have 'em ( for my "copy'n'paste" coding style :lol: )

Edited by argumentum
better code ?

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

  • Moderators
2 hours ago, argumentum said:

When you code your solution(s), post them here.

I'd love to have 'em ( for my "copy'n'paste" coding style :lol: )

See: 

There should be a self explanatory example func and an added Get func in the include.

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

Nice 🙂, added CF_HDROP for multiple filename selections.

#include <Clipboard.au3>
#include <Array.au3>

Global $gaArgs = _ClipBoard_GetCurrentFormatArray() ; https://www.autoitscript.com/forum/index.php?showtopic=211494&view=findpost&p=1530297
If @error Then
    MsgBox(16, "Error", "Error: " & @error)
Else
    _ArrayDisplay($gaArgs, Default, Default, Default, Default, "ID Formatted|ID Raw|ID Type|Memory Location|Data from  hMem ( if you added the code )")
EndIf

Func _ClipBoard_GetCurrentFormatArray($hOwner = 0)

    _ClipBoard_Open($hOwner)

    Local $iCount = _ClipBoard_CountFormats()
    If @error Then
        _ClipBoard_Close()
        Return SetError(-1, 0, 0)
    EndIf

    ; Array[number of formats][0:format id formatted
    ;                          1:format id raw
    ;                          2:format type
    ;                          3:memory location]
    ; If memory location = 0, then we'll exclude it from the array
    Local $i2ndArgs = 4 + 1 ; using redim later, save time making sure count is right ; + 1 to set the data
    Local $aRet[$iCount][$i2ndArgs]
    Local $iFormat, $iEnum = 0, $hMem = 0
    Do
        $iFormat = _ClipBoard_EnumFormats($iFormat)
        If $iFormat <> 0 Then
            $hMem = _ClipBoard_GetDataEx($iFormat)
            If $hMem <> 0 Then
                $aRet[$iEnum][0] = "0x" & Hex($iFormat, 4) ; format id formatted
                $aRet[$iEnum][1] = $iFormat ; format id raw
                $aRet[$iEnum][2] = _ClipBoard_FormatStr($iFormat) ; format type
                $aRet[$iEnum][3] = $hMem ; memory location
                $aRet[$iEnum][4] = _ClipBoard_ClipBoard_GetDataFromMem($hMem, $iFormat)
                $iEnum += 1
            EndIf
        EndIf
    Until $iFormat = 0

    _ClipBoard_Close()

    If $iEnum = 0 Then Return SetError(-2, 0, 0)

    ; resize array
    ReDim $aRet[$iEnum][$i2ndArgs]

    Return SetExtended($iEnum, $aRet)
EndFunc   ;==>_ClipBoard_GetCurrentFormatArray

Func _ClipBoard_ClipBoard_GetDataFromMem($hMem, $iFormat) ; added by argumentum
    ; based on prior post ; https://www.autoitscript.com/forum/topic/211494-get-path-from-file-in-clipboard/?do=findComment&comment=1530284
    Local $pMemoryBlock = _MemGlobalLock($hMem)
    If $pMemoryBlock = 0 Then Return SetError(-4, 0, "")
    Local $tData, $iDataSize = _MemGlobalSize($hMem)
    If $iDataSize = 0 Then
        _MemGlobalUnlock($hMem)
        Return SetError(-5, 0, "")
    EndIf

    ; hint: https://github.com/tpn/winsdk-10/blob/master/Include/10.0.10240.0/um/ShlObj.h
    ; I guess someone/you has to declare/enum these:
    Local Enum $CF_FileName = 49158, $CF_FileNameW

    Switch $iFormat ; chunk from: #include <Clipboard.au3> ; _ClipBoard_GetData()
        Case $CF_TEXT, $CF_OEMTEXT, $CF_FileName
            $tData = DllStructCreate("char[" & $iDataSize & "]", $pMemoryBlock)

        Case $CF_UNICODETEXT, $CF_FileNameW
            ; Round() shouldn't be necessary, as CF_UNICODETEXT should be 2-bytes wide & thus evenly-divisible
            $iDataSize = Round($iDataSize / 2)
            $tData = DllStructCreate("wchar[" & $iDataSize & "]", $pMemoryBlock)

        Case $CF_HDROP
            $tData = DllStructCreate("byte[" & $iDataSize & "]", $pMemoryBlock)

            ; by jchd
            ; https://www.autoitscript.com/forum/topic/210647-drag-and-drop-many-files-to-a-compiled-script/?do=findComment&comment=1522418
            Local $data = DllStructGetData($tData, 1)
            Local $bin = BinaryMid($data, 21, BinaryLen($data) - 24)
            Local $c, $s
            For $i = 1 To BinaryLen($bin) Step 2
                $c = BinaryMid($bin, $i, 2)
                $s &= ($c <> 0 ? ChrW($c) : "|")
            Next
            _MemGlobalUnlock($hMem)
            Return SetExtended(StringLen($s), $s)

        Case Else
            ; Binary data return for all other formats
            $tData = DllStructCreate("byte[" & $iDataSize & "]", $pMemoryBlock)
    EndSwitch

    _MemGlobalUnlock($hMem)
    Return SetExtended($iDataSize, DllStructGetData($tData, 1))
EndFunc   ;==>_ClipBoard_ClipBoard_GetDataFromMem

 

Link to comment
Share on other sites

  • Moderators

I added a new func, see Example 2 there:

Might actually be what OP is looking for

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...