본문 바로가기

개발하자

파이썬에서 .lnk 파일의 대상을 읽습니까?

반응형

파이썬에서 .lnk 파일의 대상을 읽습니까?

Python에서 바로 가기() 파일의 대상 파일/디렉토리를 읽으려고 합니다. 두통이 없는 방법이 있나요? 그 사양은 내가 이해할 수 없는 것이다. 나는 윈도우 전용 API를 사용하는 것을 개의치 않는다.

최종 목표는 Windows XP 및 Vista에서 폴더를 찾는 것입니다. XP에서는 기본적으로 에 있고 Vista에서는 에 있습니다. 그러나 사용자는 이 폴더의 위치를 변경할 수 있습니다. 이 경우 폴더는 더 이상 존재하지 않으며 새 폴더를 가리키는 폴더로 대체됩니다. 그리고 나는 그것의 절대적인 위치를 원한다.




기본적으로 Windows API를 직접 호출합니다. 다음은 구글링 이후에 발견된 좋은 예입니다:

import os, sys
import pythoncom
from win32com.shell import shell, shellcon

shortcut = pythoncom.CoCreateInstance (
  shell.CLSID_ShellLink,
  None,
  pythoncom.CLSCTX_INPROC_SERVER,
  shell.IID_IShellLink
)
desktop_path = shell.SHGetFolderPath (0, shellcon.CSIDL_DESKTOP, 0, 0)
shortcut_path = os.path.join (desktop_path, "python.lnk")
persist_file = shortcut.QueryInterface (pythoncom.IID_IPersistFile)
persist_file.Load (shortcut_path)

shortcut.SetDescription ("Updated Python %s" % sys.version)
mydocs_path = shell.SHGetFolderPath (0, shellcon.CSIDL_PERSONAL, 0, 0)
shortcut.SetWorkingDirectory (mydocs_path)

persist_file.Save (shortcut_path, 0)

님이 보내주셨어요.

다른 예로 "파이톤 isshell link"를 검색할 수 있습니다.

또한 API 참조는 다음과 같은 도움이 됩니다:




또는 을(를) 사용해 볼 수 있습니다. 다음 코드는 작동할 수 있지만 지금은 Windows 컴퓨터에 없기 때문에 테스트할 수 없습니다.

import ctypes

shell32 = ctypes.windll.shell32

# allocate MAX_PATH bytes in buffer
video_folder_path = ctypes.create_string_buffer(260)

# 0xE is CSIDL_MYVIDEO
# 0 is SHGFP_TYPE_CURRENT
# If you want a Unicode path, use SHGetFolderPathW instead
if shell32.SHGetFolderPathA(None, 0xE, None, 0, video_folder_path) >= 0:
    # success, video_folder_path now contains the correct path
else:
    # error



WSH를 통해 Python을 사용하여 바로 가기 만들기

import sys
import win32com.client 

shell = win32com.client.Dispatch("WScript.Shell")
shortcut = shell.CreateShortCut("t:\\test.lnk")
shortcut.Targetpath = "t:\\ftemp"
shortcut.save()


WSH를 통해 Python을 사용하여 바로 가기 대상 읽기

import sys
import win32com.client 

shell = win32com.client.Dispatch("WScript.Shell")
shortcut = shell.CreateShortCut("t:\\test.lnk")
print(shortcut.Targetpath)



나는 이것이 오래된 스레드라는 것을 알지만, 나는 원래 질문에 언급된 것처럼 링크 사양을 사용하는 방법에 대한 정보가 많지 않다고 느낀다.

나의 바로 가기 대상 구현체는 win32com 모듈을 사용할 수 없었고 많은 검색 끝에 나의 것을 생각해 내기로 결정했다. 나의 제약 하에서 내가 필요로 하는 것을 성취하는 다른 것은 아무것도 없는 것 같았다. 이것이 같은 상황에 처한 다른 사람들에게 도움이 되기를 바랍니다.

마이크로소프트가 제공한 이진 구조를 사용한다.

