2010-08-30 106 views
8

目前我使用這個功能,可以根據JCL代碼,其正常工作:如何使用Delphi來測試目錄是否可寫?

function IsDirectoryWriteable(const AName: string): Boolean; 
var 
    FileName: PWideChar; 
    H: THandle; 
begin 
    FileName := PWideChar(IncludeTrailingPathDelimiter(AName) + 'chk.tmp'); 

    H := CreateFile(FileName, GENERIC_READ or GENERIC_WRITE, 0, nil, 
    CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY or FILE_FLAG_DELETE_ON_CLOSE, 0); 

    Result := H <> INVALID_HANDLE_VALUE; 

    DeleteFile(FileName); 
end; 

有什麼我可以與標誌改進? 測試可以在沒有實際創建文件的情況下完成嗎? 或者這個功能甚至已經在RTL或Jedi庫之一中可用?

+3

不爲你的代碼工作?有沒有關於你不喜歡的這種方法?這確實是一種非常簡單(最簡單的)測試目錄寫入訪問的方式。儘管我從來沒有在Windows安全方面做過很多工作,但我猜想另一種方法是使用'GetFileSecurity'函數。 – 2010-08-30 10:01:15

+0

@Andreas看到我的編輯 - 如果我可以通過調用一個現有的庫函數來替換這個函數(甚至可能支持多平臺),這肯定會有所改進。 – mjn 2010-08-30 11:41:04

+0

我實際上看不到任何那些不在RTL中的東西 - 這是JCL調用嗎? – 2010-08-30 13:01:31

回答

15

實際上,寫入目錄是確定目錄是否可寫的最簡單方法。有太多的安全選項單獨檢查,即使這樣你可能會錯過一些東西。

您還需要在調用DeleteFile()之前關閉打開的句柄。因爲您正在使用FILE_FLAG_DELETE_ON_CLOSE標誌,所以您無需執行任何操作。

順便說一句,你的代碼中有一個小錯誤。您正在創建一個臨時String並將其分配給一個PWideChar,但是在實際使用PWideChar之前,String超出了範圍,釋放了內存。你的FileName變量應該是一個String而不是一個PWideChar。在調用CreateFile()時進行類型轉換,而不是之前。

試試這個:

function IsDirectoryWriteable(const AName: string): Boolean; 
var 
    FileName: String; 
    H: THandle; 
begin 
    FileName := IncludeTrailingPathDelimiter(AName) + 'chk.tmp'; 
    H := CreateFile(PChar(FileName), GENERIC_READ or GENERIC_WRITE, 0, nil, 
    CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY or FILE_FLAG_DELETE_ON_CLOSE, 0); 
    Result := H <> INVALID_HANDLE_VALUE; 
    if Result then CloseHandle(H); 
end; 
+0

+1(個人而言,我會使用'HFILE'而不是'THandle',但當然這只是一個問題。) – 2010-09-01 00:38:44

+1

臨時字符串不會超出範圍。臨時的範圍與函數中的其他所有內容相同。它只在函數退出時被銷燬,或者臨時需要重新用於保存另一個臨時字符串。 – 2010-09-02 22:00:18

+2

但是您必須使用「隨機」文件名,因爲函數返回FALSE,如果文件chk.tmp已經存在於選中的目錄中。 – Peter 2011-08-22 10:50:08

2

安德烈亞斯...

使用安全API來獲取文件的有效權限/目錄是一個PIA很亂,只是不可靠的。 (傾我所有我的代碼贊成正是這樣做檢查,看看是否我可以寫在目錄的文件等等。)

CF,http://www.ureader.com/msg/16591730.aspx

(我有其他裁判,但我一個新用戶,只能發佈一個鏈接,只需按照上面鏈接中給出的URL)。

0

當然,所有你需要做的就是確認您的訪問權限的目錄。什麼是錯的:

function IsDirectoryWriteable(aName : String); 
var 
    FileObject : TJwSecureFileObject; 
    DesiredAccess: ACCESS_MASK; 
begin 
    DesiredAccess := FILE_GENERIC_WRITE; 
    FileObject := TJwSecureFileObject.Create(aName); 
    try 
    result := FileObject.AccessCheck(DesiredAccess); 
    finally 
    FileObject.Free; 
    end; 
end; 
2

這裏是我的版本使用GetTempFileName將試圖在目標目錄下創建一個獨特的臨時文件:

function IsDirecoryWriteable(const AName: string): Boolean; 
var 
    TempFileName: array[0..MAX_PATH] of Char; 
begin 
    { attempt to create a temp file in the directory } 
    Result := GetTempFileName(PChar(AName), '$', 0, TempFileName) <> 0; 
    if Result then 
    { clean up } 
    Result := DeleteFile(TempFileName); 
end; 
相關問題