最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python使用ctypes調(diào)用Windows API清空回收站

 更新時(shí)間:2026年04月28日 09:33:15   作者:張賜榮  
很多朋友剛接觸 Windows 編程時(shí),總覺得調(diào)用系統(tǒng)底層 API 是一件很高深、非常復(fù)雜的事情,感到很害怕,本文就以實(shí)現(xiàn) Windows 上的 清空回收站功能為例,從零開始詳解 Python 如何通過 ctypes 庫跟 Windows API 進(jìn)行交互調(diào)用,需要的朋友可以參考下

引言

很多朋友剛接觸 Windows 編程時(shí),總覺得調(diào)用系統(tǒng)底層 API 是一件很高深、非常復(fù)雜的事情,感到很害怕。其實(shí) Python 自帶的 ctypes 庫就能讓咱們輕松調(diào)用 C 語言導(dǎo)出的動態(tài)鏈接庫函數(shù),本文就以實(shí)現(xiàn) Windows 上的 “清空回收站”功能為例,從零開始詳解 Python 如何通過 ctypes 庫跟 Windows API 進(jìn)行交互調(diào)用。

一、整體思路

清空回收站,不能直接調(diào)用 SHEmptyRecycleBin 就完事了,我們要編寫一個(gè)更智能更穩(wěn)健的程序,能準(zhǔn)確判斷是否真正成功清空:

  1. 清空前先查詢回收站里有多少文件,就知道有沒有必要清空了。
  2. 調(diào)用 Windows 提供的清空回收站 API,執(zhí)行清理。
  3. 清空后再次查詢文件數(shù)量,對比前后變化,判斷用戶是真的清空了,還是中途取消了(比如在系統(tǒng)彈出的確認(rèn)對話框里點(diǎn)了“否”)。

這種執(zhí)行后查詢驗(yàn)證結(jié)果的思路,在實(shí)際開發(fā)中非常實(shí)用,我們不能盲目依賴 API 的返回值,比如 SHEmptyRecycleBin 的返回值,僅表示函數(shù)是不是成功調(diào)用了,不表示用戶點(diǎn)擊了確定清空,或執(zhí)行過程中是否取消了操作,所以說,它的結(jié)果并不表示業(yè)務(wù)是否成功,也就是是否真正清空了回收站。

二、ctypes 是什么?怎么用?

ctypes 是 Python 內(nèi)置的庫,這個(gè)庫能把 Python 的數(shù)據(jù)類型轉(zhuǎn)換成 C 語言的數(shù)據(jù)類型,然后調(diào)用 DLL 或共享庫中的函數(shù)。簡單說就是讓 Python 可以直接調(diào)用 Windows 系統(tǒng)底層函數(shù)。

2.1 加載 DLL

Windows API 大多存放在 kernel32.dll、user32.dll、shell32.dll 等系統(tǒng)核心動態(tài)鏈接庫文件中。這里咱們要用的兩個(gè)函數(shù)都在 shell32.dll 里。

import ctypes shell32 = ctypes.WinDLL('shell32', use_last_error=True) 
  • WinDLL 表示加載一個(gè) Windows DLL,默認(rèn)使用 stdcall 調(diào)用約定(Windows API 的標(biāo)準(zhǔn))。
  • use_last_error=True 讓 ctypes 在出錯(cuò)時(shí)保存 Windows 錯(cuò)誤碼,方便調(diào)試。

2.2 定義函數(shù)原型(參數(shù)類型和返回值類型)

這是新手最容易踩坑的地方。Windows API 函數(shù)是用 C 寫的,Python 并不知道它接收什么參數(shù),所以我們必須顯式聲明參數(shù)類型(argtypes)和返回值類型(restype)。

例如咱們用到的清空函數(shù)聲明(來自 Win32 SDK):

HRESULT SHEmptyRecycleBinW(HWND hwnd, LPCWSTR pszRootPath, DWORD dwFlags);

對應(yīng)到 Python 就是:

shell32.SHEmptyRecycleBinW.argtypes = [wintypes.HWND, wintypes.LPCWSTR, wintypes.DWORD]
shell32.SHEmptyRecycleBinW.restype = ctypes.HRESULT

在這里

  • HWND 是窗口句柄(可理解為窗口的身份證),傳 None 表示沒有父級窗口。
  • LPCWSTR 是寬字符串指針,對應(yīng) Python 的 str (ctypes 會自動轉(zhuǎn)成 wchar_t*)。
  • DWORD 是 32 位無符號整數(shù)。
  • HRESULT 是一個(gè) 32 位整數(shù),一般來講 0(即 S_OK)表示成功。

2.3 定義結(jié)構(gòu)體