import struct

path = 'myfile.txt.lnk'    
target = ''

with open(path, 'rb') as stream:
    content = stream.read()
    # skip first 20 bytes (HeaderSize and LinkCLSID)
    # read the LinkFlags structure (4 bytes)
    lflags = struct.unpack('I', content[0x14:0x18])[0]
    position = 0x18
    # if the HasLinkTargetIDList bit is set then skip the stored IDList 
    # structure and header
    if (lflags & 0x01) == 1:
        position = struct.unpack('H', content[0x4C:0x4E])[0] + 0x4E
    last_pos = position
    position += 0x04
    # get how long the file information is (LinkInfoSize)
    length = struct.unpack('I', content[last_pos:position])[0]
    # skip 12 bytes (LinkInfoHeaderSize, LinkInfoFlags, and VolumeIDOffset)
    position += 0x0C
    # go to the LocalBasePath position
    lbpos = struct.unpack('I', content[position:position+0x04])[0]
    position = last_pos + lbpos
    # read the string at the given position of the determined length
    size= (length + last_pos) - position - 0x02
    temp = struct.unpack('c' * size, content[position:position+size])
    target = ''.join([chr(ord(a)) for a in temp])



저는 또한 이 질문이 오래되었다는 것을 알지만, 저는 그 대답이 제 상황과 가장 관련이 있다는 것을 알았습니다.

Jared의 답변처럼 나도 win32com 모듈을 사용할 수 없었다. 그래서 재러드가 바이너리 구조를 사용한 것이 저를 거기까지 오게 했습니다. Windows와 Linux 모두에서 읽기 바로 가기가 필요했습니다. 여기서 바로 가기는 Windows에서 Samba 공유로 생성됩니다. Jared의 구현은 나에게 별로 효과가 없었습니다. 바로 가기 형식에서 몇 가지 다른 변형을 만났기 때문이라고 생각합니다. 하지만, 그것은 제게 필요한 시작을 주었습니다(고마워 재러드).

자레드의 접근 방식을 확장한 MS 단축키라는 클래스가 있습니다. 그러나 파이썬 3.4에 추가된 일부 pathlib 기능을 사용하기 때문에 구현은 파이썬 3.4 이상에 불과하다

#!/usr/bin/python3

# Link Format from MS: https://msdn.microsoft.com/en-us/library/dd871305.aspx
# Need to be able to read shortcut target from .lnk file on linux or windows.
# Original inspiration from: http://stackoverflow.com/questions/397125/reading-the-target-of-a-lnk-file-in-python

from pathlib import Path, PureWindowsPath
import struct, sys, warnings

if sys.hexversion < 0x03040000:
    warnings.warn("'{}' module requires python3.4 version or above".format(__file__), ImportWarning)


# doc says class id = 
#    00021401-0000-0000-C000-000000000046
# requiredCLSID = b'\x00\x02\x14\x01\x00\x00\x00\x00\xC0\x00\x00\x00\x00\x00\x00\x46'
# Actually Getting: 
requiredCLSID   = b'\x01\x14\x02\x00\x00\x00\x00\x00\xC0\x00\x00\x00\x00\x00\x00\x46'  # puzzling

class ShortCutError(RuntimeError):
    pass


