#!/usr/bin/env python3
"""
db_lock_printer.py - 打印数据库锁定进程的函数

提供函数来打印锁定 SQLite 数据库的进程信息
"""

import subprocess
import os

def print_locking_processes(db_path):
    """
    打印锁定指定数据库文件的进程信息
    
    参数:
        db_path (str): 数据库文件路径
    
    功能:
        - 使用 PowerShell 命令查找锁定文件的进程
        - 直接打印锁定进程信息
        - 处理可能的错误，确保函数不会崩溃
    """
    print(f"正在查找锁定数据库 {db_path} 的进程...")
    
    # 方法1: 使用 PowerShell 的 Get-Process 和 Handle 模块
    try:
        # 使用 PowerShell 命令查找所有进程，然后检查它们是否打开了指定文件
        ps_command = f"""
        Get-Process | ForEach-Object {{
            $process = $_
            try {{
                $process.Modules | ForEach-Object {{
                    if ($_.FileName -eq '{db_path.replace(chr(92), chr(92)*2)}') {{
                        $process.Name + ' (PID: ' + $process.Id + ')'
                    }}
                }}
            }} catch {{}}
        }}
        """
        
        result = subprocess.run(
            ['powershell', '-Command', ps_command],
            capture_output=True,
            text=True,
            timeout=10
        )
        
        if result.stdout.strip():
            print("锁定进程:")
            for line in result.stdout.strip().split('\n'):
                if line.strip():
                    print(f"  - {line.strip()}")
            return
    except Exception as e:
        print(f"方法1出错: {e}")
    
    # 方法2: 使用 PowerShell 的 WMI 查询
    try:
        ps_command = f"""
        Get-WmiObject -Class Win32_Process | ForEach-Object {{
            $process = $_
            try {{
                $process.Handle | ForEach-Object {{
                    try {{
                        $handle = $_
                        $filePath = (New-Object System.IO.FileInfo $handle).FullName
                        if ($filePath -eq '{db_path.replace(chr(92), chr(92)*2)}') {{
                            $process.Name + ' (PID: ' + $process.ProcessId + ')'
                        }}
                    }} catch {{}}
                }}
            }} catch {{}}
        }}
        """
        
        result = subprocess.run(
            ['powershell', '-Command', ps_command],
            capture_output=True,
            text=True,
            timeout=10
        )
        
        if result.stdout.strip():
            print("锁定进程 (使用 WMI):")
            for line in result.stdout.strip().split('\n'):
                if line.strip():
                    print(f"  - {line.strip()}")
            return
    except Exception as e:
        print(f"方法2出错: {e}")
    
    # 方法3: 尝试使用 tasklist 和 handle 命令（如果可用）
    try:
        # 检查 handle 命令是否可用
        handle_check = subprocess.run(
            ['powershell', '-Command', 'Get-Command handle -ErrorAction SilentlyContinue'],
            capture_output=True,
            text=True
        )
        
        if handle_check.stdout.strip():
            # 使用 handle 命令
            ps_command = f"handle '{db_path}'"
            result = subprocess.run(
                ['powershell', '-Command', ps_command],
                capture_output=True,
                text=True,
                timeout=10
            )
            
            if result.stdout.strip():
                print("锁定进程 (使用 handle 命令):")
                lines = result.stdout.strip().split('\n')
                pids = []
                
                for line in lines:
                    if line.strip() and not line.startswith("Handle v") and not line.startswith("Sysinternals") and not line.startswith("Nthandle v"):
                        print(f"  - {line.strip()}")
                        # 提取 PID
                        if "pid:" in line:
                            try:
                                pid = line.split("pid:")[1].split("type:")[0].strip()
                                if pid not in pids:
                                    pids.append(pid)
                            except Exception:
                                pass
                
                # 获取每个 PID 的命令行
                for pid in pids:
                    try:
                        # 使用更直接的命令获取命令行，避免截断
                        cmd_command = f"""
                        $process = Get-WmiObject -Class Win32_Process -Filter 'ProcessId = {pid}';
                        if ($process) {{
                            $process.CommandLine
                        }}
                        """
                        cmd_result = subprocess.run(
                            ['powershell', '-Command', cmd_command],
                            capture_output=True,
                            text=True,
                            timeout=5
                        )
                        if cmd_result.stdout.strip():
                            cmd_line = cmd_result.stdout.strip()
                            print(f"  进程 {pid} 的命令行: {cmd_line}")
                    except Exception as e:
                        print(f"  获取进程 {pid} 命令行时出错: {e}")
                return
    except Exception as e:
        print(f"方法3出错: {e}")
    
    # 方法4: 显示所有 Python 进程，因为它们最可能锁定数据库
    try:
        ps_command = "Get-Process python | Select-Object Name, Id, Path"
        result = subprocess.run(
            ['powershell', '-Command', ps_command],
            capture_output=True,
            text=True,
            timeout=10
        )
        
        if result.stdout.strip():
            print("运行中的 Python 进程（可能锁定数据库）:")
            print(result.stdout.strip())
            return
    except Exception as e:
        print(f"方法4出错: {e}")
    
    # 如果所有方法都失败
    print("无法确定锁定进程，但数据库确实被锁定")
    print("建议：")
    print("1. 检查是否有多个 Python 脚本在运行")
    print("2. 重启电脑或结束可能的锁定进程")
    print("3. 考虑使用 SQLite 的 WAL 模式来减少锁定问题")


if __name__ == "__main__":
    # 测试代码
    db_path = r"\\ll\D\xtrssvjj\db\dpd.db"
    print_locking_processes(db_path)