Символы на окнах?

Кто-нибудь знает способ сделать / прочитать символические ссылки по версиям win32 из Python? В идеале должно быть минимальное количество кода для конкретной платформы, так как мне нужно, чтобы мое приложение было кросс-платформой.

  • Python win32print изменяет параметры расширенного принтера
  • Нужен способ получить текущую песню от Zune и проигрывателя Windows Media с помощью Python
  • Как я могу использовать pywin32 с virtualenv без необходимости включать папку узлов сайта хост-среды?
  • разные обои для каждого экрана для настройки нескольких мониторов в Windows
  • Как проверить, может ли файл быть создан в данной директории в MS XP / Vista?
  • win32: имитировать клик без имитации движения мыши?
  • win32: перемещение мыши с помощью SetCursorPos против mouse_event
  • Более быстрый способ чтения пикселя экрана в Python, чем PIL?
  • 8 Solutions collect form web for “Символы на окнах?”

    Файловая система NTFS имеет точки соединения, я думаю, вы можете использовать их вместо этого. Вы можете использовать API-интерфейс python win32 для этого, например

    import win32file win32file.CreateSymbolicLink(fileSrc, fileTarget, 1) 

    Если вы не хотите полагаться на модуль win32API, вы всегда можете использовать ctypes и напрямую обращаться к CreateSymbolicLink win32 API, например

     import ctypes kdll = ctypes.windll.LoadLibrary("kernel32.dll") kdll.CreateSymbolicLinkA("d:\\test.txt", "d:\\test_link.txt", 0) 

    MSDN ( http://msdn.microsoft.com/en-us/library/aa363866(VS.85).aspx ) говорит, что минимальным поддерживаемым клиентом является Windows Vista

    Кроме того : это также работает с каталогами (укажите это с третьим аргументом). С поддержкой юникода это выглядит так:

     kdll.CreateSymbolicLinkW(UR"D:\testdirLink", UR"D:\testdir", 1) 

    также см. Создание точки соединения NTFS в Python

    расширение python ntfslink

    Или, если вы хотите использовать pywin32, вы можете использовать ранее указанный метод и читать, использовать:

     from win32file import * from winioctlcon import FSCTL_GET_REPARSE_POINT __all__ = ['islink', 'readlink'] # Win32file doesn't seem to have this attribute. FILE_ATTRIBUTE_REPARSE_POINT = 1024 # To make things easier. REPARSE_FOLDER = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT) # For the parse_reparse_buffer function SYMBOLIC_LINK = 'symbolic' MOUNTPOINT = 'mountpoint' GENERIC = 'generic' def islink(fpath): """ Windows islink implementation. """ if GetFileAttributes(fpath) & REPARSE_FOLDER == REPARSE_FOLDER: return True return False def parse_reparse_buffer(original, reparse_type=SYMBOLIC_LINK): """ Implementing the below in Python: typedef struct _REPARSE_DATA_BUFFER { ULONG ReparseTag; USHORT ReparseDataLength; USHORT Reserved; union { struct { USHORT SubstituteNameOffset; USHORT SubstituteNameLength; USHORT PrintNameOffset; USHORT PrintNameLength; ULONG Flags; WCHAR PathBuffer[1]; } SymbolicLinkReparseBuffer; struct { USHORT SubstituteNameOffset; USHORT SubstituteNameLength; USHORT PrintNameOffset; USHORT PrintNameLength; WCHAR PathBuffer[1]; } MountPointReparseBuffer; struct { UCHAR DataBuffer[1]; } GenericReparseBuffer; } DUMMYUNIONNAME; } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; """ # Size of our data types SZULONG = 4 # sizeof(ULONG) SZUSHORT = 2 # sizeof(USHORT) # Our structure. # Probably a better way to iterate a dictionary in a particular order, # but I was in a hurry, unfortunately, so I used pkeys. buffer = { 'tag' : SZULONG, 'data_length' : SZUSHORT, 'reserved' : SZUSHORT, SYMBOLIC_LINK : { 'substitute_name_offset' : SZUSHORT, 'substitute_name_length' : SZUSHORT, 'print_name_offset' : SZUSHORT, 'print_name_length' : SZUSHORT, 'flags' : SZULONG, 'buffer' : u'', 'pkeys' : [ 'substitute_name_offset', 'substitute_name_length', 'print_name_offset', 'print_name_length', 'flags', ] }, MOUNTPOINT : { 'substitute_name_offset' : SZUSHORT, 'substitute_name_length' : SZUSHORT, 'print_name_offset' : SZUSHORT, 'print_name_length' : SZUSHORT, 'buffer' : u'', 'pkeys' : [ 'substitute_name_offset', 'substitute_name_length', 'print_name_offset', 'print_name_length', ] }, GENERIC : { 'pkeys' : [], 'buffer': '' } } # Header stuff buffer['tag'] = original[:SZULONG] buffer['data_length'] = original[SZULONG:SZUSHORT] buffer['reserved'] = original[SZULONG+SZUSHORT:SZUSHORT] original = original[8:] # Parsing k = reparse_type for c in buffer[k]['pkeys']: if type(buffer[k][c]) == int: sz = buffer[k][c] bytes = original[:sz] buffer[k][c] = 0 for b in bytes: n = ord(b) if n: buffer[k][c] += n original = original[sz:] # Using the offset and length's grabbed, we'll set the buffer. buffer[k]['buffer'] = original return buffer def readlink(fpath): """ Windows readlink implementation. """ # This wouldn't return true if the file didn't exist, as far as I know. if not islink(fpath): return None # Open the file correctly depending on the string type. handle = CreateFileW(fpath, GENERIC_READ, 0, None, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, 0) \ if type(fpath) == unicode else \ CreateFile(fpath, GENERIC_READ, 0, None, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, 0) # MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16384 = (16*1024) buffer = DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, None, 16*1024) # Above will return an ugly string (byte array), so we'll need to parse it. # But first, we'll close the handle to our file so we're not locking it anymore. CloseHandle(handle) # Minimum possible length (assuming that the length of the target is bigger than 0) if len(buffer) < 9: return None # Parse and return our result. result = parse_reparse_buffer(buffer) offset = result[SYMBOLIC_LINK]['substitute_name_offset'] ending = offset + result[SYMBOLIC_LINK]['substitute_name_length'] rpath = result[SYMBOLIC_LINK]['buffer'][offset:ending].replace('\x00','') if len(rpath) > 4 and rpath[0:4] == '\\??\\': rpath = rpath[4:] return rpath def realpath(fpath): from os import path while islink(fpath): rpath = readlink(fpath) if not path.isabs(rpath): rpath = path.abspath(path.join(path.dirname(fpath), rpath)) fpath = rpath return fpath def example(): from os import system, unlink system('cmd.exe /c echo Hello World > test.txt') system('mklink test-link.txt test.txt') print 'IsLink: %s' % islink('test-link.txt') print 'ReadLink: %s' % readlink('test-link.txt') print 'RealPath: %s' % realpath('test-link.txt') unlink('test-link.txt') unlink('test.txt') if __name__=='__main__': example() 

    Отрегулируйте атрибуты в CreateFile в соответствии с вашими потребностями, но для нормальной ситуации он должен работать. Не стесняйтесь улучшать его.

    Он также должен работать с папками, если вы используете MOUNTPOINT вместо SYMBOLIC_LINK.

    Вы можете проверить, что

     sys.getwindowsversion()[0] >= 6 

    если вы поместите это во что-то, что вы выпускаете, так как эта форма символической ссылки поддерживается только в Vista +.

    Проблема заключается в том, что здесь , например, объясняется, что поддержка Windows для функциональных возможностей символических ссылок зависит от версий Windows, так что, например, в Vista (с большим количеством работы) вы можете получить больше функциональности, чем в XP или 2000 (ничего AFAIK на других версии win32). Или у вас могут быть ярлыки вместо этого, которые, конечно же, имеют свой собственный набор ограничений и не «действительно» эквивалент символических ссылок Unix. Итак, вы должны точно указать, какие функции вы требуете, сколько из тех, кого вы готовы жертвовать на алтаре кросс-win32-операции и т. Д. – ТОГДА мы можем решить, как реализовать компромисс, который вы выбрали в терминах ctypes или win32all звонки … это наименьшее из этого, в некотором смысле.

    Я добавил следующее в Lib / site-packages / sitecustomize.py

     import os __CSL = None def symlink(source, link_name): '''symlink(source, link_name) Creates a symbolic link pointing to source named link_name''' global __CSL if __CSL is None: import ctypes csl = ctypes.windll.kernel32.CreateSymbolicLinkW csl.argtypes = (ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint32) csl.restype = ctypes.c_ubyte __CSL = csl flags = 0 if source is not None and os.path.isdir(source): flags = 1 if __CSL(link_name, source, flags) == 0: raise ctypes.WinError() os.symlink = symlink 

    os.symlink работает на Python 3.3 с использованием Windows 8.1 с файловой системой NTFS.

    Использование команды mklink в подпроцессе создать ссылку.

     from subprocess import call call(['mklink', 'LINK', 'TARGET'], shell=True) 

    Код Juntalis не обрабатывает Unicode, поэтому я модифицировал его для использования ctypes, а также упростил его с помощью struct. Я также консультировался с кодом с помощью функции struct как аргумент функции с модулем ctypes python

     import os, ctypes, struct from ctypes import windll, wintypes FSCTL_GET_REPARSE_POINT = 0x900a8 FILE_ATTRIBUTE_READONLY = 0x0001 FILE_ATTRIBUTE_HIDDEN = 0x0002 FILE_ATTRIBUTE_DIRECTORY = 0x0010 FILE_ATTRIBUTE_NORMAL = 0x0080 FILE_ATTRIBUTE_REPARSE_POINT = 0x0400 GENERIC_READ = 0x80000000 GENERIC_WRITE = 0x40000000 OPEN_EXISTING = 3 FILE_READ_ATTRIBUTES = 0x80 FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000 INVALID_HANDLE_VALUE = wintypes.HANDLE(-1).value INVALID_FILE_ATTRIBUTES = 0xFFFFFFFF FILE_FLAG_OPEN_REPARSE_POINT = 2097152 FILE_FLAG_BACKUP_SEMANTICS = 33554432 # FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTI FILE_FLAG_REPARSE_BACKUP = 35651584 GetFileAttributes = windll.kernel32.GetFileAttributesW _CreateFileW = windll.kernel32.CreateFileW _DevIoCtl = windll.kernel32.DeviceIoControl _DevIoCtl.argtypes = [ wintypes.HANDLE, #HANDLE hDevice wintypes.DWORD, #DWORD dwIoControlCode wintypes.LPVOID, #LPVOID lpInBuffer wintypes.DWORD, #DWORD nInBufferSize wintypes.LPVOID, #LPVOID lpOutBuffer wintypes.DWORD, #DWORD nOutBufferSize ctypes.POINTER(wintypes.DWORD), #LPDWORD lpBytesReturned wintypes.LPVOID] #LPOVERLAPPED lpOverlapped _DevIoCtl.restype = wintypes.BOOL def islink(path): assert os.path.isdir(path), path if GetFileAttributes(path) & FILE_ATTRIBUTE_REPARSE_POINT: return True else: return False def DeviceIoControl(hDevice, ioControlCode, input, output): # DeviceIoControl Function # http://msdn.microsoft.com/en-us/library/aa363216(v=vs.85).aspx if input: input_size = len(input) else: input_size = 0 if isinstance(output, int): output = ctypes.create_string_buffer(output) output_size = len(output) assert isinstance(output, ctypes.Array) bytesReturned = wintypes.DWORD() status = _DevIoCtl(hDevice, ioControlCode, input, input_size, output, output_size, bytesReturned, None) print "status(%d)" % status if status != 0: return output[:bytesReturned.value] else: return None def CreateFile(path, access, sharemode, creation, flags): return _CreateFileW(path, access, sharemode, None, creation, flags, None) SymbolicLinkReparseFormat = "LHHHHHHL" SymbolicLinkReparseSize = struct.calcsize(SymbolicLinkReparseFormat); def readlink(path): """ Windows readlink implementation. """ # This wouldn't return true if the file didn't exist, as far as I know. assert islink(path) assert type(path) == unicode # Open the file correctly depending on the string type. hfile = CreateFile(path, GENERIC_READ, 0, OPEN_EXISTING, FILE_FLAG_REPARSE_BACKUP) # MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16384 = (16*1024) buffer = DeviceIoControl(hfile, FSCTL_GET_REPARSE_POINT, None, 16384) CloseHandle(hfile) # Minimum possible length (assuming length of the target is bigger than 0) if not buffer or len(buffer) < 9: return None # Parse and return our result. # typedef struct _REPARSE_DATA_BUFFER { # ULONG ReparseTag; # USHORT ReparseDataLength; # USHORT Reserved; # union { # struct { # USHORT SubstituteNameOffset; # USHORT SubstituteNameLength; # USHORT PrintNameOffset; # USHORT PrintNameLength; # ULONG Flags; # WCHAR PathBuffer[1]; # } SymbolicLinkReparseBuffer; # struct { # USHORT SubstituteNameOffset; # USHORT SubstituteNameLength; # USHORT PrintNameOffset; # USHORT PrintNameLength; # WCHAR PathBuffer[1]; # } MountPointReparseBuffer; # struct { # UCHAR DataBuffer[1]; # } GenericReparseBuffer; # } DUMMYUNIONNAME; # } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; # Only handle SymbolicLinkReparseBuffer (tag, dataLength, reserver, SubstituteNameOffset, SubstituteNameLength, PrintNameOffset, PrintNameLength, Flags) = struct.unpack(SymbolicLinkReparseFormat, buffer[:SymbolicLinkReparseSize]) print tag, dataLength, reserver, SubstituteNameOffset, SubstituteNameLength start = SubstituteNameOffset + SymbolicLinkReparseSize actualPath = buffer[start : start + SubstituteNameLength].decode("utf-16") # This utf-16 string is null terminated index = actualPath.find(u"\0") assert index > 0 if index > 0: actualPath = actualPath[:index] if actualPath.startswith(u"?\\"): return actualPath[2:] else: return actualPath 

    вот ссылка, содержащая все методы kernel32.dll

    http://www.geoffchappell.com/studies/windows/win32/kernel32/api/

    Я использовал CreateHardLinkA для Windows xp sp3, это сработало!

    import ctypes, если os.path.exists (link_file): os.remove (link_file)

     dll = ctypes.windll.LoadLibrary("kernel32.dll") dll.CreateHardLinkA(link_file, _log_filename, 0) 
    Python - лучший язык программирования в мире.