class MSShortcut():
    """
    interface to Microsoft Shortcut Objects.  Purpose:
    - I need to be able to get the target from a samba shared on a linux machine
    - Also need to get access from a Windows machine.
    - Need to support several forms of the shortcut, as they seem be created differently depending on the 
      creating machine.
    - Included some 'flag' types in external interface to help test differences in shortcut types

    Args:
        scPath (str): path to shortcut

    Limitations:
        - There are some omitted object properties in the implementation. 
          Only implemented / tested enough to recover the shortcut target information. Recognized omissions:
          - LinkTargetIDList
          - VolumeId structure (if captured later, should be a separate class object to hold info)
          - Only captured environment block from extra data 
        - I don't know how or when some of the shortcut information is used, only captured what I recognized, 
          so there may be bugs related to use of the information
        - NO shortcut update support (though might be nice)
        - Implementation requires python 3.4 or greater
        - Tested only with Unicode data on a 64bit little endian machine, did not consider potential endian issues

    Not Debugged:
        - localBasePath - didn't check if parsed correctly or not.
        - commonPathSuffix
        - commonNetworkRelativeLink

    """

    def __init__(self, scPath):
        """
        Parse and keep shortcut properties on creation
        """
        self.scPath = Path(scPath)

        self._clsid = None
        self._lnkFlags = None
        self._lnkInfoFlags = None
        self._localBasePath = None
        self._commonPathSuffix = None
        self._commonNetworkRelativeLink = None
        self._name = None
        self._relativePath = None
        self._workingDir = None
        self._commandLineArgs = None
        self._iconLocation = None
        self._envTarget = None

        self._ParseLnkFile(self.scPath)  


    @property
    def clsid(self): 
        return self._clsid

    @property
    def lnkFlags(self): 
        return self._lnkFlags

    @property
    def lnkInfoFlags(self): 
        return self._lnkInfoFlags

    @property
    def localBasePath(self): 
        return self._localBasePath

    @property
    def commonPathSuffix(self): 
        return self._commonPathSuffix

    @property
    def commonNetworkRelativeLink(self): 
        return self._commonNetworkRelativeLink

    @property
    def name(self): 
        return self._name    

    @property
    def relativePath(self): 
        return self._relativePath    

    @property
    def workingDir(self): 
        return self._workingDir    

    @property
    def commandLineArgs(self): 
        return self._commandLineArgs    

    @property
    def iconLocation(self): 
        return self._iconLocation    

    @property
    def envTarget(self): 
        return self._envTarget    


    @property
    def targetPath(self):
        """
        Args:
            woAnchor (bool): remove the anchor (\\server\path or drive:) from returned path.

        Returns:
            a libpath PureWindowsPath object for combined workingDir/relative path
            or the envTarget

        Raises:
            ShortCutError when no target path found in Shortcut
        """
        target = None
        if self.workingDir:
            target = PureWindowsPath(self.workingDir)
            if self.relativePath:
                target = target / PureWindowsPath(self.relativePath)
            else: target = None

        if not target and self.envTarget:
            target = PureWindowsPath(self.envTarget)

        if not target:
            raise ShortCutError("Unable to retrieve target path from MS Shortcut: shortcut = {}"
                               .format(str(self.scPath)))  

        return target    

    @property
    def targetPathWOAnchor(self):
        tp = self.targetPath
        return tp.relative_to(tp.anchor)




    def _ParseLnkFile(self, lnkPath):        
        with lnkPath.open('rb') as f:
            content = f.read()

            # verify size  (4 bytes)
            hdrSize = struct.unpack('I', content[0x00:0x04])[0]
            if hdrSize != 0x4C:
                raise ShortCutError("MS Shortcut HeaderSize = {}, but required to be = {}: shortcut = {}"
                                   .format(hdrSize, 0x4C, str(lnkPath)))

            # verify LinkCLSID id (16 bytes)            
            self._clsid = bytes(struct.unpack('B'*16, content[0x04:0x14]))
            if self._clsid != requiredCLSID:
                raise ShortCutError("MS Shortcut ClassID = {}, but required to be = {}: shortcut = {}"
                                   .format(self._clsid, requiredCLSID, str(lnkPath)))        

            # read the LinkFlags structure (4 bytes)
            self._lnkFlags = struct.unpack('I', content[0x14:0x18])[0]
            #logger.debug("lnkFlags=0x%0.8x" % self._lnkFlags)
            position = 0x4C

            # if HasLinkTargetIDList bit, then position to skip the stored IDList structure and header
            if (self._lnkFlags & 0x01):
                idListSize = struct.unpack('H', content[position:position+0x02])[0]
                position += idListSize + 2

            # if HasLinkInfo, then process the linkinfo structure  
            if (self._lnkFlags & 0x02):
                (linkInfoSize, linkInfoHdrSize, self._linkInfoFlags, 
                 volIdOffset, localBasePathOffset, 
                 cmnNetRelativeLinkOffset, cmnPathSuffixOffset) = struct.unpack('IIIIIII', content[position:position+28])

                # check for optional offsets
                localBasePathOffsetUnicode = None
                cmnPathSuffixOffsetUnicode = None
                if linkInfoHdrSize >= 0x24:
                    (localBasePathOffsetUnicode, cmnPathSuffixOffsetUnicode) = struct.unpack('II', content[position+28:position+36])

                #logger.debug("0x%0.8X" % linkInfoSize)
                #logger.debug("0x%0.8X" % linkInfoHdrSize)
                #logger.debug("0x%0.8X" % self._linkInfoFlags)
                #logger.debug("0x%0.8X" % volIdOffset)
                #logger.debug("0x%0.8X" % localBasePathOffset)
                #logger.debug("0x%0.8X" % cmnNetRelativeLinkOffset)
                #logger.debug("0x%0.8X" % cmnPathSuffixOffset)
                #logger.debug("0x%0.8X" % localBasePathOffsetUnicode)
                #logger.debug("0x%0.8X" % cmnPathSuffixOffsetUnicode)

                # if info has a localBasePath
                if (self._linkInfoFlags & 0x01):
                    bpPosition = position + localBasePathOffset

                    # not debugged - don't know if this works or not
                    self._localBasePath = UnpackZ('z', content[bpPosition:])[0].decode('ascii')
                    #logger.debug("localBasePath: {}".format(self._localBasePath))

                    if localBasePathOffsetUnicode:
                        bpPosition = position + localBasePathOffsetUnicode
                        self._localBasePath = UnpackUnicodeZ('z', content[bpPosition:])[0]
                        self._localBasePath = self._localBasePath.decode('utf-16')               
                        #logger.debug("localBasePathUnicode: {}".format(self._localBasePath))

                # get common Path Suffix
                cmnSuffixPosition = position + cmnPathSuffixOffset               
                self._commonPathSuffix = UnpackZ('z', content[cmnSuffixPosition:])[0].decode('ascii')
                #logger.debug("commonPathSuffix: {}".format(self._commonPathSuffix))
                if cmnPathSuffixOffsetUnicode:
                    cmnSuffixPosition = position + cmnPathSuffixOffsetUnicode
                    self._commonPathSuffix = UnpackUnicodeZ('z', content[cmnSuffixPosition:])[0]
                    self._commonPathSuffix = self._commonPathSuffix.decode('utf-16')               
                    #logger.debug("commonPathSuffix: {}".format(self._commonPathSuffix))


                # check for CommonNetworkRelativeLink
                if (self._linkInfoFlags & 0x02):
                    relPosition = position + cmnNetRelativeLinkOffset
                    self._commonNetworkRelativeLink = CommonNetworkRelativeLink(content, relPosition)

                position += linkInfoSize 

            # If HasName
            if (self._lnkFlags & 0x04):
                (position, self._name) = self.readStringObj(content, position)
                #logger.debug("name: {}".format(self._name))     

            # get relative path string
            if (self._lnkFlags & 0x08):
                (position, self._relativePath) = self.readStringObj(content, position)
                #logger.debug("relPath='{}'".format(self._relativePath))

            # get working dir string
            if (self._lnkFlags & 0x10):
                (position, self._workingDir) = self.readStringObj(content, position)
                #logger.debug("workingDir='{}'".format(self._workingDir))

            # get command line arguments
            if (self._lnkFlags & 0x20):
                (position, self._commandLineArgs) = self.readStringObj(content, position)
                #logger.debug("commandLineArgs='{}'".format(self._commandLineArgs))

            # get icon location
            if (self._lnkFlags & 0x40):
                (position, self._iconLocation) = self.readStringObj(content, position)
                #logger.debug("iconLocation='{}'".format(self._iconLocation))

            # look for environment properties             
            if (self._lnkFlags & 0x200):
                while True:
                    size = struct.unpack('I', content[position:position+4])[0]
                    #logger.debug("blksize=%d" % size)
                    if size==0: break

                    signature = struct.unpack('I', content[position+4:position+8])[0]
                    #logger.debug("signature=0x%0.8x" % signature)     

                    # EnvironmentVariableDataBlock          
                    if signature == 0xA0000001:  

                        if (self._lnkFlags & 0x80): # unicode
                            self._envTarget = UnpackUnicodeZ('z', content[position+268:])[0]
                            self._envTarget = self._envTarget.decode('utf-16')
                        else:
                            self._envTarget = UnpackZ('z', content[position+8:])[0].decode('ascii')

                        #logger.debug("envTarget='{}'".format(self._envTarget))

                    position += size


    def readStringObj(self, scContent, position):
        """ 
        returns:
            tuple: (newPosition, string)
        """
        strg = ''
        size = struct.unpack('H', scContent[position:position+2])[0]
        #logger.debug("workingDirSize={}".format(size))
        if (self._lnkFlags & 0x80): # unicode
            size *= 2
            strg = struct.unpack(str(size)+'s', scContent[position+2:position+2+size])[0]
            strg = strg.decode('utf-16')               
        else:
            strg = struct.unpack(str(size)+'s', scContent[position+2:position+2+size])[0].decode('ascii')
        #logger.debug("strg='{}'".format(strg))
        position += size + 2 # 2 bytes to account for CountCharacters field

        return (position, strg)