很多 Windows API 都要傳結(jié)構(gòu)體,比如我們這里用到的查詢回收站信息函數(shù)要用到 SHQUERYRBINFO 結(jié)構(gòu)體。在 ctypes 中定義C語言結(jié)構(gòu)體還是相對比較容易的:只要繼承 ctypes.Structure,然后寫一個(gè) _fields_ 列表,每個(gè)元素是 (字段名, 字段類型)。

class SHQUERYRBINFO(ctypes.Structure):
    _fields_ = [
        ("cbSize", wintypes.DWORD),       # 結(jié)構(gòu)體自身大小
        ("i64Size", ctypes.c_longlong),   # 總大?。ㄗ止?jié))
        ("i64NumItems", ctypes.c_longlong) # 項(xiàng)目總數(shù)
    ]

C 語言的 __int64 對應(yīng) Python 的 ctypes.c_longlong(8 字節(jié)有符號整數(shù))。
另外,考慮到向后兼容,這個(gè)結(jié)構(gòu)體的第一個(gè)成員 cbSize 必須在調(diào)用前賦值為結(jié)構(gòu)體占用的字節(jié)數(shù),很多 Windows API 都這樣設(shè)計(jì)。

rb_info = SHQUERYRBINFO()
rb_info.cbSize = ctypes.sizeof(SHQUERYRBINFO)

三、查詢回收站信息

封裝一個(gè) get_recycle_bin_count() 函數(shù),返回所有驅(qū)動器回收站里的文件總數(shù)。

  • 調(diào)用 SHQueryRecycleBinW(None, pointer_to_struct)
    第一個(gè)參數(shù)傳 None 表示“查詢所有驅(qū)動器的總回收站”。也可以傳 "C:\\" 這樣的路徑,查詢指定盤。
  • 第二個(gè)參數(shù)需要傳結(jié)構(gòu)體的指針,用 ctypes.byref() 獲得。
  • 函數(shù)執(zhí)行后,結(jié)構(gòu)體的 i64NumItems 字段就被填上了項(xiàng)目總數(shù)。
hr = shell32.SHQueryRecycleBinW(None, ctypes.byref(rb_info))
if hr == 0:   # 成功
    return rb_info.i64NumItems
else:
    return -1

為什么函數(shù)名最后總要帶上 W 字母?
那是因?yàn)?Windows API 有兩套字符編碼:A(ANSI)和 W(Unicode)?,F(xiàn)代 Windows 內(nèi)部完全使用 Unicode,所以咱們直接調(diào)用 W 版本,用 Python 的 str 傳參即可。

四、調(diào)用函數(shù)清空回收站

hr = shell32.SHEmptyRecycleBinW(None, None, 0)
  • 第一個(gè)參數(shù) hwndNone 表示沒有父窗口。
  • 第二個(gè)參數(shù) pszRootPathNone 表示清空所有驅(qū)動器的回收站。
  • 第三個(gè)參數(shù) dwFlags0 表示使用系統(tǒng)默認(rèn)行為,也就是彈出確認(rèn)對話框并顯示進(jìn)度。

聰明的你一定想到了:如果用戶在確認(rèn)對話框點(diǎn)了“否”,API 會返回什么?
經(jīng)過實(shí)測,SHEmptyRecycleBinW 在這種情況下依然返回 S_OK(成功)!所以僅靠返回值無法區(qū)分“用戶取消了”和“真的清空了”。

因此我們的代碼要做更嚴(yán)謹(jǐn)?shù)呐袛啵?/p>

  1. 清空前記錄文件數(shù) count_before。
  2. 調(diào)用清空 API。
  3. 清空后再次查詢文件數(shù) count_after
  4. 綜合判斷:
    • 如果 hr == 0count_after < count_before(文件數(shù)減少了),說明真的刪除了,于是提示“清空成功”。
    • 如果 hr == 0count_after == count_before,說明用戶取消了確認(rèn)對話框所以提示“操作已取消”。
    • 如果 hr != 0,說明 API 調(diào)用失?。ɡ鐧?quán)限不足),應(yīng)顯示錯(cuò)誤代碼。

另,如果清空前文件數(shù)就是 0,直接彈窗告知“無需操作”。

五、完整代碼

可以直接把下面的代碼復(fù)制保存為 empty_recycle_bin.pyw 雙擊運(yùn)行,需要安裝 Python3。

empty_recycle_bin.pyw:

