Существует ли способ видеть, ли Excel Workbook, скажем DataSheet.xls, открыт (используемый) или нет? Я хотел бы закрыть ту Рабочую книгу, если она открыта.
Правильным способом является исследование объекта Application.Workbooks. В VBA вы бы написали:
Dim wb as Workbook
On Error Resume Next '//this is VBA way of saying "try"'
Set wb = Application.Workbooks(wbookName)
If err.Number = 9 then '//this is VBA way of saying "catch"'
'the file is not opened...'
End If
Другими словами, Workbooks - это массив (или, в терминах VBA, коллекция) всех открытых рабочих книг.
В C# работает следующий код:
static bool IsOpened(string wbook)
{
bool isOpened = true;
Excel.Application exApp;
exApp = (Excel.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");
try
{
exApp.Workbooks.get_Item(wbook);
}
catch (Exception)
{
isOpened = false;
}
return isOpened;
}
Вы, вероятно, захотите передать ссылку на Excel.Application самостоятельно.
Это не особенно приятно - мы попробуем открыть файл и проверим исключение, если оно не удастся. Я не уверен, что у вас есть другие варианты на C #.
Однако важно обрабатывать только правильное исключение: в основном мы пытаемся открыть файл без разрешения на совместное использование. Если это не удается, И мы получаем правильный тип исключения И мы получаем правильное сообщение в исключении, значит, мы знаем, что оно открыто.
// open the file with no sharing semantics (FileShare.None)
using (FileStream stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.None))
{
try
{
stream.ReadByte();
return false;
}
catch (IOException ex)
{
// catch ONLY the exception we are interested in, and check the message too
if (ex.Message != null
&& ex.Message.Contains("The process cannot access the file"));
{
return true;
}
// if the message was incorrect, this was not the IOException we were looking for. Rethrow it.
throw;
}
}
Очевидно, что такой подход является хрупким в отношении сообщения об исключении, изменяемого в будущей версии .Net. Вы можете дополнить такую функциональность тестом, который намеренно блокирует файл, а затем вызывает его, чтобы проверить, правильно ли он обнаруживает сообщение.
Попробуйте это:
try
{
Stream s = File.Open(FileName, FileMode.Open, FileAccess.Read, FileShare.None);
s.Close();
return true;
}
catch (Exception)
{
return false;
}
Это попытается открыть исключительно файл. Если файл уже открыт, возникнет исключение, и вы сможете (попытаться) закрыть его и продолжить работу.