class CommonNetworkRelativeLink():

    def __init__(self, scContent, linkContentPos):

        self._networkProviderType = None
        self._deviceName = None
        self._netName = None

        (linkSize, flags, netNameOffset, 
         devNameOffset, self._networkProviderType) = struct.unpack('IIIII', scContent[linkContentPos:linkContentPos+20])

        #logger.debug("netnameOffset = {}".format(netNameOffset))
        if netNameOffset > 0x014:
            (netNameOffsetUnicode, devNameOffsetUnicode) = struct.unpack('II', scContent[linkContentPos+20:linkContentPos+28])
            #logger.debug("netnameOffsetUnicode = {}".format(netNameOffsetUnicode))
            self._netName = UnpackUnicodeZ('z', scContent[linkContentPos+netNameOffsetUnicode:])[0]
            self._netName = self._netName.decode('utf-16')  
            self._deviceName = UnpackUnicodeZ('z', scContent[linkContentPos+devNameOffsetUnicode:])[0]
            self._deviceName = self._deviceName.decode('utf-16')               
        else:
            self._netName = UnpackZ('z', scContent[linkContentPos+netNameOffset:])[0].decode('ascii')
            self._deviceName = UnpackZ('z', scContent[linkContentPos+devNameOffset:])[0].decode('ascii')

    @property    
    def deviceName(self):
        return self._deviceName

    @property    
    def netName(self):
        return self._netName

    @property    
    def networkProviderType(self):
        return self._networkProviderType



