בדיקה אם קובץ נעול ב־Windows
הנה בדיקה קטנה המיועדת ל־Windows עבור קובץ קיים: ננסה לפתוח אותו לקריאה בלעדית, ונבדיל בין הפרת שיתוף לבין כשלים אחרים. חריגה כללית מסוג IOException אינה מוכיחה שקובץ נעול; אין לסווג קובץ חסר, נתיב שגוי וכשלי קלט/פלט אחרים כולם כ״נעול״. זו בדיקה של פתיחה בלעדית, ולא מנגנון שמזהה את כל הנעילות על טווחי בתים או ברמת היישום. ראו IOException ו־FileShare.
public static bool HasSharingViolationOnExclusiveRead(FileInfo file)
{
try
{
using FileStream stream = file.Open(
FileMode.Open, FileAccess.Read, FileShare.None);
return false;
}
catch (IOException ex) when (ex.HResult == unchecked((int)0x80070020))
{
return true; // Windows ERROR_SHARING_VIOLATION (32)
}
}
מסנן החריגה מזהה את שגיאה 32 של Windows, ERROR_SHARING_VIOLATION, המיוצגת ב־.NET כ־0x80070020. חריגות אחרות, לרבות קובץ חסר וכשלי הרשאה, מועברות לקוד הקורא. התוצאה false אומרת רק שניסיון הפתיחה המסוים הזה הצליח באותו רגע. מקורות: קודי השגיאה של Windows ו־מיפוי שגיאות Win32 לחריגות ב־.NET.
משתמשים ב־FileMode.Open כדי שהבדיקה לא תיצור קובץ חסר. האפשרות OpenOrCreate שבקוד המקורי מבקשת ליצור קובץ אם הוא אינו קיים, ולכן אינה בדיקת קיום נטולת תופעות לוואי. פתיחה לקריאה בלבד גם אינה מוכיחה שכתיבה מאוחרת יותר תצליח. אם המטרה האמיתית היא ליצור את הקובץ או לכתוב בו, יש לנסות לבצע את הפעולה הרצויה ולטפל בכישלונה, במקום להסתמך על בדיקה מוקדמת. ראו FileMode.
לאחר שחרור הזרם נוצר חלון לתנאי מרוץ: תהליך אחר יכול לפתוח את הקובץ לפני הפעולה הבאה שלכם. אם דרושה גישה בלעדית לצורך העבודה עצמה, פתחו את הקובץ במצב הגישה הנדרש והשאירו את הזרם פתוח בזמן ביצוע העבודה. גם הבדיקה עצמה מבקשת לזמן קצר גישה בלעדית.
שימושי גם לזהות תהליכים שמחזיקים את הקובץ פתוח. המאמר המקורי הפנה אל דוגמת הקוד הזו מהקהילה; הקישור נשמר כאן כאסמכתה היסטורית, ולא כקוד שאומת. הכלי Sysinternals Handle של Microsoft יכול להציג מזהים פתוחים (handles) ואת התהליכים שמחזיקים בהם. נדרשות לו הרשאות מנהל, ומזהה פתוח אינו בהכרח הוכחה להתנגשות השיתוף שאתם חוקרים. אל תסגרו מזהים בכוח: Microsoft מזהירה שהדבר עלול לערער את יציבות היישומים או המערכת.