Windows API

来自百合仙子's Wiki
跳转到导航 跳转到搜索

此条目在于指出 Windows API 中需要特别注意的地方,以及一些代码示例。

进程相关

CreateProcess

该函数的第一个参数指明可执行文件。如果是相对路径,“the function uses the current drive and current directory to complete the specification. The function will not use the search path”[1]。“If the file name does not contain an extension, .exe is assumed.”“If the file name does not contain a directory path, the system searches for the executable file in the following sequence:”

  1. The directory from which the application loaded.
  2. The current directory for the parent process.
  3. The 32-bit Windows system directory. Use the GetSystemDirectory function to get the path of this directory.
  4. The 16-bit Windows system directory. There is no function that obtains the path of this directory, but it is searched. The name of this directory is System.
  5. The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
  6. The directories that are listed in the PATH environment variable. Note that this function does not search the per-application path specified by the App Paths registry key. To include this per-application path in the search sequence, use the ShellExecute function.

也就是说,在不指定路径的情况下,系统目录下的程序享有优先权,而 PATH 环境变量在其次。

文件系统

文件变动通知

使用 Python ctypes 监视指定目录中的文件/目录的写操作。主要使用了 ReadDirectoryChangesW [2]API。

#!/usr/bin/env python3

import struct
import ctypes
kernel32 = ctypes.windll.kernel32

class FileWatcher:
  def __init__(self, path):
    self.d_hdl = kernel32.CreateFileW(
      path,
      1 | 0x80000000, # FILE_LIST_DIRECTORY | GENERIC_READ
      7, # FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE
      0, # NULL
      3, # OPEN_EXISTING
      128 | 0x02000000, # FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS
      0, # NULL
    )

    self.bufsize = 4096
    self.buf = ctypes.create_string_buffer(b'\0' * (self.bufsize-1))
    # DWORD is unsigned long http://stackoverflow.com/a/39430/296473
    self.datalen = ctypes.c_ulong()

  def read(self):
    ret = kernel32.ReadDirectoryChangesW(
      self.d_hdl,
      self.buf,
      self.bufsize,
      0, # not bWatchSubtree
      # FILE_NOTIFY_CHANGE_LAST_WRITE
      # This happens when a write is performed (to a file or directory)
      0x00000010,
      ctypes.byref(self.datalen),
      0,
      0,
    )
    if ret == 0:
      raise RuntimeError('ReadDirectoryChangesW failed')

    p = 0
    buf = self.buf.raw
    ret = []
    while True:
      namestart = p + 12
      offset, action, filenamelen = struct.unpack('=LLL', buf[p:namestart])
      ret.append(buf[namestart:namestart+filenamelen].decode('utf-16le'))
      if offset == 0:
        break
      p += offset
    return ret

  def __del__(self):
    kernel32.CloseHandle(self.d_hdl)

if __name__ == '__main__':
  w = FileWatcher(r'd:\test')
  while True:
    print(w.read())

图形相关

LoadImage

只接受 BMP 图像。

参见

外部链接

参考资料

  1. MSDN: ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/dllproc/base/createprocess.htm
  2. ReadDirectoryChangesW function (Windows)