def UnpackZ (fmt, buf) :
    """
    Unpack Null Terminated String
    """
    #logger.debug(bytes(buf))

    while True :
        pos = fmt.find ('z')
        if pos < 0 :
            break
        z_start = struct.calcsize (fmt[:pos])
        z_len = buf[z_start:].find(b'\0')
        #logger.debug(z_len)
        fmt = '%s%dsx%s' % (fmt[:pos], z_len, fmt[pos+1:])
        #logger.debug("fmt='{}', len={}".format(fmt, z_len))
    fmtlen = struct.calcsize(fmt)
    return struct.unpack (fmt, buf[0:fmtlen])


def UnpackUnicodeZ (fmt, buf) :
    """
    Unpack Null Terminated String
    """
    #logger.debug(bytes(buf))
    while True :
        pos = fmt.find ('z')
        if pos < 0 :
            break
        z_start = struct.calcsize (fmt[:pos])
        # look for null bytes by pairs
        z_len = 0
        for i in range(z_start,len(buf),2):
            if buf[i:i+2] == b'\0\0':
                z_len = i-z_start
                break

        fmt = '%s%dsxx%s' % (fmt[:pos], z_len, fmt[pos+1:])
       # logger.debug("fmt='{}', len={}".format(fmt, z_len))
    fmtlen = struct.calcsize(fmt)
    return struct.unpack (fmt, buf[0:fmtlen])