import ctypes
from ctypes import wintypes
# <-定義結(jié)構(gòu)體 ->
# SHQUERYRBINFO 結(jié)構(gòu)體用于接收回收站信息
class SHQUERYRBINFO(ctypes.Structure):
    _fields_ = [
        ("cbSize", wintypes.DWORD),      # 結(jié)構(gòu)體大小
        ("i64Size", ctypes.c_longlong),  # 回收站內(nèi)文件總大小 (字節(jié))
        ("i64NumItems", ctypes.c_longlong) # 回收站內(nèi)項(xiàng)目總數(shù)
    ]
# <- 定義常量 ->
MB_OK = 0x00000000
MB_ICONINFORMATION = 0x00000040
MB_ICONWARNING = 0x00000030
MB_ICONERROR = 0x00000010
def get_recycle_bin_count():
    """獲取所有驅(qū)動器回收站的文件總數(shù)"""
    shell32 = ctypes.WinDLL('shell32', use_last_error=True)
    # 定義 SHQueryRecycleBinW
    # HRESULT SHQueryRecycleBinW(LPCWSTR pszRootPath, LPSHQUERYRBINFO pSHQueryRBINFO);
    shell32.SHQueryRecycleBinW.argtypes = [wintypes.LPCWSTR, ctypes.POINTER(SHQUERYRBINFO)]
    shell32.SHQueryRecycleBinW.restype = ctypes.HRESULT
    rb_info = SHQUERYRBINFO()
    rb_info.cbSize = ctypes.sizeof(SHQUERYRBINFO)
    # pszRootPath 為 None 表示查詢所有驅(qū)動器
    hr = shell32.SHQueryRecycleBinW(None, ctypes.byref(rb_info))
    if hr == 0:
        return rb_info.i64NumItems
    return -1
def empty_recycle_bin():
    shell32 = ctypes.WinDLL('shell32', use_last_error=True)
    user32 = ctypes.WinDLL('user32', use_last_error=True)
    # 定義 SHEmptyRecycleBinW
    shell32.SHEmptyRecycleBinW.argtypes = [wintypes.HWND, wintypes.LPCWSTR, wintypes.DWORD]
    shell32.SHEmptyRecycleBinW.restype = ctypes.HRESULT
    # 記錄執(zhí)行前的項(xiàng)目數(shù)
    count_before = get_recycle_bin_count()
    if count_before == 0:
        user32.MessageBoxW(None, "回收站已經(jīng)是空的,無需操作。", "提示", MB_OK | MB_ICONINFORMATION)
        return
    # 調(diào)用 API 執(zhí)行清空 (dwFlags=0, 顯示系統(tǒng)確認(rèn)對話框)
    hr = shell32.SHEmptyRecycleBinW(None, None, 0)
    # 記錄執(zhí)行后的項(xiàng)目數(shù)
    count_after = get_recycle_bin_count()
    # 綜合判斷
    # 邏輯:API必須成功 AND (文件數(shù)減少了 OR 文件數(shù)變?yōu)榱?)
    if hr == 0:
        if count_after < count_before and count_after >= 0:
            user32.MessageBoxW(None, f"清空成功!\n文件數(shù)從 {count_before} 降至 {count_after}。", "成功", MB_OK | MB_ICONINFORMATION)
        elif count_before != -1 and count_after == count_before:
            # API 返回了成功,但數(shù)量沒變,說明用戶在系統(tǒng)對話框點(diǎn)了“否”
            user32.MessageBoxW(None, "操作已取消或未執(zhí)行刪除。", "提示", MB_OK | MB_ICONWARNING)
        else:
            user32.MessageBoxW(None, "回收站狀態(tài)未發(fā)生顯著變化。", "提示", MB_OK | MB_ICONWARNING)
    else:
        # 如果返回了非 0 的 HRESULT
        err_hex = hex(hr & 0xFFFFFFFF)
        user32.MessageBoxW(None, f"操作失敗。錯(cuò)誤代碼: {err_hex}", "錯(cuò)誤", MB_OK | MB_ICONERROR)
if __name__ == "__main__":
    empty_recycle_bin()

: 執(zhí)行腳本的 “python.exe” 要和調(diào)用的 DLL 位數(shù)相同,比如都是64位的。

通過上面這個(gè)例子,就應(yīng)該意識到了,Python + ctypes 和 comtypes 幾乎可以調(diào)用所有 Windows API,借助Python 調(diào)用 C dll 把系統(tǒng)底層能力融入到自己的程序中,其實(shí)也沒有想象中的那么難。

