2012-02-21 37 views
12

Ok, vì vậy tôi đã tìm kiếm ở nhiều nơi để trả lời cho câu hỏi này, nhưng tôi mở cho bất kỳ liên kết nào nếu tôi bỏ sót điều gì đó hiển nhiên.Hành vi ngoại lệ liên quan đến việc mở FileStream

Tôi quan tâm đến việc tạo ra các thông báo lỗi hợp lý cho người dùng khi họ cố gắng mở một tệp cụ thể, nhưng vì lý do nào đó, chương trình không thể truy cập tệp đó. Tôi muốn phân biệt các trường hợp sau:

  • Tệp bị khóa bởi một quy trình khác mà quy trình này không thể ghi vào đó.
  • Người dùng không có đặc quyền truy cập thích hợp để ghi vào tệp (như trong, quyền người dùng của họ, như được thấy trong màn hình Thuộc tính cho tệp trong Windows explorer, không cấp quyền cho người dùng)
  • tệp yêu cầu quyền "nâng cao" để truy cập tệp.

Tôi đang sử dụng đối tượng FileStream. Tôi đã xem xét các msdn documentation for instantiating a FileStream, và nó không phải là ở tất cả rõ ràng với tôi mà ngoại lệ làm những gì cho ở trên, và làm thế nào để phân biệt giữa chúng. Tôi thừa nhận rằng kinh nghiệm của tôi với lập trình Windows bị hạn chế, vì vậy tôi có thể thiếu một cái gì đó hiển nhiên. Lời xin lỗi của tôi nếu vậy.

+1

Có sự khác biệt nào giữa 2 trường hợp cuối cùng bạn muốn kiểm tra không? Tôi sẽ tưởng tượng (mặc dù chưa được chứng minh) rằng cả hai sẽ ném một 'SecurityException', trong trường hợp đầu tiên sẽ ném một' IOException'. –

+0

@ M.Babcock: Theo một số cách, hai trường hợp cuối cùng không khác nhau. Tuy nhiên, người dùng phải (nói chung) làm những việc rất khác nhau để có quyền truy cập vào tệp. Đối với trường hợp thứ 2, họ có thể cần yêu cầu người dùng khác cấp quyền cho họ. Đối với trường hợp thứ 3, họ cần "Chạy với tư cách Quản trị viên" hoặc có thể di chuyển tệp ra khỏi thư mục "Program Files" (mặc dù tại sao nó lại ở trong đó mà tôi không biết). Tôi muốn giúp người dùng biết những gì họ cần làm để có quyền truy cập vào tệp. – skybluecodeflier

+0

Một lần nữa, tôi có thể cho thấy sự thiếu hiểu biết của tôi về hệ điều hành Windows trong bình luận trước đây của tôi- tôi mở để sửa nếu giải thích của tôi là không chính xác. – skybluecodeflier

Trả lời

5

Đây là những gì bạn có thể làm:

1) Bạn có thể kiểm tra xem bạn có quyền truy cập vào các tập tin trước cố gắng truy cập vào tập tin của bạn. Từ this SO thread, đây là phương thức sẽ trả về true nếu người dùng có quyền Write (nghĩa là khi nhấp chuột phải vào tệp -> thuộc tính -> bảo mật). Này bao gồm các quan điểm của bạn (2) cho đặc quyền truy cập không dùng đến (đừng lưu ý rằng có lẽ là một cái gì đó trở nên mạnh mẽ/lỗi chống để có được thông tin này hơn so với mã bên dưới):

public static bool HasWritePermissionOnFile(string path) 
{ 
    bool writeAllow = false; 
    bool writeDeny = false; 

    FileSecurity accessControlList = File.GetAccessControl(path); 
    if (accessControlList == null) 
    { 
     return false; 
    } 

    var accessRules = accessControlList.GetAccessRules(true, true, typeof(SecurityIdentifier)); 
    if (accessRules == null) 
    { 
     return false; 
    } 

    foreach (FileSystemAccessRule rule in accessRules) 
    { 
     if ((FileSystemRights.Write & rule.FileSystemRights) != FileSystemRights.Write) 
     { 
      continue; 
     } 

     if (rule.AccessControlType == AccessControlType.Allow) 
     { 
      writeAllow = true; 
     } 
     else if (rule.AccessControlType == AccessControlType.Deny) 
     { 
      writeDeny = true; 
     } 
    } 

    return writeAllow && !writeDeny; 
} 

2) Đừng cố gắng để nhanh chóng FileStream của bạn , và ngoại lệ bắt:

try 
{ 
    string file = "..."; 
    bool hasWritePermission = HasWritePermissionOnFile(file); 
    using (FileStream fs = new FileStream(file, FileMode.Open)) 
    { 
    } 
} 
catch (UnauthorizedAccessException ex) 
{ 
    // Insert some logic here 
} 
catch (FileNotFoundException ex) 
{ 
    // Insert some logic here 
} 
catch (IOException ex) 
{ 
    // Insert some logic here 
} 

Trong trường hợp của bạn (3) (tập tin đòi hỏi độ cao), UnauthorizedAccessException được ném.

Trong trường hợp của bạn (1) (tệp bị khóa bởi một quy trình khác), IOException bị ném. Sau đó, bạn có thể kiểm tra HRESULT của ngoại lệ để biết thêm chi tiết:

catch (IOException ex) 
{ 
    // Gets the HRESULT 
    int hresult = Marshal.GetHRForException(ex); 

    // See http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx 
    // for system error code 
    switch (hresult & 0x0000FFFF) 
    { 
     case 32: //ERROR_SHARING_VIOLATION 
      Console.WriteLine("File is in use by another process"); 
      break; 
    } 
} 

Bây giờ bạn sẽ có thể phân biệt 3 trường hợp sử dụng của mình.

+0

Hmm. Điều này có ý nghĩa - tôi sẽ kiểm tra điều này. Mặc dù tôi không nghĩ rằng tôi có thể tin tưởng chỉ trong giải pháp 1 mà bạn đã chỉ định ở đây, vì khả năng của điều kiện chủng tộc. Đó là, a) Quá trình của tôi kiểm tra xem nó có thể truy cập tệp hay không, b) một số tiến trình khác sẽ mở tệp (hoặc thay đổi quyền, v.v), c) quy trình của tôi cố mở tệp và không thành công/bị hỏng. – skybluecodeflier

+0

Thực ra chỉ có thể có điều kiện chủng tộc cho trường hợp (2) (các đặc quyền truy cập không thích hợp) nếu người dùng mất quyền giữa kiểm tra 'HasWritePermissionOnFile' và lệnh gọi' FileStream' mới. Nếu nó xảy ra, một ngoại lệ 'UnauthorizedAccessException' sẽ bị ném ra, vì vậy bạn vẫn có thể biết rằng" có một vấn đề truy cập ". Sau đó bạn có thể gọi 'HasWritePermissionOnFile' trong khối 'catch (UnauthorizedAccessException)' để đảm bảo ngoại lệ khi được ném vì vấn đề độ cao. – ken2k

+0

Ha, nó cảm thấy như thế sẽ chỉ di chuyển điều kiện cuộc đua vào khối catch cho UnauthorizedAccessException. Mặc dù tôi không chắc chắn nếu nó có thể tránh được điều đó. Hay là có? Nó chắc chắn hoạt động trong điều kiện bình thường. Cảm ơn! – skybluecodeflier

Các vấn đề liên quan