나는 이것이 다른 사람들에게도 도움이 되기를 바란다. 감사해요.




".exe" 파일을 여는 것만큼 쉽습니다. 여기서도 이를 위해 모듈을 사용할 예정입니다. 바로 가기를 만들고 원하는 폴더에 저장하기만 하면 됩니다. 그런 다음 Python 파일에서 먼저 모듈을 가져옵니다(이미 설치되어 있으므로 가져오기만 함). 그런 다음 변수(예: )를 사용하여 파일의 위치를 포함하는 문자열 값을 할당합니다. 원하는 응용프로그램의 바로 가기를 만들기만 하면 됩니다. 마지막으로 를 사용하여 바로 가기를 엽니다.

기억해야 할 점:

  1. 위치는 이중 반전 쉼표 내에 있어야 합니다.
  2. 가장 중요한 것은 속성을 여는 것입니다. 그런 다음 "상세 정보"를 엽니다. 거기서 바로 가기의 정확한 이름을 알 수 있습니다. 마지막으로 그 이름을 ".lnk"로 써주세요.

이제 절차를 완료했습니다. 도움이 되었으면 좋겠어요. 추가적인 도움을 위해, 나는 이것에 대한 나의 코드를 하단에 남길 것이다.

import os

path = "C:\\Users\\hello\\OneDrive\\Desktop\\Shortcuts\\OneNote for Windows 10.lnk"

os.startfile(path)

내 코드에서, 나는 변수로 사용했고 원노트의 바로 가기를 만들었다. 경로에서 원노트의 바로 가기 위치를 정의했다. 그래서 내가 사용할 때, 모듈은 가변 경로에 정의된 내 바로 가기 파일을 열 것이다.




저는 점점 더 많은 라이브러리를 계속 가져오고 싶지 않았고 테스트 기계에서 '쉘' 옵션이 얼룩덜룩했기 때문에 사용 가능한 답변 중 하나도 마음에 들지 않았습니다. 나는 ".lnk"를 읽은 다음 정규 표현을 사용하여 경로를 읽기로 선택했다. 저는 최근에 연 pdf 파일을 찾고 그 파일의 내용을 읽고 있습니다:

# Example file path to the shortcut
shortcut = "shortcutFileName.lnk"

# Open the lnk file using the ISO-8859-1 encoder to avoid errors for special characters
lnkFile = open(shortcut, 'r', encoding = "ISO-8859-1")

# Use a regular expression to parse out the pdf file on C:\
filePath = re.findall("C:.*?pdf", lnkFile.read(), flags=re.DOTALL)

# Close File
lnkFile.close()

# Read the pdf at the lnk Target
pdfFile = open(tmpFilePath[0], 'rb')

주석:

분명히 이것은 작동하지만 그에 따라 다른 파일 확장자를 지정해야 합니다.




이 작업은 모듈 없이도 가능하며, 이렇게 하면 바로 가기 파일의 대상이 있는 b 문자열이 반환됩니다. 기본적으로 파일을 읽기 이진 모드(모드)로 엽니다. 이 작업을 수행하기 위한 코드는 다음과 같습니다:

with open('programs.lnk - Copy','rb') as f:
    destination=f.read()

저는 현재 파이썬 3.9.2를 사용하고 있습니다. 만약 당신이 이것과 관련된 문제에 직면한다면, 제게 말해주시면 제가 그것을 고치도록 노력하겠습니다.