以上就是Python使用ctypes調(diào)用Windows API清空回收站的詳細(xì)內(nèi)容,更多關(guān)于Python ctypes調(diào)用Windows API的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 如何使用 Python 中的功能和庫創(chuàng)建 n-gram的過程

    如何使用 Python 中的功能和庫創(chuàng)建 n-gram的過程

    在計(jì)算語言學(xué)中,n-gram 對于語言處理、上下文和語義分析非常重要,本文將討論如何使用 Python 中的功能和庫創(chuàng)建 n-gram,感興趣的朋友一起看看吧
    2023-09-09
  • Python 裝飾器使用詳解

    Python 裝飾器使用詳解

    裝飾器是Python語言中的高級語法。主要的功能是對一個(gè)函數(shù)、方法、或者類進(jìn)行加工,作用是為已經(jīng)存在的對象添加額外的功能,提升代碼的可讀性。裝飾器是設(shè)計(jì)模式的一種,被用于有切面需求的場景,較為經(jīng)典的有插入日志、性能測試、事務(wù)處理等
    2017-07-07
  • 如何利用python在剪貼板上讀取/寫入數(shù)據(jù)

    如何利用python在剪貼板上讀取/寫入數(shù)據(jù)

    說起處理數(shù)據(jù)就離不開導(dǎo)入導(dǎo)出,而我們使用Pandas時(shí)候最常用的就是read_excel、read_csv了,下面這篇文章主要給大家介紹了關(guān)于如何利用python在剪貼板上讀取/寫入數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下
    2022-07-07
  • Python數(shù)據(jù)分析之使用scikit-learn構(gòu)建模型

    Python數(shù)據(jù)分析之使用scikit-learn構(gòu)建模型

    這篇文章主要介紹了Python數(shù)據(jù)分析之使用scikit-learn構(gòu)建模型,sklearn提供了model_selection模型選擇模塊、preprocessing數(shù)據(jù)預(yù)處理模塊、decompisition特征分解模塊,更多相關(guān)內(nèi)容需要朋友可以參考下面文章內(nèi)容
    2022-08-08
  • Python如何使用函數(shù)做字典的值

    Python如何使用函數(shù)做字典的值

    這篇文章主要介紹了Python如何使用函數(shù)做字典的值,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • 記錄一下scrapy中settings的一些配置小結(jié)

    記錄一下scrapy中settings的一些配置小結(jié)

    這篇文章主要介紹了記錄一下scrapy中settings的一些配置小結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • python中28種極坐標(biāo)繪圖函數(shù)總結(jié)

    python中28種極坐標(biāo)繪圖函數(shù)總結(jié)

    這篇文章主要為大家詳細(xì)介紹了python中28種極坐標(biāo)繪圖函數(shù)的用法,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以跟隨小編一起了解一下
    2023-09-09
  • vscode帶命令行參數(shù)進(jìn)行調(diào)試的方法

    vscode帶命令行參數(shù)進(jìn)行調(diào)試的方法

    文章介紹了如何在VSCode中使用命令行參數(shù)進(jìn)行調(diào)試,并描述了如何通過修改`launch.json`文件來簡化調(diào)試過程
    2025-01-01
  • Python使用psycopg2連接PostgreSQL數(shù)據(jù)庫的步驟

    Python使用psycopg2連接PostgreSQL數(shù)據(jù)庫的步驟

    PostgreSQL 是一個(gè)廣泛使用的開源對象關(guān)系數(shù)據(jù)庫系統(tǒng),以其強(qiáng)大的功能和靈活性而聞名,Python,作為一種流行的編程語言,提供了多種方式與數(shù)據(jù)庫交互,其中 psycopg2 是連接 PostgreSQL 數(shù)據(jù)庫的流行選擇之一,本文介紹了Python使用psycopg2連接PostgreSQL數(shù)據(jù)庫的步驟
    2024-12-12
  • 使用Python對Excel數(shù)據(jù)讀取與保存的全面指南

    使用Python對Excel數(shù)據(jù)讀取與保存的全面指南

    在數(shù)據(jù)分析與處理工作中,Excel文件是最常見的數(shù)據(jù)源之一,本文將詳細(xì)介紹如何使用Python的Pandas庫進(jìn)行Excel文件的讀寫操作,涵蓋常用函數(shù)、典型應(yīng)用場景、實(shí)例演示及常見問題解決方案,需要的朋友可以參考下
    2025-12-12

最新評論

安陆市| 吉木乃县| 湖口县| 安远县| 凌源市| 福建省| 济南市| 资源县| 凌源市| 镇平县| 灯塔市| 金沙县| 井冈山市| 呼图壁县| 滨州市| 前郭尔| 武平县| 深圳市| 罗平县| 西吉县| 精河县| 平泉县| 山阴县| 呼伦贝尔市| 周口市| 响水县| 鸡西市| 崇明县| 阿勒泰市| 雷州市| 扎赉特旗| 马鞍山市| 涞源县| 延川县| 桂平市| 兴宁市| 龙岩市| 东乌珠穆沁旗| 高淳县| 张家界市| 饶河县|