powershell을 사용하여 .lnk 파일에서 대상 경로를 읽는 파이썬의 보다 안정적인 솔루션입니다.

  • 표준 라이브러리만 사용하면 win32com과 같은 추가 종속성이 발생하지 않습니다
  • 이 접근법은 재러드의 대답과 함께 실패한 .nks와 함께 작동합니다,
  • 우리는 파일을 직접 읽는 것을 피하는데, 그것은 해킹처럼 느껴졌고, 때때로 실패했다
import subprocess


def get_target(link_path) -> (str, str):
    """
    Get the target & args of a Windows shortcut (.lnk)
    :param link_path: The Path or string-path to the shortcut, e.g. "C:\\Users\\Public\\Desktop\\My Shortcut.lnk"
    :return: A tuple of the target and arguments, e.g. ("C:\\Program Files\\My Program.exe", "--my-arg")
    """
    # get_target implementation by hannes, https://gist.github.com/Winand/997ed38269e899eb561991a0c663fa49
    ps_command = \
        "$WSShell = New-Object -ComObject Wscript.Shell;" \
        "$Shortcut = $WSShell.CreateShortcut(\"" + str(link_path) + "\"); " \
        "Write-Host $Shortcut.TargetPath ';' $shortcut.Arguments "
    output = subprocess.run(["powershell.exe", ps_command], capture_output=True)
    raw = output.stdout.decode('utf-8')
    launch_path, args = [x.strip() for x in raw.split(';', 1)]
    return launch_path, args

# to test
shortcut_file = r"C:\Users\REPLACE_WITH_USERNAME\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Accessibility\Narrator.lnk"
a, args = get_target(shortcut_file)
print(a)  # C:\WINDOWS\system32\narrator.exe 

(이전 버전의 파이썬에서 작동하기 위해 -> 타이핑 힌트를 제거할 수 있습니다)

나는 많은 단축키로 실행할 때 이것이 느리다는 것을 알아차렸다. jareds 메서드를 사용하여 결과가 없음인지 확인하고, 있으면 이 코드를 실행하여 대상 경로를 가져올 수 있습니다.




직접 정규식 기반 구문 분석(에서 제안됨)을 사용한 멋진 접근 방식은 내 경우의 모든 단축키에 대해 신뢰할 수 없었다. 이들 중 일부는 (MSI-installer에 의해 생성된)와 같은 상대 경로만 가지고 있으며, 파이썬에서 다루기 까다로운 넓은 문자와 함께 저장된다. 그래서 나는 사용하기 쉽고 나의 요구를 충족시키는 파이썬 모듈을 발견했다. 다음은 첫 번째 인수로 전달된 링크 파일의 대상을 보여주는 샘플 스크립트입니다:

import LnkParse3
import sys

with open(sys.argv[1], 'rb') as indata:
    lnk = LnkParse3.lnk_file(indata)
    print(lnk.lnk_command)



나는 ".lnk" 파일을 구문 분석하고 대상 파일 이름을 얻는 방법을 찾기 위해 이 스레드에 도착했다.

나는 다른 매우 간단한 해결책을 찾았다:

pip install comtypes

그리고나서

from comtypes.client import CreateObject
from comtypes.persist import IPersistFile
from comtypes.shelllink import ShellLink

# MAKE SURE THIS VAT CONTAINS A STRING AND NOT AN OBJECT OF 'PATH'
# I spent too much time figuring out the problem with .load(..) function ahead
pathStr="c:\folder\yourlink.lnk"

s = CreateObject(ShellLink)
p = s.QueryInterface(IPersistFile)
p.Load(pathStr, False)
print(s.GetPath())
print(s.GetArguments())
print(s.GetWorkingDirectory())
print(s.GetIconLocation())
try:
    # the GetDescription create exception in some of the links
    print(s.GetDescription())
except Exception as e:
    print(e)
print(s.Hotkey)
print(s.ShowCmd)

이 훌륭한 대답을 바탕으로...


반응형